 Sandy Nets is a bicyclist who also codes. She's from D.C. Durham. Sorry, I meant Durham. She's from Durham. And she and I share a bond of being all-time small talkers. So we learned object-oriented programming the right way. Woo-hoo! And she's just written the most awesome Ruby programming book of the year, which I'm sure she'll mention in her talk. There's a little shill for the end. Okay, good. She'll mention it. And we actually have a couple copies that we're going to give away tomorrow in a random drawing. So that's enough of me talking. Now Sandy Nets is going to talk to you about making a mess and cleaning it up. So before we get started, I have just a couple things. Is the echo as bad for you as it is for me? No? Okay, good. I'll deal. This is a 45-minute talk. I'm in a 45-minute time slot. I know you're all post-lunch, low blood sugar. So those of you who did not already get a snack, you're not going to get one till 39 minutes from now. Okay? Just like, get yourself reconciled to that right now. I'm from the East Coast. And so if I were at my, well, if I were at my house, I would be having a beer right now, so I don't feel all that bad for you. So the Life Cycle of a Rails app. Here's a story, and you guys probably know this story. You love life. You love Ruby, and you love Rails. And you wrote an amazing app, and everyone thinks you're a genius. And then the customer asked for a change, sorry. The customer asked for one little change. And so you go off, you turn it off, you open up the code base, you get your text editor, and you make that change, and then it turns out you have to make another change, and you make a few more, but it's really not that bad. And you check all the code, and you fling it in production. You still feel happy and smart. And then your customer changes their mind. They didn't really want that. They want this other thing instead. And so you say, okay, and you go off, and you grab the code, and you open up your text editor, and you get in there, and it turns out you need to make about 50 changes, and all the tests are broken, and it's a long time to get all the code put back together. But you do it, you fix it, you deploy it, and it's all back in production, and everybody's happy. And then, of course, they ask for a new feature. And they need it tomorrow. Everyone's hair's on fire. And so you go in, and it's impossible to do. The code wasn't designed to do that. And so you just start beating at it with a machete. You whack it, and you do every possible hack. You make every crappy decision. And in the end, you're trying to figure out how you can get the code checked in without putting your name on it. And you realize that you hate this app, and that you hate Rails, and you hate Ruby, and you hate your life. So we know this story, right? Everybody here knows this story. In the beginning, the app was a delight. And you felt great, and the reason you felt great, that deep feeling of satisfaction is because you were getting so much done. We feel happy when we're doing our best work. And these feelings, these feelings about happiness stand as proxy for the state of your app. Unfortunately for many apps, this feeling peaks about the time when you deliver the first beta, and then it goes downhill ever after. Things get worse and worse. You were fast, now you're slow. You were happy, now you're sad. You were cost-effective, and now you're a money pit. The app was amazing, and now it's just a mess. And this does not mean that it's time to look for a new job. There you go. Amnesia doesn't help. Unless you do something different, you're going to end up hating every app you ever write. These applications are prisoners of their designs, and they're holding you hostage. You can't outrun the problem. You have to do something different. You have to learn to understand the mess. And the problem with messes is that they're messy. They're hard to understand. Everything is tangled up together. They're like big tapestries where everything is woven together. There's a warp and a weft, and they run over and under to make these pictures in the cloth. In the beginning, everything's a-dilling, but as soon as you start making changes, the illusion gets shattered. Your app isn't a pastoral scene with these sweet, furry little lambs. No, your app is trying to kill you. Things are so woven together that you can't pull on any single thread without breaking many things. And this coupling, this mess, is because of knowledge. Your app is made of objects, and objects know things. They always know things about themselves, and sometimes they know things about others. And it's knowledge of others that weaves objects together. When an object knows something outside of itself, that's a dependency. We all know dependencies. A dependency is something that you know that when it changes, you might be forced to change in turn. You can't avoid dependencies. Objects have to collaborate. They have to know things about each other. And these collaborations require that they talk, that they know things. However, there are many different ways to solve any programming problem, and you can easily arrange your dependencies so that things turn out badly. So controlling dependencies requires understanding the stability of the various bits of knowledge in your app. Everything an object knows, every bit of information can be ranked along a continuum from completely stable to completely unstable. And it doesn't actually matter how stable any individual thing is. It just needs to be more stable than the things that depend on it. Stability is relative, and things that seem wildly unstable from some point of view are perfectly dependable from others. It's also true that sometimes you don't know how stable things are. You're uncertain. You don't have enough information. You're confused. You're confused about how stable a bit of knowledge is, so you don't know whether you can safely depend on something or not. When I found this picture, I thought, this baby is confused why its parents put it in that snowbank. What? Do you have kids? Okay, we're not going there. So you're confused, right? You don't know enough to make good decisions about your app. And this is where object-oriented design gives us hope. Hope. Object-oriented design is the ultimate dispenser of programming treats. Hope. Oh, sorry. Oh, that was a screw-up. Hope. So object-oriented design lets you write code that your future self will love, even in the face of confusion and uncertainty. It knows how to separate the stable from the unstable, and it allows you to depend on the first and to hide the second. It explains confusing things. It's like a light for you in the dark places of your app, and it gives you a way to arrange the mess so that you can write apps that are fun forever. It changes everything. Design lets you stop worrying and learn to love the mess. Okay, so I'm going to show you code now. We're going to look at code. I got three examples. The first one is just the setup. It's a very simple example. We're going to talk about it for a while. I demoed this talk to somebody who was disappointed that the example didn't change during... But I didn't change the code during the example once. I said, don't get your hopes up. We're going to just look at one piece of code and talk about it for a few minutes. I'm going to diagram the knowledge, and we're going to give things names. It's going to take maybe 10 minutes. Example two is I'm just going to ruin it. I'm going to introduce a change that's going to break the code. And in example three, a miracle occurs. We're going to apply a technique of object-oriented design to remove all the dependencies. So, oh, sorry. And these are the slides that go with what I just said. I really did practice this a great deal, but now I'm wound up. Example number one, imagine we have a game for racing bicycles because all my examples are bicycle-related. So players have to buy parts, and one of the parts they can buy is a bike shock. So if you've ever ridden a bike that has a shock, you know that bikes without shocks are stiff and uncompliant, and mountain bikes have shocks. In this case, the customer told you there's only one shock, but there will probably be others in the future. So the shocks cost in this game model. So before buying a shock, a player wants to ask the game what it's going to cost, what a shock will cost. So here's the code. The code already exists. A player can send shock cost to game. The game will turn around and get a new instance of shock, send it the, and send that cost message. Here's what cost looks like. I didn't even bother to implement it here. It's assumed that it's 100 lines of scary math, right? It's a completely ridiculous method. But it has these qualities. It has no dependence. No change inside this code can force a change anywhere else in your app. And it has no dependencies. There's nothing you can change outside in the app that would force you to make a change in this code. The mess is completely self-contained. And it doesn't matter, if that is true, it does not matter how embarrassing this code is, it doesn't exist. This is a tree that falls in an empty forest. You can't, if you're brave enough, if you have enough guts to leave this ugly code, you can leave it right there. Because of that, because of these special qualities, I'm going to give this mess a name. I'm going to call it an omega mess. So here's what an omega mess is. It's at the end of the line and has neither dependencies nor dependence. So that's all well and good. But we already know the customer tools that more shocks are coming. I got this big ugly calculation and we know it's going to change. And so the question now, the question is what should we do? Should we leave it? Should we change it? Should we anticipate the future in any way? This method is a house of cards that's going to fall. And what you have to decide is what are the consequences of walking away right now? So I want to post, hold on to that question. I want to postpone it for a little bit. First, I want to look at this code another way. I want to look at a picture. This is a picture of the objects and the messages that pass between them. It's called a sequence diagram and I love them. It's also UML, but trust me, it will be okay. Here's how they work. The object is going to boxes at the top and the bottom. What's in that box can be, it's some kind of object. So it could be an instance of a class or it can be a class itself. Where the boxes, they're connected by this vertical dashed line. When you send a message, you get this horizontal line that has a filled-in triangle at the end. So this is an instance of players sending the shot-cost message to a game. While game is busy processing that message, you see this vertical gray bar and then the result gets returned on this dashed line that has a filled-in arrow. Who has not seen a diagram like this before? Your lives are about to get better. So I used a web... Oh, look, I have a special pointer watch. I used web sequence diagrams to draw all the sequence diagrams you'll see in this talk. I took their name off the rest of the slides, but there's a credit at the end. So this picture, this sequence diagram represents the code you just saw. There's a, right? Players send shot-costs to game, it sends new to shot class, sends blah blah blah, right? It's exactly what you just saw. It's a visual representation of the knowledge and the dependencies in the code. You can draw on it using a couple of different shapes and colors. So the line with an arrow on it is going to mean some bit of knowledge that I have that's external to me. Someone else knows it. The dotted line with the circles on it is something I know about myself. The colors represent stability, it's a stop light, things that are unstable are red, things that are really stable are green, oranges somewhere in the middle. So game knows the name of the shot class. Game knows the name of the new method and it knows that the shot class knows it. Game knows the name of the cost method and game knows that the instance it created of the shot, that that guy, it knows the name of the cost method, it knows to whom it consented. Shock, and those are all dependencies. Shock knows that it implements cost and it knows how it does so. So shock has knowledge but no dependencies and game depends on a surprising number of things and they're all in shock. So shock's just a shock. Does it require any other object? It's easier to use, it's easier to test. But a game, however, a game is a little stuck to shock and if you pull on a thread in shock, game might come to, game might unravel. When you test a game, you're probably also running code in shock. The sequence diagram is a much truer representation of the relative importance of things and what might dominate your view of the code, that hundred line mess, is reduced to this little gray bar on the sequence diagram and it's hidden behind the message. And so this view of reality is deceiving. It feels like pounds of code ought to be related to how important the thing is and maybe if we all wrote perfect code, that would be true, right? Everything would be abstracted at the same level but it's very often not true. This cost implementation is like, it's like that big boisterous guy who monopolizes the conversation and all the introverts stand around and act as an audience. If you walk in that room, it might seem like that guy is the most important thing but the introverts are all more interesting. It's just hard to hear them, right? It's so noisy. Don't be misled. It's not about the code. It's not about the classes that are defined by the characters that you typed into your files on disk. It's about the running, living, breathing objects as they interact in memory. It's about the message. So now let me see a little bit of code. Ooh, okay. 40 minutes. Sorry, I was wrong about 39. So now you've seen a little bit of code, we're going to just take a break and step up like to 10,000 feet and just think about what we just saw. Here's a plot. We're going to plot every bit of knowledge in this space. So the horizontal axis is stability. Things that are really stable go left, really unstable go on the right. The vertical axis is about whether or not it's your job. So for any object, is this thing that you know deeply inside your purpose or perhaps outside your purpose? Each quadrant, the top left quadrant, the stable things that are within your purpose define the public API. Unstable things that you should own or private behavior that's yours. Anything below this horizontal line is a dependency and knowing what quadrant a piece of knowledge falls into tells you what you should do about it. The public API should be exposed. Private behavior should be hidden. Stable things that are outside your purpose, you should have a minimal number of these. You should depend on the fewest number of things that are more stable than you. And unstable things that outside your purpose do not belong there. That code needs to be moved out of this class. This is what makes you hate your applications later. It's that stuff that changes every time something else in your app changes. So on the sequence diagram, we saw that shock knew some things and game knew some things. And so let's just put each of these bits of knowledge in that quadrant. Shock knows it implements cost. It's part of its core responsibility. It's as stable as you can get. And its purpose goes top left-hand corner. All right? What about the calculation? Well, same thing, kind of, right? It's really unstable. I mean, we know it's going to change, but it's completely within shock's responsibility. It belongs above the line on the right-hand side. We should just hide it. Let's switch to game, the things that game knows. Game knows the cost message. Now, the cost message, it isn't his. It's part of the stable API of shock. But still, that's the kind of thing that you have to know to get anything done, right? The fact that shock implements cost is likely to be very stable, and it's something that's probably safe to depend upon. These last two, knowing the name of the shock class name and knowing that you can use it to generate the object that should receive the cost message, these two are bound up together. Where do they go? Well, it's not really clear. Like, how stable is that? It seems like it might be stable. It might not be. It's really common to be in this situation where you just don't know how stable something is. And so I don't know where to put it on the quadrant. I know it's below the line, but it could be something that's all right for me to know, and it could be something that I should get out of there. So we're just going to... I'm just going to let that go. Since I don't know enough to do anything, I'm going to do nothing. So here you go. Ten lines of code, and I've been talking about it for, my God has time flown. Ten minutes. And earlier I asked you to ponder what the consequences were of walking away and leaving this code. Is it worthwhile to make any change here? We're uncertain about the stability of the things game depends upon, and while we know that the cost message in shock will change, we don't know how. So at this point in the design, what you should ask is one very basic question to guide your decision here. You should ask what is the future cost of doing nothing now? If the future cost is the same as the present cost, wait. You will always have better information later. There is no reason to anticipate any future requirement here. This code will not cost you more later when you make a change. So even though you know that shocks are coming, don't anticipate that. You don't know what will happen. And even though you know that you don't know how stable the name of the shock class is, perhaps it will not cost you more to wait. So in that case you should. Since cost is an omega mess with no dependence and no dependencies, that's the criteria you use, right? You can leave it because it's an omega mess. Now having said that, this was my code, I would not leave it. I would not leave it. I would inject that dependency. It's free and it saves me time, it saves me time and trouble in the testing. And I would refactor this big mess to make little tiny methods that had intention revealing names, because I know I'm coming back to it and I know I will not remember. You might do something else, right? You might do something else. I do these things almost without exception because doing a refactoring that simplifies code is like buying a ticket in a lottery that's rigged in my favor. This pays off so often that the winning strategy is to play every chance I get. Doing a refactoring to simplify code is not the same as doing design. I'm not anticipating a design, I'm just rearranging this code so that it's easier to understand. And I find that if I do it 100% of the time and it pays off 50% of the time and the 50% of the time it pays off, it often saves me an hour later instead of 10 minutes. So it's worth it if you just do it all the time. So I'd need this code, but I would not do more in the way of design. But that's it. So we're done with example one. And so now let's make things more interesting. Let's break it. So the days come when there's more than one shock and they vary in cost. In case you're not a bicycle, I gave this talk to some people who did not know what all these things meant. So I'll tell you, front shocks is on your front wheel. The rear shock is the one that makes your seat post go up and down. And there's also a special kind of front shock called a lefty that just has like, instead of those two arms that go down and grab your wheels, there's just one. Don't ask me why. But you can buy a shock like that. So you'll see those shock types coming up. Well-intentioned, well-meaning programmer has gone and made these changes. The change to game was pretty simple. It just took the game player, picked the type that got passed in here, and then that got passed right on to shock. Shock's been ordered so that it knows that type. And they went into the cost method and they put this case statement to switch on type to get the right calculation. So now I have four calculations here. Each one is independently a big mess. This is the sequence diagram for the code you just looked at. Like, you can see it's a little bit different. Like, this is the difference here, and then I put this comment here. Now, I told you before that I love sequence diagrams because they were a truer representation of what was going on in code than the code itself. But now I have to take that back a little bit and tell you there are some programming sends you can commit that are so egregious that they cannot be revealed by a sequence diagram. I put this comment here to remind myself that there was a conditional with messes in each branch. If I didn't have that comment, it would still just be this little gray box that said cost. The difference here is that cost is no longer an omega mess. It no longer has no dependence and no dependencies. Oh, sorry. So it's not an omega mess. Here's what it used to know. Before I made this change, there was a cost method in the cost calculation, and now it doesn't know just one calculation, it knows four, and it also knows four symbols for shock types, and it knows the mappings between the two. And this information, these things are known to but not owned by shock. What will happen if the application adds another shock type? What will happen if any one of the cost calculation changes? Suddenly, there are many ways things outside in the app can change that will force you to change this method. And when you reach into your app and grab a thread and pull, and the whole thing comes with you, this is what happened. This case statement, the case statement itself cost an explosion of dependencies. Cost is no longer an omega mess. It's something completely different, and I'm going to call it meta-knowledge. So meta-knowledge, meta-knowledge is knowledge about knowledge. Omega messes are hidden inside the pieces of this puzzle, but meta-knowledge is knowing how the puzzle fits together. And so meta-knowledge is a domain of design. It explains what just happened. It understands why the dependencies exploded and it offers many, many, many simple ways to fix this. And in a minute, in the miracle, in example three, I'll show you one of them. But before that, let's go back up and plot this knowledge. So these are the four things that Shock knows now. So we already did cost, so we're not going to look at that again. So let's just check out the calculations. When Shock knew just one thing, it was within its responsibility. But now that it knows four, it's probably not its job. They are still wildly unstable, but they probably belong in this quadrant. They should probably be moved out of Shock. It's not Shock's job to know about the for-ness of things. So what about the fact that it knows about four types? Well, it's the same thing. I mean, your cue is that there's a number there. And what about the fact, the mappings between them? Well, the mappings between them are probably more stable, but it's still not Shock's job. So these new dependencies make code costly to change. The method used to be independent, and now it's woven into other parts of the app. Not only is it costly to change, but it's likely to change. Where there's for-ness, there's probably somebody going to be three-ness or five-ness. Adding that case statement ruined a perfectly good omega-mess. And this is really unfortunate because the problem is completely avoidable. You never have to accept these dependencies. You can easily arrange this code to avoid them. It just takes a little bit of knowledge of object-oriented design. And here's the guiding principle. I would rather send a message than implement behavior. That's it. That's all you need to know. Okay, well, so that, in theory, in theory that's great, but here there is no one to whom to send a message. Right? The code ended up where it is because Shock is at the end of the line. It already knew how to calculate one cost, and when you ask that naive programmer to come in here and add more shock costs, the question they ask was, where should I put this code? And the cost message was the obvious place. But that's the wrong point of view. It asks the wrong question. We acquired these dependencies because we asked what object should know this. And we can remove them by asking, what message should I send? Once you know what message you want to send, you can just make an object if you have to. And as soon as you have an object and a message, you can send it, and that brings us to example three. Composition. Object-oriented composition. I would explain it, but it's so much easier just to show you because the demo is really simple. So here we go. Ugly, dependent-laden case statement. We want to reduce the dependencies. We would rather send a message than implement behavior. We don't want to know things. We want to ask somebody. So there's a repeating pattern here where each type gets its own calculation. Let's just look at the first one, the original mess. If I don't want to know this calculation, I have to figure out what message to send. So what message should I send? Well, how about compute? That seems fine. Compute. And where am I going to send it? Well, let's just make something up. So I'll just make a new class. I'll name it after the type and this entire calculation into its compute method. That's an omega mess. I'm back to where I was. There are no dependencies on this code. This is code that will never change because of something else in your app and it will never make anything in the rest of your app change. So now that we have somebody to ask, we can just send the message. And if we just repeat this pattern for every branch of the case statement and make up a new class to hold every different conditional, then I end up replacing all the computations with the calls to the classes and I just send the message. So shock is now composed of all these costars. But somehow, it's a let down, isn't it? Somehow, it doesn't seem very satisfying. Right? You're like, well, that sucks. You're expecting something more, I know. And the reason is, I think people don't do this whole refactoring because when they look ahead, this is as far as they can see, right? If you imagine you're going to hear it, it does not seem worthwhile. Like, is this an improvement or did I just complicate the situation in the name of design? Well, what did this accomplish? Let's go back and look at our meta knowledge. So I used to know four shock cost calculations and now I know the name of four classes. And I used to know four mappings between a type and a calculation and now I know four mappings between a type and a class. So there is good news here. The calculations have been re-isolated. They used to all be in one method and now anytime you need to change any one of those calculations, there's just one place that you can go and change it. So there is good news, but there's still bad news. There's still lots and lots of dependencies in there because of the case statement. There are many ways in which this could be forced to change for an unrelated reason. So if you add or remove a shock, you have to change this code. I hate that. So let's fix that. So notice the pattern. There's a symbol name and then the symbol name matches up with the class name. We're switching on type to select the class. That looks a lot like foo, foo shock cost, right? So because of that, and we control these names, because of that I can do a very Rails-like thing and use a convention to manufacture the right class. I can convert the name of the class into the class itself. The most obvious way to do this, I'm not recommending this. The most obvious way to do it is with the eval method. Okay, I sometimes do that. I know it's bad, but I sometimes do it. So this takes a string and it sort of evaluates it as Ruby code and so if you pass a string of a class name in there, it'll turn it into a class. Then you can send new to it. A slightly better way to do it is to use this method on object called const get. So there's a, you know, somewhere, I don't know nothing about Ruby really, so there's like a table someplace. Like I pretend that there's a table someplace with all the classes in it, so there's a hash somehow and you can, so this looks up, I tell myself, this is the story I tell myself about this code, this looks up the string in that table and I get back the object I can send new to it. But since we're clearly using Rails here, we're calling titleize, in terms of Rails has a constantize method and so it's much more in the pattern that we have here to just use constantize to turn that into a class. Any one of these things works. So we can use a tiny bit of metaprogramming here to manufacture a class. Now I use the word manufacture quite deliberately. It's exactly right because this is a factory. Some of you just broke into a sweat, right? You came from one of those languages where everything was hard and you have PTSD, but I'm telling you, you were clever enough to choose Ruby and those days are behind you. Not only do we love factories, we like this word and it's a perfectly good word, it's exactly right and I want to reclaim it. Something that manufactures an object is a factory. It's as simple as that. Go forth and spread that gospel. So now that I have this factory, I can remove the entire case statement. Shock doesn't need to know the class names. It doesn't need to know the shock types and it doesn't need to know the mappings between them. It just needs to know the convention. I can replace this code which will break just about every time you change something with this. Now of course I wouldn't leave it at this because I can't stand it because it does two different things so I would actually refactor it a little bit. I would separate the thing that turned the string into a class from that, just because I would have to give it a name. So you can change that and then you can just make as many as you want. You can make them or delete them. Nothing ever changes about this code. As long as you follow the convention, this code works. So that was composition and so everything seems like a picture to me so I drew you a picture in Keynote. So here's what it feels like. We started out with a shock class and it had a single cost method and then I jammed four different calculations in there and so I was trying to fix that. I was trying to get those responsibilities where they belong so I made up a method and then I pulled all those parts out, wrapped them in classes to find the interface, attached that interface to all the parts and then this is a key quality of composition. It does not matter what's behind the interface. I can make a new one just by giving it the interface. This interface is the API of a duck type. It's a role. Shock's cost method doesn't know or care about the class of the object to which it's sending the message. It just expects every collaborator to play that role. Thinking of a collaborator as a kind of its role rather than a kind of its class changes everything. When you can manufacture the right kind of thing and trust it to play the role that you expect you can just send the message and everything gets easier. The dependencies disappear and applications become like pluggable Lego component like objects. So design happens from the message sender's point of view. You don't send messages because you have objects. You have objects because you send messages. Object-oriented design is not in the business of dictating perfection and knows there's no such thing. The only request is that you remove the dependencies and the dependents from your programming sends and that you make them self-contained and that you hide them behind stable interfaces. It shows us how to recognize meta-knowledge and it tells you to organize it according to the principles of object-oriented design. So there you go. Object-oriented design. It's a set of tools. That's all it is. It's a set of tools that tell you the consequences of how you choose to arrange code. If you know the tools, you can grab the right ones and apply them in the right places. And the truth is, even if you never make an effort to learn them, if you write object-oriented code for long enough, it will teach you these rules. That's design. I know more now. We can probably all say this. I know more now than I used to. But there was a time. I was writing object-oriented code in a cave. I never read anything. I never talked to people on the real world. In that cave, I discovered many rules about how to write code for myself. This is a slightly embarrassing story, but I'm going to tell it anyway. There was a time when I thought that I had made up the law of Demeter. Pinky swear. I did. I found out that it already existed because I was having an extended rant with somebody one day and I was like, you know that thing where they send a lot of messages and they go and they go and it's tangled up and she was like, oh, the law of Demeter. And I was like, what? It has a name? And so, I mean, the truth is you can figure it all out. You can learn these things. You can figure out composition. You can understand dependencies. You can get rid of all these things. But they say that good judgment comes from bad judgment. And unfortunately, you've heard this, right? Bad judgment. Good judgment comes from, I'm sorry, experience... Sorry. Wait, I can do it. Good judgment comes from experience and experience comes from bad judgment. All right. And I have a lot of experience. Like Joe said this morning, I am a woman of a certain age. So, I walked... Wow. I walked into the headwind for a long time. I didn't realize that there was an easier way. And you might be different, but no matter how special you are, there's no need to suffer. Like, we can all learn from those who have come before. Object-oriented design says that stability is relative and that you should notice it and you should depend on things that are more stable than you are. It says that what you want is more stable than what they do. What they do is messy and uncertain and changeable, but from the outside, from where I stand, it does not matter what's inside that house. If you arrange code so that you cannot see the mess, it does not exist. We stand on the shoulders of giants. We truly do. We are so lucky to live in this age of information where the best thoughts of anyone are available to everyone. And I'm not saying we're all Isaac Newton's or that everybody in the design world can start somewhere. We start out as infants of design but you can grow and learn and we can teach each other. It isn't always easy. There's no guarantee that you'll be happy every step of the way. But if you persevere, a time will come when your applications bring you nothing but joy. You can never outgrow the principles of design. Learn them, use them, make them your own and you can write applications forever. Thanks. Wait for it. Watch this. I've always wanted to use this effect. Sorry. Questions. I have... I went slow and then I sped up somehow. A couple minutes for questions. Any questions? Who's got $5 to ask a question? I have a question. From a Tet debt perspective when you're making all these classes you're probably going to want to put them in their own files. So now you have tons of these files and if you grow a very large application over a number of years you're going to have hundreds and hundreds of these classes and then if you generally like to clean it up you did a good job using some meta-programming of concertizing so now you don't know which ones you still are using and then now you have 200 classes and you use 77. So scary. I don't care. Here's a deal. What cost you money? I'll quote myself. Tolerance of the ambiguity of a class of an object is the hallmark of a confident designer. You don't know. Make the interface. You've got to have good tests. There's a continuum. Things that are real procedural are really easy to understand and really easy to change. On the other end things that are more object oriented are harder to understand. The procedural things cost to change but they're easy to understand. The more object oriented you get the harder it is to look at any single piece of code and understand it but the easier it is to make change the systems are small, little loosely coupled, highly cohesive and hard to look at it and understand it. The better the design you have the more you rely on your tests explaining that there's APIs, there's duct types, there's roles. And I would tell you I do not hesitate to make a class that has two lines of code in it and it always saves me money. You get used to it. If I can console you, you get used to it, right? Like bring me a metric that tells me that costs you more than the better design saves you and I will be absolutely willing to rethink my ideas about this. One more? Is it done here? Screw you, man. So I was wondering why you wouldn't create a separate class for say left shock and front shock and rear shock and define cost in each of them. Absolutely. And you could totally do that, right? Of course I had a whole another... I had four examples originally so I'll show you inheritance. Here's the way I would make the decision about whether is it a kind of thing that shock is composed of or is it another kind of shock in a way that might use inheritance. And that argument about should you use composition or should you use inheritance is like loud in the community, right? As an old small talker I like inheritance, I use it a lot. In this case if there were a lot... So you should use inheritance when all the variants are almost alike and there's tons and tons of code that is almost just the same. So if the only time if there was like shock was this big and the tiny difference was this thing then maybe it's all subclasses of shock. In this case shock has assumed... shock has a bunch of other behavior and this is a piece of it but a big piece of it. So shock is going to be composed of these parts. Anything that you can do in composition you can do in inheritance too. So if you're getting all these tools in your toolbox is playing at the boundary point between those two decisions and trying to figure out where you save the most money. And so you could, absolutely. And I might have done that myself had I not wanted to show you composition. Okay. Are we done? Sorry, it's break time. Give me the hall. I'll talk about this forever. You haven't missed your last chance. We've got another day. Plenty of time to talk. And thank you so much. That was great.