 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. Cucumber is not slow. Whoever said that. Testing through the UI is slow. Firing a test is slow and also stupid. That's what's slow. 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. Ventrate seems to be expressing itself more than others. Facial hair. Yes, facial hair. Well, 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. 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? Who likes the show? Identify with the character of House. So, House is a doctor. He 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. 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. In fact, 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, oh, I can break all the rules I want. I can come in any time I want. I can go home any time I want. I can go 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 and coding. Same rule that applies to pilots. Name of this talk, oh, by the way, I should probably do a science lecture first. Who has been tracking the e-cat thing? See, that's just fascinating, right? I've read about it. You've read about it? Okay, all right, so this is probably a hoax. Probably. And if I had to wager right now, I'd say I had nine tenths of hoax, 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 do, 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, oh, 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 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. There's this catalyst that he talks about that he won't tell us about and all this interesting stuff. So probably it's a hoax. It's probably too good to be true. Take a look at this one. It's interesting. And 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 util. Well, you can go into the specs over here because, of course, it's test-driven. Those are 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 communicate 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 immediately 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 about. Rails is a web framework. What is the web? Thank you, yes. It is a delivery mechanism. The web is a 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 pipeline. It is nothing more than a pipeline. It is not the central abstraction of your application. It is not the grand overarching thing that makes your application the application it is. The web is just a dumb detail. And yet, 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. If I did not 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. 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 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 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... Hello, this is my wife, Tom. Excuse me. I'll turn my phone off. Where was I? Thank you, yes. 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 Ivar 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. And 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. I'm going to need a customer ID. I'm going to need some customer contact info, maybe a shipment of that 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 the 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. It'll have some alternate, exceptional courses in it, just ways to deal with errors and so on. And Jacobson 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 Jacobson said was, look, this is the central abstraction of your application. So it ought to be an object. He called it a control object and I would call it an interactor object. I would call it that because I don't want you to be confused 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 application-agnostic business rules in your entities. You put application-specific business rules in your interactors. And notice there's 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? 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 in the interactors. Application-agnostic business rules in the entities. These kept nicely isolated from the rest of the application. How do we get the data in and out of the interactors and 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. It disappears 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? Wow. Can you see that? 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 deck I'm going to do with it. All I can do with it is color my glasses black. So I'll get my... How about the red one? We've got a user here. A user is going to talk to our application through the delivery mechanism. I don't care. I don't care what the delivery mechanism is. It might be the weather. It might be the client. It might be a console app. 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 interactors 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 DLL 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. Think of what that would mean to you. If the delivery mechanism were 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? 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 tests 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. Doesn't matter. The delivery mechanism somehow captures what the user wants. Maybe on a forum, 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. 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 entity and 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, entities, and boundaries. Very good, thank you. Someone with a brain cell 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? 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 does 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? It's Trig V. Trig V what? Brian is something wrong. Rheinska? I can't say it either, but you probably can't. Trig V Rheinska, 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, a 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 basic submodel 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? Smalltalk. If there were a screen in smalltalk, 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 on 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. And that the... How many models does the view know? Hundreds. Hundreds! Yeah, we've kept the model idea, haven't we? But now the view... Well, actually, I have a picture of this, which is the picture. Anybody recognize that picture? No. 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. Oh, 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, in some horrible, bastardized language, that can't figure out whether it's HTML or Ruby or Cotnos or what else. And it's reaching into the business objects. Your view... 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 32-70 program? Did you recognize this? Alright, this is just 32-70 programming, and I'm not going to say on steroids. More like on Strickline. Alright, it's 32-70 programming poisoned with all kinds of crud. How many languages do you have to know to write a web application? You gotta 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 Zazzle and Dazzle and... 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. Okay, now hold this hammer. Good, now you got that hammer? Now here's no. Now I got a big barrel of water you gotta 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. Ooh, 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 packs 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. Doesn't have anything left to do. It's just one last thing. It kicks it through some interface to an Interactor. And the Interactor does whatever it's going to do and eventually creates a response model here and the 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 that 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, maybe 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 to the view model and all the view does is go put that there, put that there, put that there, put that there. 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 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 don't write a lot of them. 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. There's a lot. 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 can be put into a gem. And the stuff on the left 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? A thousand. Four and a half minutes, a thousand. That's a good time. If it's four and a half minutes, I'm pretty happy with that. Who's got one longer? Hour and a half. Hour and a half. Or five hundred and fifty. That's not good. In the bag? What? How many tests? Two. Two. Too many. 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 tad. Because they're taking too long to execute. This is the symptom that occurs. You know, this whole 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? What about the database? 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 the problem. We'll solve the problem. 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. I don't care or ask 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. It's important 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. 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 we had our interactors and our entities? 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 an item gateway. A bunch of them. And I can invoke methods on them like put entity. Get order. Find order. Put a bunch of nice little methods on them. And then allow some interesting lines. I like to draw these lines. You know what architecture really is? It's the art of drawing lines. 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 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 plugins. 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. What 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 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? All the delivery mechanism of Rails to the left of the line. We know the Ruby code. 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. Ruby that doesn't know anything about the web Ruby that doesn't know anything about the database just Ruby that deals with some nice little data structures and hands it off to some plug-ins that do happen to know about the database somebody mentioned, well, you know these could be services. 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 the one of the authors and committers on a project called Fitness who's used it a few of you good it is a Wiki-based testing tool and has a front page that looks like in case you want. No. It's a Wiki. Who invented Wiki's? Excellent. Who's word cutting him? Word's actually a very interesting fellow. He did invent Wiki's. He also invented a number of other things. He's the guy that called Eric Gamma on the phone and said, you know he 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 and testing and development and agile methods and 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 it makes HP35 user? Oh, 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. It 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 seven-segment display. Reverse polish. Right? HP copy. Reverse polish. No parentheses. So, on the screen is the card that came with it that 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 on the card turned green. And I thought, test wasn't it, Ward? 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 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, Ward 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. Now, I went home and I said, we're going to write this wiki. It's called 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 wiki text translation that has to be done. You know what a wiki does is it takes a little text and it turns it into HTML, which is really horrible text. I'm not sure what the point is anyway. But anyway, it takes all 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. 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 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, well 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 the in-memory page. We'll write all our query methods on there and our save methods on there. And they'll just use the hash table and store it all in memory because after all we're not going to do millions upon millions of things. 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 got tests running. We couldn't save any of it. It wasn't particularly useful. It wasn't anything, but it all worked. And we could show it to people. Look, it worked. Don't, don't, don't quit. But you can make 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 the 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. 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 fly fox. And he sat down 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 on 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 were done. 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 in. 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. It was never part of the plan, but it was there. It just happened. We kind of looked at each other and thought, well, that's 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 the 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 MySQLPage or OraclePage or whatever the hell you want to call it. Which he did. He went away and did that. It 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 arrow 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 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 you know, rails are really fast. Just throw together some shit. And that would be the plug-in to your application that allows you to show your customers, oh, look, well, 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 done. Do not decide up front what road you're going to take. Keep all 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. 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. Thank you. If you're a test-driven developer, that makes perfect sense. If you're not a test-driven developer, it sounds insane. So, why must you write your tests first? So you know when you're done. So you know when you're done. Another good example, okay? But not the one I'm 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 our suite of tests? So that we can refactor. That is the exact reason. The suite of tests is not there to satisfy a QA group. The 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. You look at it and your first thought is, oh, someone should clean this. Your next thought is, I'm 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. 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've 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 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. Soon as you think that you've lost it. Because now you're 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's not enough to write your test first. Your tests have to be fast. Because if they're not fast you start throwing them away. And if you start throwing them away then the exact same symptom comes to you. You lose 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 thread. Decouple it, decouple it, decouple it. So you can write your tests and have them execute like that. 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 thought because his hand was up first. It's between your ears, son. Okay, now it's you. You're next. Are there any examples of a Rails app or 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 a cold fusion thing. We're not sure if it's you. You could manage to tie all these things together sometimes. 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 and 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. I said, wait a minute, what am I seeing at the top level here? What really triggered it for me was I remember the guy and we were pairing on a little bit of code and I said, well, let's run the test and his shoulders dropped. Run the test? Okay. And then it was a minute. It was a minute before we got the answer. Now I'm used to just button-yid a little thing and it was a minute. So why is it a minute? Oh, when you're on the test, you've got to start up Rails. And that's when it started to hit me. I've been using Rails as the central abstraction. They test through it. They 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, oh, 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 that 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. 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 it's now starting to come back. Okay, you had a question. So first is a joke about how I'm going to find the job because it's so unreliable that we can't connect to it. Yeah, right, okay. The second one is, is this slide deck somewhere where we can find it? Is it on one of these websites? Please speak up. Yeah, I'll answer the question. I'll repeat the question. He wants to know if this slide deck is on any of those websites. But it could be. It could be. And is there a website for the conference? So if I give it to you? Yeah. 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.