 Please help me welcome Uncle Bob to the stage. Two things about going last is that you get to correct everybody who went before you. We're said that. Oak cucumber is a nice, lightweight little package, does a little regular expression analysis, calls a little function and it's in and out very, very fast. Cucumber is not slow. Somebody said that it would be nice if our community were diverse. To be expressing itself more than others. Facial hair. Yes, facial hair. Let me just put it this way. If you would like to attract a more diverse crowd, specifically the softer among us, dropping the F-bomb might be something you'd like to avoid in public speaking. At least once. Totally fucking disagreeing. Competition. I know with the shitty developers. Not the same thing with the managers. And what is this thing about Vim? Who's doing Vim here? Last comment on that. This house, who likes the show, identify with the character of house? So, house is a doctor. House is the quintessential asshole. If you were to... Well, I'm not going to go there either. Just imagine that this is the most irascible, negative, horrible, ducky guy you can imagine. He explained his behavior a couple of years ago in one of the episodes. He said, I am so good, they can't get rid of me. So I am free to act any way I want. That's how he tests his self-worth. He tests his self-worth by making himself so repugnant and then watching as they can't fire him because he's just so good. House is a loser. Keep that in mind. Those of you who think, I can break all the rules I want. I can come in anytime I want. I can go home anytime I want. I can code drunk. No, I'm sorry. House is a loser. By the way, I came up with a rule a very long time ago about alcohol encoding. Same rule that applies to pilots. Same with this talk. Oh, by the way, I should probably do a science lecture first. Who has been tracking the e-cat thing? Fascinating, right? You've read about it. So this is probably a hoax. And if I had to wager right now, I'd say I had nine tenths of hoax, one tenth is not a hoax. But the one tenth has gotten me titillated. By the way, that's not one of the seven words that George Carlin talked about. The idea here is there's this guy in Italy. His name is Andrea Rossi. And for several years now, he's been saying that he can generate power by running hot hydrogen over nickel. The hydrogen atoms will fuse with the nickel to produce copper and release energy. And the energy that comes out is in the form of gamma rays and heat. And the gamma rays can be absorbed to produce more heat. But there's no other radiation that comes out. No neutrons come out, no electrons come out. It's not radioactive. It's just this interesting nuclear reaction. And of course, most of the scientists remember the old Fleischmann and Pond these years and the horrible fiasco of the cold fusion stuff in 1989 and everybody's going... And he is saying, nope, I can do it and I can prove it. On October 28th, he got a group of professors together. He got somebody who's buying his generator. He built a megawatt generator. He got a bunch of reporters around and he fired up this generator and he managed to boil many gallons of water, 400 kilowatts worth of water, 400 kilowatt hours worth of water. I don't remember. A lot of water, he boiled it. And then he turned the machine off and the customer immediately paid for the device apparently. And this is still all shrouded in lots of secrecy and there's this catalyst that he talks about that he won't tell us about and all this interesting stuff. Probably it's a hoax. It's probably too good to be true. Take a look at this one, it's interesting. Maybe it's a hoax, maybe it's not. Maybe it's too good to be true. I look at most things that are too good to be true and think, well, they're too good to be true but then I look at my wife. That's how you get diversity into the group. What you're looking at here is the top level structure of a Rails app that I wrote a long time ago. Look at the directories here. What do you see? Well, you see controllers because you'd expect to see controllers in a Rails app, wouldn't you? And you see models and you see views and a few other things like helpers and utility and you can go into the specs over here because of course it's test-driven. Who's doing test-driven development? We're going to have a talk. You can look in the tests over here. There's controller tests and model tests and view tests, blah, blah, blah, blah, blah. Okay. What do you see? If I were to show you this and I did not tell you that it was a Rails app, would you be able to recognize that it is in fact a Rails app? It looks like a Rails app. Oh, there might be something else. Maybe there's a few other apps that have that kind of directory structure but it's a Rails app. So now my question to you is why should the top level directory structure take that information to you? What does this application do? There's no clue here. Substitute is the name of the project. Well that's very helpful. Apparently the customer's name is Angela. Maybe. But nothing at the top level of this application, the most visible level, the level that everybody goes to first, nothing here, talks about what this application does. It's basically recognizable as a Rails app. So apparently the most important thing about this application is the framework upon which it is built and the rest of it we don't care so much. The web is the detail. The web is not particularly important to your application. The web is simply the way that your application gets information from the user and delivers information back to the user. The web is a pipe. It is nothing more than a pipe. It is not the central abstraction of your application. It is not the grand over-arching thing that makes your application the application it is. The web is just a dumb detail. It dominates our code. We can look at an application that is a web application and we know that it is a web application because of that controller's directory. No other type of application would have a controller's directory at the top level, especially if there were models and views around it. We'll talk about Model View Controller later and the horrible bastardization that's happened there. Take a look at this top level drawing of a library. You might have the word library on this slide. You could look at this and think, well, there's some big entrance here and there's some offices. Looks like there's a desk where people might come in and register things. Looks like there's some bookshelves. By God, I think that's a library. The top level structure of the library would show you that it was a library or how about a church? Is it even slightly doubtful that that's a church? You've got the big entrance gallery. You've got all the pews. You can see the altar. You can see the fellowship rooms. This is a church. The top level architecture of this structure screams its intent at you. But the top level architecture of my little rails application did not scream its intent at you. It screamed the framework at you. It screamed rails at you. This is good for DHH, not so good for you. Why does this happen? Why do we create architectures that reflect the framework that reflect the delivery mechanism and don't reflect the application? Aren't we building an application? Doesn't that application have some intent? Isn't architecture about intent? Clearly it is from the building point of view. Isn't it also true of the... Oh, hello. This is my wife, Tom. Excuse me. I'll turn my phone off. Where was I? Thank you. Isn't the architecture of an application all about its intent? And why shouldn't we see that intent at the top level of our code? The year was 1993. This guy, his name is Evar Jakobson, wrote a book called Object-Oriented Software Engineering. A youth case-driven approach. Now, what was going on in 1993? There was no web. The web had not yet been born, or maybe it had. It was actually born. I can't remember what year it was born in. Some guy wrote a web page once and then spread like wildfire. But there was no web at the time. We were all doing C++ or C or some horrible thing like that. And we were doing thick client applications. And here comes this guy. And he writes this book, and it's a fascinating book, and he solves the architectural problem. This book is not the first guy to do it. It won't be the last. But in this book, he talks about how to get the intent of the application at the top level to be the central abstraction that we build upon. He called it a use case-driven approach. What's a use case? Well, that's a use case. Nothing really terrific about it. I mean, you kind of give it the name, create order. You talk a little bit about the data that's being passed into the create order use case. So I'm going to need a customer ID. I'm going to need some customer contact info, maybe a shipment that met destination, a few other things. You talk a little bit about how this system is going to respond when it gets this request. The order clerk issues a create order command with the above data. The system validates all the data, blah, blah, blah, blah. It's just a set of simple statements that describe how the system responds when the user does this little thing. You don't have some alternate, exceptional courses in it, just ways to deal with errors and so on. And Yarkinsen went through a fair number of pages in his book just to describe what that was. Who's done any use cases before? Does anybody remember that? Oh, yeah, lots of you do. What's the difference between a use case and a user's story? Yes, the word story and the word case and an R. A use case and a user's story are roughly the same thing, although the user's story begins as something very small and it evolves into the use case. We gradually take the user's story, which usually begins as a sentence or so, and then over the course of the project we add a few more sentences to it. We turn it into something that looks like this, typically through acceptance tests, and then we implement the use case. What Yarkinsen said was, look, this is the central abstraction of your application, so it ought to be an object. He called it a control object, I will call it an interactor object. I will call it that because I don't want you to be used with model view controller. So, use control objects or my interactor objects are objects that implement a use case. Interactors have application-specific business rules. What does it mean to have application-specific business rules? They can't be in a framework. They can't be in a framework, clearly. There are going to have to be business rules that you are putting in there for the purpose of the application. What would an application non-specific business rule be? A business rule that was not specific to the application. Well, you might have them. You might have, pardon me, entities. Entities which represent business objects. Business objects that could span more than one application. And in every application that the business object might appear, it would encapsulate the same rules. And so you put business, excuse me, application agnostic business rules in your entities. You put application-specific business rules in your interactors. And notice there is a dependency between them. The interactor knows about the entity. Now, what would an entity be? Well, maybe something like an order, or a customer, or Rails programmers. What would you do with something like this? What would you call it? What directory would it go into? Would it go into the model directory? No, it wouldn't. It would not go into the model directory. What goes into the model directory? Stuff that derives from... What? Never mind. What is the stuff that would derive from active record? The models? All the models derive from active record? Well, these things I don't want derive from active record. These entity things are decoupled from the database. So are the interactors. They don't know anything about the database. They don't know anything about the delivery mechanism. They are agnostic of all these things. These are the business rules. Application specific business rules and the interactors application. Agnostic business rules and the entities kept nicely isolated from the rest of the application. How do we get the data in and out of the interactors and the entities? And Jacobson had an answer for that, too. He said, well, we'll just use boundaries. What are boundaries? Well, boundaries are essentially interfaces. They're protocols or interfaces. In Java, we would make them interfaces. In .NET, we would make them interfaces. In Ruby, we wouldn't make them anything at all. But they would still be there, conceptually, hiding behind the scenes. A set of methods invoked by the interactors or by the people on the other side of the boundary in order to get certain things done. And with that in place, we have the three objects in Jacobson's model. And I wrote a whole book on this. It's a fascinating book. But those are the three central parts of Jacobson's model. We have a whole bunch of interactors, which each one represents a use case. We have a whole bunch of entities. Each one represents a business object. All of the business rules go in here. What about validation? Stuff like that has to run on the browser. Stuff in JavaScript. Are those business rules? Can they run in those objects? They're not going to, right? They're going to run in a different computer, probably the user's machine. They're going to run in a different language, JavaScript. They're going to be somewhere off the side. Does that mean they're not part of this model? No, they're still part of this model. It's just that they're running in a different machine. They're written in a different language, but they are still just as decoupled from everything as everything else is. They try to keep all these business rules decoupled. Here's the whole picture. We have some delivery mechanism, which talks to the user. By the way, I've got some lasers here. You've got to have lasers. Don't let this go in your eyes. This is a fairly bright one, and I've got a red one. And then I've got this one. You can't see that. Over here, you can kind of see it. How about that? No. Not so good there. This appears there, virtually. I wonder if these are going to play nice with us. Ooh, that's nice and bright. How about that one? That's even brighter. How about this one? That's pretty bright. How about that one? Look at that. They're all bright. What color is this laser? Ah! Wow. Can you see that? Wow. Isn't that cool? What color is this laser? It's an ultraviolet laser. The little tiny spillover into the violet. Not much, but most of the energy coming out of here is ultraviolet. How cool is that? I have a UV laser. I don't know what the heck I'm going to do with it. All I can do with it is color my glasses black. So, I'll get my... Oh, how about the red one? We got a user here. A user's going to talk to our application through the delivery mechanism. What's the delivery mechanism? I don't care. I don't care what the delivery mechanism is. It might be the lab. It might be the client. It might be a console lab. It might be a bunch of web services. I don't care. And I want to keep it that way. I do not want to care what the delivery mechanism is. I'm going to have the delivery mechanism talk to me through a boundary interface, which my interactors will derive from. My interactors will then catch the data coming from the user through the delivery mechanism. My interactor will impose application-specific business rules. It will go to my entities, which encapsulate application-nonspecific business rules. It will get a whole bunch of interesting work done. Then it will gather a whole bunch of data back, pass it back through the boundary object, which the delivery mechanism implements, and hand it back to the user. Notice the direction of the dependencies right here. The delivery mechanism depends on the boundaries. Nothing to the right of the delivery mechanism depends on the delivery mechanism. There are no dependencies landing on the delivery mechanism, which means that I can take this whole thing here and put it in a gem, put it in a DOL if you're a .NET programmer, put it in a JAR file if you're a Java programmer. I can take that and I can put it in a nice little place, completely decoupled from everything else. I can make the delivery mechanism a plug-in to my application. I think of what that would mean to you. It's the delivery mechanism where a plug-in to your application. That would mean that you would not have to plug it in. When would you not want to plug in the delivery mechanism? When you're running tasks. Let's say that's cucumber. That delivery mechanism right there. Let's say that's cucumber. How fast do you think that's going? Oh, it's going about as fast as it can because there's no web system in there. There's no web server in there. There's no HTML going around this whole thing. All the JavaScript is happening somewhere else. There's no web server or anything like it here. There's cucumber there. You could get your tasks to go. Very, very fast indeed. So let's follow it through. User decides he's going to interact with the system. So the user has some great idea, walks up to the system, types a bunch of stuff on the keyboard. This is a web environment maybe. The delivery mechanism somehow captures what the user wants. Maybe on a form, maybe on some kind of window. Who cares? Maybe it's on a command line. I don't care. The delivery mechanism eventually gathers all the data that it needs and creates a request model. What is this thing? It's a data structure. It has no methods. It's just a chunk of simple data. Nothing in this data structure even looks like it comes from the web. You would not be able to look at that data structure and say, oh, this must have come from the web. No session IDs, none of that other stuff. Just a simple bunch of data that represents the request that goes through the boundary, gets to the interactor. Now the interactor has it. And it's still just a dumb data structure. But the interactor knows what to do with it. It gets all the interesting information it wants to out of a request model. And then it's going to have to execute. What does it do? It talks to the entity objects. They talk. There's a nice little interaction here where the interactor... By the way, that's why we call it an interactor. It interacts with the entities. It also interacts with the user. It's the thing that kind of ties the whole use case together. So the interactor is popping out to the entities, going, oh, do this, do that, do this. Finally, the interactor is done. It has created a result model. What is that result model? It's a data structure. There's nothing else in it. No methods, no nothing. Just a chunk of dumb data. Nothing in it looks like it's for the web. Just a chunk of nice bunch of data which it then takes, passes through the boundary, and allows the delivery mechanism to figure out how to present that to the user. So when you write a cucumber test over here, that cucumber test is creating the data structure. It's invoking the appropriate interactor by going through the boundary interface. All the magic happens on this side. All the business rules get invoked. A request model gets created. It comes back across through the delivery mechanism, back into cucumber. And you can now test all the business rules and all the use cases of your application. And everything your application does on the far side of the delivery mechanism without having the delivery mechanism there. Why is this important? Why should we want to do this? Well, first of all, if you were to look at this part of the code, what do you think you'd be seeing? What would the names of those directories be? Interactors, entries, and boundaries. Very good, thank you. Someone with a brain is out here. Good. Interactors, entities, and boundaries. Excellent. And if you were to go into the interactors, what do you think you would see in there? And what would they be named? Create order. Now that's interesting, isn't it? Create order. Add item to order. Submit order. Delete order. Deliver order. They would have the names of the use cases. So at the very top level of the application, you would see a structure that started to look like the intent of the application. What about model view control? Isn't that kind of the architecture of the web? Where did this come from? So this guy, oh, I need to change the slide. Excuse me a second. This dude, who knows what his name is? I did not mean to put that between his eyes. Who is that guy? Trick V. It's Trick V. Trick V what? Brian. Is that something wrong? Rene's Cali. I can't say it either, but you probably can. Trick V Rene's Cali, who is the inventor of model view controller. He invented it in 1979. If I remember correctly. This may be the first named design pattern model view controller. And model view controller was a very interesting idea, very simple idea. We're going to have some model. That model is a model of some entity in the business. It's where we put the business rules. And the controller gathers input from the user and the view displays output to the user. That was the basics of model view controller. There was an observer relationship here, which is why I drew it with the double error. So the view observes the model, whenever the model changes, the view automatically represents it. This was written in what language? Small talk. Small talk? If there were a screen up in small talk, which had a whole bunch of stuff on it, how many views do you think there would be? If you had 100 things on the screen, there'd be 100 views. Because this design pattern was meant to be used in the small. Every little widget on the screen had a controller and a model and a view. Every little rectangle, every little circle, every little thing on the screen had its own little model controller and view. It was a mechanism that was meant to be used in the small, but it would replicate over and over and over again. We have changed that rather significantly. We have in the web world decided that the entire screen is a view. Well, that was not the intent here. How many models does the view know? Hundreds. Hundreds? Yeah, we've kept the model idea, haven't we? But now the view. Actually, I have a picture of this, so I should use the picture. Anybody recognize that picture? All our business objects are over here. They're in the models, right? We've got a bunch of controllers. Controllers are dancing around, trying to control all the models. I've got all this data from the web. I'm going to unpack all that stuff from the web. Now I need to tell those business objects what to do. And the business objects are doing stuff. And then the controller has to say, okay, what did they do? And it's got to gather all that stuff together and pass it to the view. And the view is sitting there written in some horrible, bastardized language that can't figure out whether it's HTML or Ruby or Cotnos what else. And it's reaching into the business objects. Your views. Your views should know nothing of the business objects. Your views should be utterly divorced from the business objects. They should not know that the business objects exist. Your controllers should not know about the business objects. They should be completely divorced of that. The communications pathway between the controllers and the views are those interesting little data structures. Imagine a controller that gets an HTTP request. Here's our HTTP request here. Loaded with data. By the way, just I have to say this. The web is probably the worst idea that's happened to our industry in the last 40 years for delivering data to people. It may be the best one we've got, but it's pretty putrid. There's going to be some better way to do this. Now what? Anybody ever do any 3270 programming? Did you recognize this? This is just 3270 programming and I'm not going to say on steroids, more like on Strickline. It's 3270 programming poisoned with all kinds of karate. How many languages do you have to know to write a web application? You've got to know... Well, there's some programming language, but that's incidental. Ruby, who cares? Java, whatever. Then you've got to know HTML and CSS and JavaScript and Sazzle and Dazzle and you know, the guy over here is saying let's build communities by leveling people up. Leveling them up! I mean, what we're going to do is hand them up. Let's hammer. Good. Now you've got that hammer? Now here's Noah. What's that with you? Now I've got a big barrel of water you've got to hold on your head. We are not helping our cause with this truly terrible mechanism that we have adopted, in any case. Here comes the HTTP request. It comes into the web server through all the routing stuff who cares about the routing stuff just decoding a bunch of slashes and names who we could call it REST, I suppose. Anyway, here comes the controller. The controller gets executed by something in the web server that does all that and the controller now unpacks all the data from the form or whatever that came in and it puts it in the request model. It doesn't talk to any business objects. It just loads up a nice simple little data structure and then it's done. It doesn't have anything left to do. It's just one last thing. It kicks it through some interface to an interactor. An interactor does whatever it's going to do and eventually creates a response model down here and a response model eventually gets passed through a boundary to a presenter. Now the presenter's job, by the way some of you know this design pattern models you presented. The presenter's job is to take this delivery agnostic model this model of all the results that has no idea how it's getting represented. And the job of the presenter is to turn it into another data structure called the view model which has been webified. How do you webify something? Fill it full of gunk. For example, if you're going to display the data in a grid you organize the data in some grid structure. Not one that knows about the web. Just one that knows that it's a grid. There are on the screen there may be menus some of which should be gray some of which should not. There should be booleans in here that tell you whether those menu items are gray or not. There may be buttons on the screen that have names and the names of the buttons may change depending on the state of the system. Those names should be in the view model so that in the end the view is this truly stupid piece of code. You pass it the view model and all the view does is go put that there, put that there, put that there, put that there. Okay, I'm done. So stupid you don't need to test it with unit tests. You don't need to write unit tests for the dumb little things that the view has to do. That's my way I like to deal with with testing views. I just don't. I make sure that there's no point. There's just no point in testing this gunk in here. Alright, some acceptance tests out at the high level. I do write a few of them and they will go through the GUI. I'm not going to test all of this stuff by talking down here. I'm going to go through a nice thick interface, a nice fast interface if I'm testing business rules. Here's the whole engine lock without the entities. I left the entities off. We've got the interactors. The interactors talk to the entities. We've got the nice little boundary interfaces. The interactors use the request models and create the response models. The presenter uses the response model turns it into a view model. The controller creates the request models. And the whole thing into the line can be put into a gem. And the stuff on the left of the line can be put into a gem. And you can plug them in if you want to. You don't have to. Now you're thinking yeah, but I've got to get stuff done. Well yeah, you do have to get stuff done. So, tell me what your day is like. Is your day first of all, how long does it take to run your tests? Too long. Too long? Good answer. How long? Four and a half minutes. Four and a half minutes from beginning to end. That's nice. How many tests are there? Thousands. Four and a half minutes, thousands. That's a good time. Who's got one longer? Hour and a half. Or five hundred and fifty? That's not good. In the bag? What? Twenty-eight minutes. How many tests? Two. Too many. Now that's an interesting psychological response, isn't it? Twenty-eight minutes. Why? Because there are too many tests. And if there are too many tests, what would that cause you to do? We need to get rid of the tabs. They're taking too long to execute. This is the symptom that occurs. You know, this all testing thing doesn't work. I mean, you know how long it takes us to run our tests. It just slows us down like, you know, if we could just code and ship it. Is this your view of the database? I don't know who's going to solve the problem. We'll just let the database handle it. The database will solve all problems because it is the all-knowing, all-absorbing creation of God knows what. Unfortunately, we see the database in the center of many applications. The database is not the center of your application. It is not the center of any application. What is a database? The database is a detail. The database is a detail. Something that you don't want to know about. Something off in the corner that somehow stores things. And you guys don't want to know how it stores things. I want the things that it stores. Bratz Petudi about the relational model that doesn't interest me at this moment in time. Other people it does. That's fine, but I'm trying to write an application here. And the relational model means nothing to me. I want those objects. I want those entities. I want those things out of the database. And why do I have to know that this thing is there? And why do I have to follow all its stupid rules? I don't want to know that the database is there. Now I want there to be one. I want that we have one, but I don't want it in the middle. I do not want the database dominating the shape of my code. I do not want the database telling me what my objects look like. I want some way to abstract the database. Get it out of the way. Turn it into a detail. I want to defer the decision about the database. What if tractors are entities and I use the word gateway here? I have them use this thing called the entity gateway. Which is just an interface, which has a bunch of methods in it. There's probably a bunch of these things. Maybe there's an order gateway and a customer gateway and an item gateway. Who knows? A bunch of them. And I can invoke methods on them like get entity or put entity. Get order. Put order. By order. Put a bunch of nice little methods on them. And then I could implement that below some interesting line. I like to draw these lines. You know what architecture really is? It's the art of drawing lines. With the interesting rule that once you have drawn the lines all the dependencies that cross that line go in the same direction. That's what architecture is. Find some place to draw a line and then make sure that every dependency that crosses that line goes in the same direction. Once you have that you have a gem. Once you have that you've got a compound. Once you've done that you have plug-ins. And what I want to do is I want to make the database a plug-in to the application. If the database is a plug-in to the application then the database is still there but I don't need it. I don't have to have it when I'm running my test. The other time for that matter I don't have to have it. Except in production I have to have it. I have to have something. Something below this line that does what I need it to do. And I don't care how it does it. Does it have to be relational? Don't care. Don't care what if it was a battery backed up piece of RAM? Don't care. It's just down there. Saves all the data. That's all I care about. It's down there and I can decouple all my business rules from the database and run my tests without a delivery mechanism without a database where would active record be in all of this? Delivery mechanism of rails but what was one of the talks today was who's done non-web applications in Ruby? Well if your architecture is any good everybody does because your whole architecture your whole application should be non-web Ruby. So some nice little data structures and hands it off to some plugins that do happen to know about the database. Somebody mentioned, well you know these could be services. Okay. If you want to do service oriented architecture with this stuff and that stuff, that's fine with me. I think I'd probably rather not but okay. So let me tell you a story. I am one of the authors and committers on a project called Fitness who's used it. Feel of you good. It's a wiki based testing tool and has a front page that looks like in case you want. No. It's a wiki. Who invented wikis? Excellent. Who's Ward Cunningham? Ward's actually a very interesting fellow. He did invent wikis. He also invented a number of other things. He's the guy that called Eric Gamma on the phone and said, you know, you should write a book about design facts. He's the guy who invented CRC cards. Nobody knows what they are. He's the guy who did most of the early work in test room development and agile methods of stream programming. He's been around for a very, very long time. Very interesting guy. He sits in the back of the room. He has a whole bunch of ideas. Other people run with his ideas and make money. Okay. I went to a conference in 2001. It was OOPSLA. Anybody ever been doing OOPSLA? Yeah. Anybody going to go to one? No. It's not there anymore. So, I went to this OOPSLA. I think it was important. And Ward was there. And Ward said, Bob, come here. I want to show you something. And he sat me down on some stairs. And he pulled up on his laptop an image of the HP35 user card. Okay. Who knows what an HP35 is? A few of you. Good. Yeah. Okay. Very early, full function calculator. Not four function. Full function. We had leather pouches. We put them on our hips. Cost us $350 in 1975 dollars, right? These were significant machines. They could do arch tangents. You could take an HP35 and throw it against the wall. It would keep right on working. Nice little LED display. Reverse polish. HP calculator. Reverse polish. No parenthesis. So, on the screen is the card that came with it. It showed you how to use it. They had put the entire user guide on a card. Which tells you how smart this machine was. And there it is on the screen. I said, Ward, that's an HP35 user card. He says, yeah, now look what I can do with it. He pushed a button on his keyboard. And the cells of the card turned green. And I thought, test wasn't important. You used the user guide and turned it into the acceptance test. He says, yes. And I said, well, how'd you do that? He said, I wrote this thing called FIT. Which stands for Framework for Integration Testing. I said, that's really cool. How does it work? Well, it looks at the HTML of the document there. And it turns that into a bunch of test calls. And then you write these fixtures and blah, blah, blah, blah. And it became very clear what this was about. And I said, you know, Ward, there's got to be some good way to produce this HTML. And he said, well, I just used Microsoft Word for that. And it occurred to me, okay, Word has just invented FIT. And there's something else that Ward had invented called a wiki. I bet these two could be brought together. And that's what fitness is. Fitness is a wiki that coordinates with FIT. I went home. I said, we're going to write this wiki. We're going to call it fitness. We're going to conquer the world with this thing. And I got my programmers at the time. I had a staff of programmers. I said, all right, guys, we're going to write this thing. And we all sat down and we started talking. And we realized right away that it's a wiki. And a wiki is going to have to store something. What's it going to store? What do wiki store? Web wiki. There's no other kind of wiki. They store pages. Wiki pages. So we said, well, we're going to need some place to store the wiki pages. We're going to need a database. And we thought, well, all right, this is 2001. What kind of database would serve and probably MySQL would do. So we decided, MySQL. And we said, all right, well, let's go get MySQL and crank it up. And one of us said, well, we don't really have to do that yet. Because there's all of this translation that has to be done. What a wiki does is it takes this really horrible text and it turns it into HTML. Which is really horrible text. I'm not sure what the point is anymore. But anyway, it takes all of this wiki text and turns it into HTML. We could write that whole translation. Which we did. It took us about three months. We did a whole bunch of work. Wrote all this code that translated wiki text into HTML. And we needed a placeholder for the wiki page. So we created the mock wiki page. This is not a true mock. We didn't understand what the word mock meant in 2001. So this was a kind of replacement for the wiki page. It did have the two HTML method. So you could take this wiki page mock up. And you could convert it to HTML. And you could also save it. But the save function didn't do anything. And for three months, we were working away. And we got all that to work. And then we thought, well, pretty soon now we're going to have to have more than one page because we have to make links between pages. So now is the time for the database. And then we thought, wait, we don't really have to do that. What we could do instead is just hold all of the wiki pages in memory. I mean, we don't have to store them yet. So we'll just create another mock called vfids on there and our save methods on there. And we'll just use a hash table and store it all in memory because after all, we're not going to do millions upon millions of things yet. We're still writing the application. And so we started to write the application. We spent a year writing the fitness application. We got the whole thing done. We got the whole wiki functionality going. We had tests running. We couldn't save any of it. It wasn't particularly useful. We couldn't save anything, but it all worked. And we could show it to people. Look, it works. But you can see, you can make sure. So that was kind of cool. Eventually, though, we started to write tests that forced us to have persistence. You know, the kind of test that says you're going to be able to save a page, tear down the system, reboot the system and the test that page is still going to be there. And we thought, all right, now it's time for the database. And Michael Feathers was there. And he said, you know, you don't really need the database yet. I mean, you're just still just writing tests. So you could fake a database. You could even fake persistence by writing that hash table out to a bunch of flyfogs. And he sat down. And in a day, he wrote this thing called File System Page. He handed it to us. Here, use this. And we did. And now we could write all of our persistence-level tests. So we spent another couple of months doing all the persistence-based stuff, writing tests, getting... Because the whole thing was test-driven, right? Test, test, test, test, test. All these tests passed. We started using fitness and courses and teaching people about it. We started using it for our own purposes. We still thought we had a database to do. And then it occurred to us. One day, we had taken that architectural decision about the database. We had deferred it and deferred it. We deferred it right off the edge of the planet. We never put the database. It was fast enough the way it was. What do we need a database for? That had some very interesting, unintended consequences. Since all the Wiki pages were stored in flat files, you could check them into source code control. That was never part of the plan, but it was there just happening. We kind of looked at each other and thought, cool, never actually had to use the database. But that's not the end of the story. About a year later, one of our customers came to us and said, we really need these pages in a database. I said, well, why? He said, well, our corporation has a policy that all software assets must be in the database. Now, I don't know who makes up these rules. Dumb rules, but okay, you can't fight city hall. We went to him and said, look, this is what our architecture looks like. There it is right there. All you need to do is create another derivative called MySQL page, or Oracle page, or whatever the hell you want to call it. Which he did. He went away and did that. He came back a day later with the whole thing working in MySQL. Took him a day. He gave that card code to us. We used to ship it with fitness as a plug-in, but nobody ever used it, so we stopped. There's an interesting case of the database. This thing that's so incredibly important, and yet we took that decision and we just deferred it right off the end of the world, and then when somebody needed it, we shimmed it in in a day. Because our architecture had done something right. What is the hallmark of a really good architecture? A good architecture allows major decisions to be deferred. You don't create an architecture and say this architecture is based on rails. That's the error right there. You've lost the game as soon as you say that. If the first thing you type is rails, you've lost the argument. You've gone down the wrong path. Your architecture is not based on rails. Rails is a detail. Rails is incidental. You can make that decision later. Get your use cases working. Get your entities working. Fiddled around with them. Get cucumber test passing. If you need to show the customers and stuff working, put together a dumb little plug-in with rails and show it to them. It's probably not the one you're actually going to use, but rails is really fast. Throw together some shit. That would be the plug-in to your application so you can do this on the web and then you can figure out later how you really want to do it on the web or even if you want to do it on the web. A good architecture maximizes the number of decisions not made as the purpose of an architecture to prevent you from making decisions. It is to keep your options open for as long as those options can be open. Do not decide up front what road you're going to take. What are those options open for as long as you can? I've asked all these questions, but I do want to come back to one. How many of you are doing TDD? Oh, it's more hands this time. I started doing the talk. Yes, started doing the talk. Good. And those of you who are doing TDD, are you writing your tests first? So let me be very clear writing unit tests after the fact is not test-driven development. It has nothing to do with test-driven development. Writing tests after the fact is a waste of time. It is something you are doing to check off some little procedural thing that somebody told you you had to do, but you are not taking things seriously if you are not writing your tests first. Why? Why do you have to write your tests first? Okay, that's good, Angela. If you are a test-driven developer, that makes perfect sense. If you are not a test-driven developer, it sounds insane. So why must you write your tests first? So you know when you are done. So you know when you are done. Another good example, okay, but not the one I am going for. How do you know that those tests cover everything? Let me put this different. Why do we have a suite of tests? What is the purpose of that? That is the exact reason. A suite of tests is not there to satisfy a QA group. A suite of tests is not there to prove to other people that our code works. The suite of tests is there so that we can refactor. So that when we bring code up on our screen, we are not afraid of it. How many of you are afraid of your code? Afraid what will happen to you if you touch it? Code comes up on the screen. Your next thought is, I am not touching it. I want you to think how deeply dysfunctional it is for you to be afraid of the thing that you created. For you to be submitting to its will instead of it submitting to use. You are no longer the sculptor. You are no longer the artist. Now you are dominated by your own creation because you are afraid to touch it. And if you are afraid to touch it, then it will rot. And you have seen that rot and you know what that rot is like. And that rot will slow you down and it will slow the whole team down. It will drag you into a filthy morass and you will blame management. When the fault is actually your own because you did not keep this beast under control. How do you keep the beast under control? You need a suite of tests You need a suite of tests you trust with your life. You must never look at that suite of tests and think you know, I don't think I really tested everything as soon as you think that you have lost it. Because now you are afraid of your code. The reason we write our test first is so that we know that every line of code we wrote was because of a failing test that we wrote. So that we know that every single decision we made is tested. So that then we can pull up that code on our screen and say, oh my god that looks like a mess and clean it without any fear. But it is not enough to write your test first. Your tests have to be fast. Because if they are not fast you start throwing them away. And if you start throwing them away then the exact same symptom comes to you. It chooses control of your code. It dominates you, you don't dominate it. How do you keep your tests fast? By decoupling everything that's slow. Which by the way we should have been doing anyway. The delivery mechanism, the database, the services, all that slow decouple it, decouple it, decouple it so you can write your tests and have them execute like that. You know I think I'm getting tired. I would like to thank you all for your attention. Are there any questions before I run away? Okay you got one, hold that because his hand was up first. Where can we find the gem with us? It's between your ears son. Okay now it's you. Are there any examples of a software application that also uses Rails in the way that you're talking about? I haven't seen it yet. Who's got one? Yeah I do have one. I can't show it to you. Sorry. Who's got one? It's just like the cold fusion thing we're not sure about. Do you get managed to tie all these things together somehow? The Rails code that I have seen without exception and that's just what I have seen does not follow this pattern. The reason I came up with this talk is that I have been consulting at a number of Rails places looking at the code and something deeply bothered me about this code. I could not put my finger on it until it occurred to me one day. What am I seeing at the top level here? What really triggered it for me was when I was pairing with a guy and we were pairing on a little bit of code and I said well let's run the tests and my shoulders dropped. Run the tests? Okay and then it was a minute it was a minute before we got the answer. Now I'm used to, you know, I used to button you to a little thing and it was a minute. So why is it a minute? Oh well when you're on the test you've got to start up Rails and that's when it started to hit me. Wait a minute. All these Rails programmers do everything through it. It's just the first thing they think of and then I started thinking wait, that sounds familiar. And it took me all the way back to 1973 and I read Jakobson's book back then and thought excuse me, 93. And I thought yeah, that's the thing. I call this talk architecture the lost years. Why do I call it the lost years? Because from 1993 until now we have forgotten this thing and we were on the verge of learning this thing that Jakobson had given us this architectural idea. And you know what drove it out of our brains? The web. The web. It was the web. The web was so all consuming all so exciting so God help us whatever it was and it drove all those ideas out of our brains for ten years and they're just now starting to come back. Okay you had a question. This is a joke about how I found the job because it was so unreliable that we can't connect to it. The second one is is this slide deck somewhere where we can find it? Is it on one of these websites? Please speak up. I'll answer the question. I'll repeat the question. He was to know if this slide deck is on any of those websites the answer to that is no. But it could be. And is there a website for the conference? So if I give it to you? By the end of the month the video should be up on rubymidwest2011.conference.com as well. So the video will also be up at some point and you can hear me do this again. I think that does it. Thank you for your attention.