Strong Duck Type Driven Development
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Cinnamond, John
As a language, Ruby plays fast and loose with the type system. Developers rely on duck typing to check that the things they want to do with an object are permissible. Whilst this freedom makes writing code frictionless and often a whole lot of fun, it doesn't always scale up well to writing larger systems. I can't promise that strong duck typing - adding automated checking to inter-object interfaces - will make writing complex systems easy but it will help you think about how to structure code in new ways and bring some of the lessons learned from other languages to the Ruby community.
 I'm not sure. I'm pretty excited to be here. I'm a little bit terrified but a good excited kind of terrified. I'm super excited. I'm very excited. I'm super excited. I'm super excited. I'm really excited. I'm super excited. I'm really excited. I'm super excited. I'm a little bit terrified, but the good excited kind of terrified. I was a high school coming out and there's three of them talking to me on the scene, but for some reason he decided to come here and see this talk. Although I've asked why, I mean, did you guys look at the title and think, yes, drawing down Patrick and Gawd and that's the kind of thing that's relevant to me. I'm guessing that most of you are looking at the title and probably not really going to tell what this talk's going to be about. I mean, maybe a little word you think, but I don't know, it's just somebody with ducks driving. Maybe it was a duck's tithing, I'm not quite sure. Well, never mind, it's just a strong duck, yeah? Well, no, it's not going to be with an ass. And the title remains kind of confusing, but actually, I don't really want to explain the title quite yet, I want to give it a bit of context first. But I'm going to say this is not a talk that's all to do with ducks. Let's start by building a duck. Now, I'm going to say I'm not a professional duck builder. So before I can start to build a duck, I'm going to ask you a question, how do you build a duck? I haven't built ducks before, but I have built other things, other non-duck related things. And in order to build something, you really need to understand what it is you're building. So the question really becomes, what is a duck? Now, I'm not completely in it, I've got some idea what a duck is. But my past experience suggests that I don't know of them in enough detail. So you need to kind of understand the duck in a lot of detail before you build it. Now, again, my experience suggests that I can't hold all that detail on my head in one go. I need to break it down into smaller, more manageable chunks. So I guess the final thing I need to do before I build a duck is to deconstruct a duck to break it up into these smaller, more manageable chunks. Luckily for me, ducks are pretty common, it's going to be quite easy to find some kind of reference material. So I've chosen this chart, this is a muller, this is a pretty typical duck. I kind of break this down into manageable chunks so we can build it up again. Now, I don't build ducks for anything, but I do write movies, so I like to think that I understand the important aspects of a duck. I know it's got a warplugged duck, but it's got a quagmire duck. So we can find those bits, we can find a bit of duster quagging and we can find a bit of duster walking. But that doesn't really cover much of the duck, there's still a whole load of duck left on the conscience for it. Now, I know the duck floats, so maybe we've got a floating bit, I know the ducks fly as well, so we don't find it. And there's not much detail here, but it covers enough of the duck, I'm confident I can take this and start to reconstruct the duck. So it's good to go. So we can start with a quaggy bit, which I think is a little bit like that, and then we have the walking bit, which looks a little bit like that, and then the floating bit, and then finally the flying bit. So this is our duck, and it's a pretty roguish duck. But this is my first attempt, so I mean, we can refine this. Now, one of the things that I noticed when looking at this is we have all this negative space, and this wasn't here in the original duck that we looked at. So I'm going to do what any good developer will do at this point, and I'm going to remove the white space, or in this case, the black space. And we get this instead. Now, this is a little bit roguish duck. The next thing that really strikes me is that all these joints are really jarring, the thing doesn't fit together very well. So look at these connections and think, you know, we can improve this. I'm looking at it, I'm thinking, well, everything attaches to the floating bit, so maybe we can change the shape of the floating bit, this will fit together much better. So we can do that. We can put something in place to support the floating bit, and then we can put a little support in place for the floating bit, and then finally put something in place for the floating bit. So we'll move up a bit, and this is still a pretty roguish duck. But there's nothing obviously wrong with what we've done at the moment, except it doesn't really look like a duck. So I'm going to go back to our original source duck, which is this guy. I'm going to use Concentrate on the floating bit. Now, if we take the quacking bit that we built and super-posed it, we get something that looks like this. It's not a very good fit. It's just a good thing, it's a wrong angle, so we can improve it. And then, even if it gets like that, we're just going to lock quite right, but it's a much better approximation. So if we take this and put it back in our original duck, we get this. Now, I've improved the shape of the quacking bit, but overall our duck is worse. And it's worse because it doesn't really leak out properly. Now, I can fix this obviously. If you look at the floating bit, you can see the angles wrong when the snake sticks up too far. And of course, we can just repair that. And it's easy to do, but I'm a little bit uncomfortable as something isn't quite right here. And what happened was, I went back to my source, and I had changed the quacking bit to be more accurate. And I thought this would make everything better. But this forced me to also change the floating bit. And that's kind of weird. I wasn't trying to change the floating bit. This was forced upon me. This is just really bad coupling for improving it. So I love being too excited about that, but I would bear in mind as we go on, look at our duck. I mean, this is still a shit duck, isn't it? So maybe let's look at improving this. And when we last looked, we looked at the quacking bit, and I was thinking, actually, it's all this detail we missed a lot in there. We've got the neck bit, the brain bit, and the eye bit. And these are all missing from our model. So I only got to add them into the model. And now, it's not quite right. We need to move the quacking bit, so we'll move it up to there. And now, seeing the fish there, I'm thinking, this is the brain we made out of the provenance. This looks more like a duck we did previously. But actually, it's hiding a problem. I mean, we caused some serious damage, and if I let the floating bit, you can see what the problem is. We have this thing sticking up into the neck. So we built the duck, but it's going to die some slow, horrible lingering death. Now, that's probably what we want, unless we've got some doxedas here, but we have to have to leave, please, and... Now, we can easily fix this. We can just remove it, OK? Because this is going to be very bad for a duck, so we can just get rid of it. Those are fine, but this is the second time it's happened. We've tried to change something, and then it's always another change up to us, because we've been running out of it. And I think generally what's happening is, we're kind of focusing on the bits that we're building as we go along. But we're not thinking about how these bits fit together. And then this is causing problems for us. And this is much more interesting than building the duck. I didn't bring it here today to show you how to build a duck. This isn't a problem that I'm really quite interested in. So I want to start over, but I want to start over by focusing on this kind of problem. So, hello, my name's John, what do you talk? This is about ducks that are driving at ducks are very muscular obviously. And then let's build a duck, but actually I'm not going to build a duck again from scratch. I'll get a little repetitive. Instead, I'll tell you what problem I came across. I work as a contractor in London, and I had a client, and they had previously built a duck, and they called me in to make some changes to it. And they have a piece of code that looks like this. And this is the thing that's responsible for quacking. And it's fine, it works very well, but they were saying no problems, they were slightly different. We were just going to quack, we want to quack loudly, we want to quack quietly. I thought, this is a great contract, this is a nice easy change. So I took the quack method, and that's never going to happen in isolation. I didn't have soft quack, so I used my name to method to that. And then I did the new method for loud quack. And that worked. And I was about to go and collect my big pilot contract to cash and go home, and I thought, I'm going to see what else is affected by this change. So I ran the test suite, and it looked like this. It helped me in our aspect before. The green dots mean everything is working fine, and crucially at the end, it says zero failures. I was like, what? This doesn't make any sense. I've gone and taken the method out and replaced it with two new methods, but everything looked working. So either code is not used in the first place, in which case I can just delete it. The test room. So I did some quack and I found some code that looked a bit like this. Crucially, there's a line in here which calls build quack method. So the code was in use, which means that the test must have been wrong. It should have been a surprise because this client was very good at what testing. So I had a look at the test and it would be so code and it looked like this. And the problem here is this expect line. So when we write this line, it effectively adds a receiver for that quack method onto the object quack unit here. So it changes the interface before we want the code. Now, you can avoid this. In RSpec3, for example, if you use a business double, it will raise an exceptionally trained in this. My concern is not that we can't avoid this kind of problem. My concern is it's all too easy to have this kind of problem and not notice because as you saw before, the test's all passed. Around this time, I was planning to go quite a lot. And I thought, this is the kind of thing you can't get on Go. So I thought, how do you write on Go? So I'm going to show you some Go code. Don't worry if you don't know any Go. The code should be pretty simple. I'll try to explain it to you along. But I'm going to write the same thing in Go. And I'm going to start with the double brain. Now, I'm going to start with a struct which is a little bit like the Client-In-Class. And I'm saying it's got a single attribute called quack unit, which is a type quacker. I'll come back to this type quacker in a moment. But before that, I'm going to add a method on to our dot brain. And we do it like this. And we have to say, hello, method on. And all that does is call the quack on the quack unit. So I'm going to come back to this quacker. Now, because this is Go, everything has to be tight. And I've said the type of this is quacker. And because this is Go again, I'm going to write quacker as an interface. And we do it like this. And all this says is that we have an interface that's got a single method called quack. It takes more, again, it returns nothing. An interface isn't Go or a little bit like an interface from Java, or maybe protocols, enclosure, or various other similar constructs and other languages. You can't instantiate an interface directly. What you're doing is saying that some of the implements this interface is guaranteed to have these methods inside it. OK. So let's write some of the implements this interface. So I'm going to write some called bink. It's a little bit like an empty class here. And I'm going to add a method onto it called quack. And all this does is print a standard item. So there's the mark. OK. This is pretty much the equivalent of the original Ruby code I showed you. So we can stick it all together now. We can instantiate a new b object. And then we can instantiate a new dot-brain object. And we can set the attribute of quacky bit to be as a b. And finally, we can call say hello on this brain object. And that will call a quack object on the bink. And that will just print quack like the standard item. Or it's very fine. Now I'm going to make the same change to the go code that I made to Ruby code. So we have this b, we've got single-pack method. And you're going to place it in the soft-pack. And then now the new method is called void-quack. It's actually the same change as we made to Ruby code. OK. So what happens next? Well, it goes to compile language. And we try and compile it. And it says something a little bit like this. It says you can't make that change. Because we're trying to take b and pass it into the dot-brain. And dot-brain expects I'm going to type quacker. It'll check b against the interface quacker. And it's saying we don't need that interface. We're missing a method. We're missing a method here called quack. So in this case, I can think, well, the interface started date. I need to update the interface to my implementation because implementation is more correct. So we go back to the interface, and we just change it to have these two methods inside it. Now that we've tried compile it, we get a different error. It's nice saying you can't call quack on something of type quacker because that's not on the interface anymore. In fact, if you go back to lib.co, you can see we're still calling it old quack method. And that's no longer valid. So I kind of like this. I'm taking like that the compiler tells me how to break stuff. Now, I don't run you long, but I break stuff all the time. And it's really nice that the compiler helped me out and say, hey, you made a mistake. But more than that, the compiler's also hinting at how to fix things. It's not just saying it's broken. You're on your own. It's saying it's broken, and you missed its methods. You should have implemented it, but we can't call this anymore. There's another nice thing about the Go approach. I was writing duckbreak. I wasn't thinking about beat. I wasn't thinking about implementation of anything. And likewise, I was writing beat. I wasn't thinking about bug brain. I was only connected through this interface in the middle. And even burdened out, the interface is tangible. I can have a look at my code and I can say, oh, look, these are the messages that flew from duck brain to beak between these two objects. So I spoke to a friend of mine. He's a guy called Jacob. He writes Ruby. He also was learning Go at the time. He's a bit of a polyglot. Unfortunately, I've lost exact transcript. It was in Skype. You can never search history in every easily. But the conversation went a little bit like this. I called him up and said, hey, Jacob, wouldn't it be great with interfaces in Ruby? And he said, in Ruby, this is easy. Just go and write it. And I had to admit it at a point. It is quite easy to go and implement. So I'm back to my original duck brain. And I thought, okay, how do we check the type of quacky bit here? My first approach was a bit naive. I wrote some code like this. I said, I'm going to check a response to quack. This is just your standard duck typing. And if it doesn't implement that, I thought, okay, I'll raise it an error. In this case, an interface error. And I thought, this is great. Aren't I clever? I just implemented no method error. Except it's less efficient and gives me less information. Probably not the right approach. Okay. So I went back and thought about the problem some more. And I thought, okay, really there are contracts we're putting up between objects. And on one half of the contract, we have an object that promises to provide those methods. And on the other half, we've got an object that promises to only ever use those methods. So inspired by this, I wrote a gem called lawyer. The idea being that lawyer will enforce these contracts for me. And to write a contract, it's a little bit like writing an interface and go. You write a class and a heritage from the lower gem. And then inside that, you write declarations for the methods you want. So in this case, we'll write a declaration that says, there's going to be a method called quack. And the zero here means it takes no arguments into that method. Okay. So how do we use it? If we go back to our quacky bit, all you need to do to say this is the interface is add a line at the bottom, add a declaration, and it looks like this. And I'm saying this implements the interface called quacker. Okay. So what I'm going to make my change again. So if I change quack into soft quack and then add load quack in like we did before, what happens is when you load this file, this line at the end gets run, the declaration of implementing the interface. And of course, we don't implement this anymore. So it stops. It raises an exception. It says, you can't do this. Quacky bit does not implement this interface. And then it goes on to tell me why it says you're missing a method and this method is called quack. So this is very similar to the way that it go worked. So then we go back to interface and we think, well, actually the class is right, the interface is wrong here, the contract is wrong here. So we can just change it and add the two methods into there. So now our class loads properly. So that's one half of the contract. What about the other half, the person that's calling it? Well, I can't enforce it in the compiler in Ruby. So I thought the next best thing for me is going to be RSpec. RSpec is a tool I use a lot to check that things are valid. So I'm going to write a spec which validates this contract for me. So if you write a spec for duckbrain, we had this duck nearby method. So I'll write a spec for that. Okay. So inside here, what we're going to do is we're going to call duckbrain and then we're going to check some behavior. So we're going to call this say hello method. And then we're going to make sure that something has received quack. But I'm not quite sure that something is yet. So I'm going to follow the go approach and say, okay, we're going to have something called quacker. And we're going to pass it into duckbrain when we start duckbrain up. And then we're going to check that we call the method and that. So what is this quack that we're passing in? Well, I wrote a helper for this called contract double. It's a little bit like instance double in RSpec 3. What it does is it creates an object. It's got the same interface as anything that implements that contract. So all the methods in the contract will be available in this double object. And it will check methodality as well. So it would say, you know, you need to have the same number of arguments and it checks them arguments as well in Ruby 2. So that's what we create. And we pass it into duckbrain. And then we run our duckbrain code and then later on we can say, I want to make sure you call the right methods in this thing that I gave to you. Now, of course, I'm still calling it old interface. I'm calling quack, which we took out of interface. We replaced it with soft quack and loud quack. So what happens when we run this spec? Well, we get a failure, of course, is what you expect. And it's saying you can't call this. You cannot call quack on this double because it doesn't exist. It doesn't respond to that message. So this is kind of like the go code to me. In the go, I was quite happy because the compiler told me my rubric stuff. I thought that was pretty useful. We don't really have a compiler in a typical sense in Ruby, but I've kind of faked it by saying the tool chain tells me my rubric stuff. And this is pretty good. And it's important to note that this is still Ruby. And this is still just duck typing. But I've taken it and I've made it strong duck typing. Now, if you go to the internet and you look up the difference between strong typing and weak typing, you're going to find that it means many different things. It basically means what someone wants it to mean to win an argument. So here's what I think it means to win an argument. Actually, I think it means two things to me. The first thing is that the tool chain is helping to enforce the types. This is not like type annotations where it's up to you to check it. It's not just documentation. It will actually break, tell you early on when you break something, when you have something that doesn't implement the contract properly. The next thing that's important to me is we check before runtime. So duck typing is a really lovely idea. But quite often, it manifests itself by running a production and saying, you tried to call this method and it's not there, and I'm going to helpfully crash now and tell you it's all broken. And that's not what I want. I want it to break as early as possible so that we have time to fix things. So we have this thing and then I thought, is it actually useful? And initially I was thinking, yeah, this is great. And I was thinking things like, I've got more confidence that my code will not break in production. And it's not going to break because we've got this extra type checking in place. And then I thought about some more. And I thought, well, this kind of interface problem, I've seen it maybe a few times. And I've been writing Ruby for about eight years now. So on average, that's once every couple of years maybe. And worse than that, I've seen it happen, but it's always been caught really early on. It's very obvious when you make this kind of break. I've never seen this get into production. So I don't know this work, but I've solved the wrong problem. I've solved a problem that doesn't really exist. And I was feeling a little bit down at this point. But it could be worse. I mean, you guys have listened to me for 20 minutes telling you the wrong thing. So anyway, I was a bit down, but then I thought about it some more. And I thought, well, go with doing more than just telling me that it's broken. The other thing it's doing is it's hinting about how to fix things. I thought, that's cool. I've got that as well. It's not just telling me that it's broken, but it's giving me some hints as to how to fix it. That's kind of useful. And then I thought, when I'm writing objects, they don't need to know about each other anymore. They don't need to know about this interface in between. And I also thought, well, interface is tangible again. I can look at my code and I can think, hey, I can look and see a list of messages that are going from one object to another. And this is quite nice. I quite like this. So I want to start over and I want to bear this in mind. I want to look at how it's changed the way I wrote code. Hello. My name is John. Well, just talk and duck typing. I want to look at how this drives our code forward now. I want to look at how it changes my coding, because this is obviously a picture of me photoshopped a little bit. Okay, so let's build a duck. Now, I want to focus on a little bit of detail here. And I want to build just quite a lot of code coming up. I'm going to try and step through it slowly. But what you pay attention to is the way that I'm being driven forward as I write the code. So we had this bit of duck before, and we got the eye here and it's looking around. And I thought, well, how is this really going to work? So I imagine the eye is kind of constantly sending image data back, and it's going to go to something which is going to interpret that image data. So I'm going to send it to something called the visual cortex. And I was going to do things like shape detection and proximity detection and so on. And then when this thing is a duck nearby, it's going to send a message to the brain. It's going to say, hey, brain, there's a duck nearby. And the brain will be responsible for the next part, which is probably going to be quacking at it. So it's going to trigger these other processes to make the quack happen. Okay, so I'm going to build some scratch. Now, when I started before with drawing the duck, I could just put the bits of the duck onto the page. And that works well in your drawing stuff. But when you're writing code, you can't just put stuff nowhere. We need a container to hold everything together. So I'm going to start by writing a duck class. I'm going to start by writing a spec, because I'm a grown-up developer. I'm going to start with just one little piece of functionality. So I'm going to say, when we create a duck, I want it to also create a visual cortex for us to use. Okay, so how do we do this? Well, we're going to block of code here, which creates a new duck for us. And when we do that, we're going to say, we want to create a spec that's to also create a visual cortex object. And then crucially, I'm going to say, with no arguments. And we're very precise about what I expect to happen here. Okay, so we run the spec and it fails for a very boring reason, because we haven't written any code yet. So I'm going to go and write the duck class. So we start with an empty class. I'm thinking, okay, what do I need to do? What's the smallest amount of work I need to do to make this pass? So I'll write an initializer, which creates a visual cortex object. And of course, this fails because there's no visual cortex. You get a name error at this point. So, the next thing to do is go and write visual cortex. Now, if you have a little think about what visual cortex does, it says, when is duck nearby? I'm going to tell the brain about this. So I'm going to implement that very small slice of functionality. So let's start writing a test for that. So this is a button to define the brain. I'm missing some context here. I'm going to imagine we set this up so that we are faking the image data from the eye, which shows a duck nearby. This is the context in which we're running this test. Okay. So how do we do this? So we create a new visual cortex object. I'm going to call it method call run. I've got this kind of idea of just running in a thread on its own, constantly processing the image data coming in. And then we'll say, when we run this with a duck nearby, with the right image coming in, they'll make expected to call the brain and say, hey, there's a duck nearby. Okay. So let's go and write some code for that. We have the test sitting here. So we'll write a run method, and it's the smallest amount of work it can do, which says, hey, brain, there's a duck nearby. Okay. We have a problem here. I'm referencing brain, but I haven't actually written this yet. It doesn't exist yet. And in fact, if we go back to the spec, I did the same thing. I was saying I expected you to call this on the brain, but we haven't written brain yet. We have no idea what this thing is. So I'm going to use this on the trick from before. I'm going to pass something in to the initializer when I create it. I'm going to say, when I create a visual cortex, I'm going to give it an object, and I'm going to check that you call something on this object. So what is this thing we're going to pass in? Well, it's a contract double, of course. It's the thing that I used before. And I'm going to create a new contract, and I'm going to call this contract greeter, because this has to do with greeting nearby ducks. Okay. This spec will not fail because there's no contracts greeter. So let's go and have a look at writing that. If we write the same as before, we just write a class and inherit from the lawyer gem, and then we'll put a single declaration there saying, you will have a method called duck nearby, which takes no arguments. Okay. So we have our spec working now. We have this thing named, and then we pass it into visual cortex. But this failed because we haven't written the initializer in visual cortex to take this argument. So the test is saying, you can't do this. You cannot pass an argument here. So we have to go and change that. So we go back to our visual cortex class. We need to add an initializer, which takes an argument. And in fact, this will be the brain that we then try and call later for duck nearby. Okay. At this point, when we run the spec for visual cortex, it passes. Everything is great, except we haven't written the brain yet. So a little bit of our code is working. We're quite happy with that. We have a chunk to go. And in fact, we're doing it to worry about this because the test is going to tell us this. If you go back to our duck spec, you can see that we said we're going to create it and we're going to create it with no arguments. And this will now fail because visual cortex cannot be created with no arguments as it expects a particular argument to be passed in. And in fact, you get an error like this coming up. So you're saying, you can't do this. Okay. So what do we do at this point? Well, we said that we're going to call it with no arguments. What do we want to call it with? Well, I've written this in such a way that you can just give it a name of a contract. You can say, I want you to call me with anything that implements this particular contract. Okay. So we look at implementing this code. We're going to say, we need to pass something in here. But what's this thing going to be? We don't have anything to pass in at this point. So we need to add another thing. So we go back to our spec. This is saying we already expect to create a visual cortex. But now we need to create another thing as well. So we expect you to create a brain object. And this is the same format. We expect you to create a brain with no arguments. Okay. So now we can go back to our code, the actual code, and we can say, right, let's create a new brain and pass it in. Now at this point, of course, the whole thing fails again because we haven't defined brain. So we can do this quickly. We can say, okay, write a new class called brain. And then we run the spec. And the spec fails because it says, you don't match this interface. So we can say, okay, let's do something of type contracts greater into the visual cortex. But the thing that you're passing in doesn't meet that contract. It has no duck nearby method. So this is the thing that we need to go and implement on brain to satisfy the spec. Okay. So we can write a spec for brain. We can say it greets ducks nearby. So we'll create a new brain object. And then we're going to call duck nearby on it. And then we need to expect some kind of behavior. And actually generate a quack. Okay. Except that we don't have quack yet. So this whole process repeats. We can say, okay, we haven't got a quack. We're going to create one. We're going to pass it into brain. We're going to create an interface or a contract that specifies what the behavior is from this. And then we're going to go and find it. When we create the duck object, it's not passing this into brain. And then we're going to repeat the whole process again and again and again until all of our tests pass. And when the tests pass, we're going to be pretty confident that we know what's happening. And of course, what we're doing here is letting the tests guide us through this process. This is just TDD, right? This is nothing particularly new. Except that we're adding contracts into the mix. Now, this is great for writing new code, but writing new code is easy. I'm not really that interested in writing code. I find that changing code is much, much harder. Because not only do you have to put in your new functionality, but you need to not break existing stuff. So I think it's really important that we focus on making change easier rather than making writing new stuff easier. So how do we make change easier? Well, we already do this using TDD. We use TDD to make refactoring easier. And in fact, more specifically, I think we use TDD to make refactoring of objects easier. So we can go in and say, I'm going to change the way this object works. But by adding contracts into the mix, I think we make refactoring of messages easier as well. So when we get our object working the way we want, we can think about the way these objects interact. And we can think about the way these objects interact. And we can think about the way these objects interact. So we can think about the messages between the different objects. And then if necessary, we can go and change the contract. We can say, the way these two things talk is not the way that I expect. And this will generate a load of failing tests. Well, it will if you break something anyway. And then we can go and just fix those things. And then we can be in a nice working situation again and start the process again and think about the messages some more. So look at two types of changes that this supports. One is just changing the message that we have. And the other is just changing the message that we have. One is just changing the message that we're going to send between objects. So we had this contract before and it defines a single duck nearby method that takes no arguments. I'm thinking, this isn't quite right. I don't want to take no arguments. I want to know how close it is. So I'm going to add a named argument onto there called distance. So I've changed the contract now. So what happens when we run the specs? Well, first of all, you can't even load the classes up because we had this declaration saying that something will already implement this contract. And the fact of breaks, it says you no longer implement the contract. There's a problem. You don't have this named argument in your duck nearby method. And the other side of the equation, when we have something that's using this contract double and trying to call something, we get a different type of failure coming up saying you can no longer call this method without any arguments. We expect you to pass something in here, something in the name. So we can make these changes to the way two objects speak and we can rely on the specs to come and tell us if there's any implications of that change. The other nice thing we can do is we can swap out implementations very easily. A little caveat here. They need to implement the same interface. So if you've got two things with the same interface, we can change one for the other without breaking any code. So we had this idea of the brain and we talked to the brain and said it's a duck nearby, but actually that's the wrong abstraction. As we develop our system, we might think we're going to break the brain up into more details pieces. We might have something like the front lobe being responsible for this high-level decision-making. So what we do is we make this implement the same interface as the brain did before. And then we can go back to our duck class, which originally created the brain and passed it to the visual cortex, and we can just replace it with front lobe. And assuming these things have got the same interface, they have the same contract, then we can do this and break nothing. And the tests, if they pass, will tell us that this is a fine thing to do. You know, we have no problem doing this. And if you don't have the same contract, the tests will blow up and say this is not a valid thing to do. So again, we're relying on a test here to tell us what to do next. And what I find is I've learned to trust this. I can trust the tests to tell me what to write next. So what happens is I start in a little isolated pieces of functionality within my system. And I focus on this and I get the test passed for that particular thing, and I start throwing things into the system. And I start to think, what's the best way to do this? And I start to think about this thing. And I start throwing things into this contract to say, remind me that I need to write this letter. I need to send this message to some other part of the system. So we focus on these little isolated things about thinking about the bigger picture. And then we focus on the messages. Now, this is probably the most important thing I want to say today. That we start to focus on the messages between parts of the system. So this is a really big idea and it's a really important idea. Now, if you look at Alan Kay, Alan Kay is a guy that coined the term object-oriented. And then later on, he showed a little bit of regret for doing this. Because in his words, it put the focus too much on objects. And that's not the most important thing. For him, the big idea is messaging. And if you forget everything else I said today, just think the big idea is messaging. We want to think about not just the bits of system we're building, but how these things talk to each other. Okay, so let's recap. What have we done today? Well, first of all, we've built a duck. We did it pretty badly. But this is quite interesting because as we built it, we noticed some accidental coupling creeping in. And I said that this is caused by ignoring the connections between objects. And another way of saying that is caused by ignoring the messaging between objects. So that's not where we want to be. So I took duck typing, really standard duck typing. And I supercharged it so that we can focus on the connections between objects. And then we get this to generate errors when we break those connections. But that's not the whole story. What we did next is we took those errors and we used it to drive our development forward. And by approaching coding in this style, we reduced this accidental coupling. I think that this helps avoid ball of mod code. And to me, ball of mod code is the problem I see most often when working in Ruby systems. You get these systems that grow quite large, and you get these systems that grow quite large, and you can't touch one part of it without that change rippling through and affecting lots of other code. So we fixed this. I think this is a big win for everybody. So this is strong duck type driven development and why I think it's a good idea. Thank you very much for listening. APPLAUSE.
 I'm not sure.  I'm pretty excited to be here.  I'm a little bit terrified but a good excited kind of  terrified.  I'm super excited.  I'm very excited.  I'm super excited.  I'm super excited.  I'm really excited.  I'm super excited.  I'm really excited.  I'm super excited.  I'm a little bit terrified, but the good excited kind of terrified.  I was a high school coming out and there's three of them talking to me on the scene,  but for some reason he decided to come here and see this talk.  Although I've asked why, I mean, did you guys look at the title and think,  yes, drawing down Patrick and Gawd and that's the kind of thing that's relevant to me.  I'm guessing that most of you are looking at the title and probably not really going to  tell what this talk's going to be about. I mean, maybe a little word you think,  but I don't know, it's just somebody with ducks driving. Maybe it was a duck's tithing,  I'm not quite sure. Well, never mind, it's just a strong duck, yeah?  Well, no, it's not going to be with an ass.  And the title remains kind of confusing, but actually, I don't really want to explain the title  quite yet, I want to give it a bit of context first.  But I'm going to say this is not a talk that's all to do with ducks.  Let's start by building a duck. Now, I'm going to say I'm not a professional duck builder.  So before I can start to build a duck, I'm going to ask you a question, how do you build a duck?  I haven't built ducks before, but I have built other things, other non-duck related things.  And in order to build something, you really need to understand what it is you're building.  So the question really becomes, what is a duck?  Now, I'm not completely in it, I've got some idea what a duck is.  But my past experience suggests that I don't know of them in enough detail.  So you need to kind of understand the duck in a lot of detail before you build it.  Now, again, my experience suggests that I can't hold all that detail on my head in one go.  I need to break it down into smaller, more manageable chunks.  So I guess the final thing I need to do before I build a duck is to deconstruct a duck  to break it up into these smaller, more manageable chunks.  Luckily for me, ducks are pretty common, it's going to be quite easy to find some kind of reference material.  So I've chosen this chart, this is a muller, this is a pretty typical duck.  I kind of break this down into manageable chunks so we can build it up again.  Now, I don't build ducks for anything, but I do write movies, so I like to think that  I understand the important aspects of a duck.  I know it's got a warplugged duck, but it's got a quagmire duck.  So we can find those bits, we can find a bit of duster quagging and we can find a bit of duster walking.  But that doesn't really cover much of the duck, there's still a whole load of duck left on the conscience for it.  Now, I know the duck floats, so maybe we've got a floating bit,  I know the ducks fly as well, so we don't find it.  And there's not much detail here, but it covers enough of the duck, I'm confident I can take this  and start to reconstruct the duck.  So it's good to go.  So we can start with a quaggy bit, which I think is a little bit like that, and then we have the walking bit,  which looks a little bit like that, and then the floating bit, and then finally the flying bit.  So this is our duck, and it's a pretty roguish duck.  But this is my first attempt, so I mean, we can refine this.  Now, one of the things that I noticed when looking at this is we have all this negative space,  and this wasn't here in the original duck that we looked at.  So I'm going to do what any good developer will do at this point, and I'm going to remove the white space, or in this case, the black space.  And we get this instead.  Now, this is a little bit roguish duck.  The next thing that really strikes me is that all these joints are really jarring, the thing doesn't fit together very well.  So look at these connections and think, you know, we can improve this.  I'm looking at it, I'm thinking, well, everything attaches to the floating bit,  so maybe we can change the shape of the floating bit, this will fit together much better.  So we can do that.  We can put something in place to support the floating bit, and then we can put a little support in place for the floating bit,  and then finally put something in place for the floating bit.  So we'll move up a bit, and this is still a pretty roguish duck.  But there's nothing obviously wrong with what we've done at the moment, except it doesn't really look like a duck.  So I'm going to go back to our original source duck, which is this guy.  I'm going to use Concentrate on the floating bit.  Now, if we take the quacking bit that we built and super-posed it, we get something that looks like this.  It's not a very good fit.  It's just a good thing, it's a wrong angle, so we can improve it.  And then, even if it gets like that, we're just going to lock quite right, but it's a much better approximation.  So if we take this and put it back in our original duck, we get this.  Now, I've improved the shape of the quacking bit, but overall our duck is worse.  And it's worse because it doesn't really leak out properly.  Now, I can fix this obviously.  If you look at the floating bit, you can see the angles wrong when the snake sticks up too far.  And of course, we can just repair that.  And it's easy to do, but I'm a little bit uncomfortable as something isn't quite right here.  And what happened was, I went back to my source, and I had changed the quacking bit to be more accurate.  And I thought this would make everything better.  But this forced me to also change the floating bit.  And that's kind of weird. I wasn't trying to change the floating bit.  This was forced upon me. This is just really bad coupling for improving it.  So I love being too excited about that, but I would bear in mind as we go on,  look at our duck. I mean, this is still a shit duck, isn't it?  So maybe let's look at improving this.  And when we last looked, we looked at the quacking bit, and I was thinking,  actually, it's all this detail we missed a lot in there.  We've got the neck bit, the brain bit, and the eye bit.  And these are all missing from our model.  So I only got to add them into the model.  And now, it's not quite right. We need to move the quacking bit, so we'll move it up to there.  And now, seeing the fish there, I'm thinking, this is the brain we made out of the provenance.  This looks more like a duck we did previously.  But actually, it's hiding a problem.  I mean, we caused some serious damage, and if I let the floating bit,  you can see what the problem is. We have this thing sticking up into the neck.  So we built the duck, but it's going to die some slow, horrible lingering death.  Now, that's probably what we want, unless we've got some doxedas here,  but we have to have to leave, please, and...  Now, we can easily fix this. We can just remove it, OK?  Because this is going to be very bad for a duck, so we can just get rid of it.  Those are fine, but this is the second time it's happened.  We've tried to change something, and then it's always another change up to us,  because we've been running out of it.  And I think generally what's happening is,  we're kind of focusing on the bits that we're building as we go along.  But we're not thinking about how these bits fit together.  And then this is causing problems for us.  And this is much more interesting than building the duck.  I didn't bring it here today to show you how to build a duck.  This isn't a problem that I'm really quite interested in.  So I want to start over, but I want to start over by focusing on this kind of problem.  So, hello, my name's John, what do you talk?  This is about ducks that are driving at ducks are very muscular obviously.  And then let's build a duck, but actually I'm not going to build a duck again from scratch.  I'll get a little repetitive.  Instead, I'll tell you what problem I came across.  I work as a contractor in London, and I had a client, and they had previously built a duck,  and they called me in to make some changes to it.  And they have a piece of code that looks like this.  And this is the thing that's responsible for quacking.  And it's fine, it works very well, but they were saying no problems, they were slightly different.  We were just going to quack, we want to quack loudly, we want to quack quietly.  I thought, this is a great contract, this is a nice easy change.  So I took the quack method, and that's never going to happen in isolation.  I didn't have soft quack, so I used my name to method to that.  And then I did the new method for loud quack.  And that worked.  And I was about to go and collect my big pilot contract to cash and go home,  and I thought, I'm going to see what else is affected by this change.  So I ran the test suite, and it looked like this.  It helped me in our aspect before.  The green dots mean everything is working fine, and crucially at the end, it says zero failures.  I was like, what? This doesn't make any sense.  I've gone and taken the method out and replaced it with two new methods, but everything looked working.  So either code is not used in the first place, in which case I can just delete it.  The test room.  So I did some quack and I found some code that looked a bit like this.  Crucially, there's a line in here which calls build quack method.  So the code was in use, which means that the test must have been wrong.  It should have been a surprise because this client was very good at what testing.  So I had a look at the test and it would be so code and it looked like this.  And the problem here is this expect line.  So when we write this line, it effectively adds a receiver for that quack method  onto the object quack unit here.  So it changes the interface before we want the code.  Now, you can avoid this. In RSpec3, for example, if you use a business double,  it will raise an exceptionally trained in this.  My concern is not that we can't avoid this kind of problem.  My concern is it's all too easy to have this kind of problem and not notice  because as you saw before, the test's all passed.  Around this time, I was planning to go quite a lot.  And I thought, this is the kind of thing you can't get on Go.  So I thought, how do you write on Go?  So I'm going to show you some Go code. Don't worry if you don't know any Go.  The code should be pretty simple. I'll try to explain it to you along.  But I'm going to write the same thing in Go.  And I'm going to start with the double brain.  Now, I'm going to start with a struct which is a little bit like the Client-In-Class.  And I'm saying it's got a single attribute called quack unit, which is a type quacker.  I'll come back to this type quacker in a moment.  But before that, I'm going to add a method on to our dot brain.  And we do it like this. And we have to say, hello, method on.  And all that does is call the quack on the quack unit.  So I'm going to come back to this quacker.  Now, because this is Go, everything has to be tight.  And I've said the type of this is quacker.  And because this is Go again, I'm going to write quacker as an interface.  And we do it like this.  And all this says is that we have an interface that's got a single method called quack.  It takes more, again, it returns nothing.  An interface isn't Go or a little bit like an interface from Java,  or maybe protocols, enclosure, or various other similar constructs and other languages.  You can't instantiate an interface directly.  What you're doing is saying that some of the implements this interface  is guaranteed to have these methods inside it.  OK. So let's write some of the implements this interface.  So I'm going to write some called bink. It's a little bit like an empty class here.  And I'm going to add a method onto it called quack.  And all this does is print a standard item.  So there's the mark. OK.  This is pretty much the equivalent of the original Ruby code I showed you.  So we can stick it all together now.  We can instantiate a new b object.  And then we can instantiate a new dot-brain object.  And we can set the attribute of quacky bit to be as a b.  And finally, we can call say hello on this brain object.  And that will call a quack object on the bink.  And that will just print quack like the standard item.  Or it's very fine.  Now I'm going to make the same change to the go code that I made to Ruby code.  So we have this b, we've got single-pack method.  And you're going to place it in the soft-pack.  And then now the new method is called void-quack.  It's actually the same change as we made to Ruby code.  OK. So what happens next?  Well, it goes to compile language.  And we try and compile it. And it says something a little bit like this.  It says you can't make that change.  Because we're trying to take b and pass it into the dot-brain.  And dot-brain expects I'm going to type quacker.  It'll check b against the interface quacker.  And it's saying we don't need that interface.  We're missing a method. We're missing a method here called quack.  So in this case, I can think, well, the interface started date.  I need to update the interface to my implementation  because implementation is more correct.  So we go back to the interface, and we just change it to have these two methods inside it.  Now that we've tried compile it, we get a different error.  It's nice saying you can't call quack on something of type quacker  because that's not on the interface anymore.  In fact, if you go back to lib.co, you can see we're still calling it old quack method.  And that's no longer valid.  So I kind of like this.  I'm taking like that the compiler tells me how to break stuff.  Now, I don't run you long, but I break stuff all the time.  And it's really nice that the compiler helped me out and say, hey, you made a mistake.  But more than that, the compiler's also hinting at how to fix things.  It's not just saying it's broken. You're on your own.  It's saying it's broken, and you missed its methods.  You should have implemented it, but we can't call this anymore.  There's another nice thing about the Go approach.  I was writing duckbreak. I wasn't thinking about beat.  I wasn't thinking about implementation of anything.  And likewise, I was writing beat. I wasn't thinking about bug brain.  I was only connected through this interface in the middle.  And even burdened out, the interface is tangible.  I can have a look at my code and I can say, oh, look,  these are the messages that flew from duck brain to beak between these two objects.  So I spoke to a friend of mine. He's a guy called Jacob.  He writes Ruby. He also was learning Go at the time.  He's a bit of a polyglot. Unfortunately, I've lost exact transcript.  It was in Skype. You can never search history in every easily.  But the conversation went a little bit like this.  I called him up and said, hey, Jacob,  wouldn't it be great with interfaces in Ruby?  And he said, in Ruby, this is easy. Just go and write it.  And I had to admit it at a point.  It is quite easy to go and implement.  So I'm back to my original duck brain.  And I thought, okay, how do we check the type of quacky bit here?  My first approach was a bit naive. I wrote some code like this.  I said, I'm going to check a response to quack.  This is just your standard duck typing.  And if it doesn't implement that, I thought, okay, I'll raise it an error.  In this case, an interface error.  And I thought, this is great. Aren't I clever?  I just implemented no method error.  Except it's less efficient and gives me less information.  Probably not the right approach.  Okay. So I went back and thought about the problem some more.  And I thought, okay, really there are contracts we're putting up between objects.  And on one half of the contract,  we have an object that promises to provide those methods.  And on the other half,  we've got an object that promises to only ever use those methods.  So inspired by this, I wrote a gem called lawyer.  The idea being that lawyer will enforce these contracts for me.  And to write a contract, it's a little bit like writing an interface and go.  You write a class and a heritage from the lower gem.  And then inside that, you write declarations for the methods you want.  So in this case, we'll write a declaration that says,  there's going to be a method called quack.  And the zero here means it takes no arguments into that method.  Okay. So how do we use it?  If we go back to our quacky bit,  all you need to do to say this is the interface is add a line at the bottom,  add a declaration, and it looks like this.  And I'm saying this implements the interface called quacker.  Okay. So what I'm going to make my change again.  So if I change quack into soft quack and then add load quack in like we did before,  what happens is when you load this file,  this line at the end gets run, the declaration of implementing the interface.  And of course, we don't implement this anymore.  So it stops. It raises an exception.  It says, you can't do this. Quacky bit does not implement this interface.  And then it goes on to tell me why it says you're missing a method  and this method is called quack.  So this is very similar to the way that it go worked.  So then we go back to interface and we think,  well, actually the class is right, the interface is wrong here,  the contract is wrong here.  So we can just change it and add the two methods into there.  So now our class loads properly.  So that's one half of the contract.  What about the other half, the person that's calling it?  Well, I can't enforce it in the compiler in Ruby.  So I thought the next best thing for me is going to be RSpec.  RSpec is a tool I use a lot to check that things are valid.  So I'm going to write a spec which validates this contract for me.  So if you write a spec for duckbrain, we had this duck nearby method.  So I'll write a spec for that.  Okay. So inside here, what we're going to do is we're going to call duckbrain  and then we're going to check some behavior.  So we're going to call this say hello method.  And then we're going to make sure that something has received quack.  But I'm not quite sure that something is yet.  So I'm going to follow the go approach and say,  okay, we're going to have something called quacker.  And we're going to pass it into duckbrain when we start duckbrain up.  And then we're going to check that we call the method and that.  So what is this quack that we're passing in?  Well, I wrote a helper for this called contract double.  It's a little bit like instance double in RSpec 3.  What it does is it creates an object.  It's got the same interface as anything that implements that contract.  So all the methods in the contract will be available in this double object.  And it will check methodality as well.  So it would say, you know, you need to have the same number of arguments  and it checks them arguments as well in Ruby 2.  So that's what we create.  And we pass it into duckbrain.  And then we run our duckbrain code and then later on we can say,  I want to make sure you call the right methods in this thing that I gave to you.  Now, of course, I'm still calling it old interface.  I'm calling quack, which we took out of interface.  We replaced it with soft quack and loud quack.  So what happens when we run this spec?  Well, we get a failure, of course, is what you expect.  And it's saying you can't call this.  You cannot call quack on this double because it doesn't exist.  It doesn't respond to that message.  So this is kind of like the go code to me.  In the go, I was quite happy because the compiler told me my rubric stuff.  I thought that was pretty useful.  We don't really have a compiler in a typical sense in Ruby,  but I've kind of faked it by saying the tool chain tells me my rubric stuff.  And this is pretty good.  And it's important to note that this is still Ruby.  And this is still just duck typing.  But I've taken it and I've made it strong duck typing.  Now, if you go to the internet and you look up the difference between strong typing and weak typing,  you're going to find that it means many different things.  It basically means what someone wants it to mean to win an argument.  So here's what I think it means to win an argument.  Actually, I think it means two things to me.  The first thing is that the tool chain is helping to enforce the types.  This is not like type annotations where it's up to you to check it.  It's not just documentation.  It will actually break, tell you early on when you break something,  when you have something that doesn't implement the contract properly.  The next thing that's important to me is we check before runtime.  So duck typing is a really lovely idea.  But quite often, it manifests itself by running a production and saying,  you tried to call this method and it's not there,  and I'm going to helpfully crash now and tell you it's all broken.  And that's not what I want.  I want it to break as early as possible so that we have time to fix things.  So we have this thing and then I thought, is it actually useful?  And initially I was thinking, yeah, this is great.  And I was thinking things like, I've got more confidence that my code will not break in production.  And it's not going to break because we've got this extra type checking in place.  And then I thought about some more.  And I thought, well, this kind of interface problem,  I've seen it maybe a few times.  And I've been writing Ruby for about eight years now.  So on average, that's once every couple of years maybe.  And worse than that, I've seen it happen,  but it's always been caught really early on.  It's very obvious when you make this kind of break.  I've never seen this get into production.  So I don't know this work, but I've solved the wrong problem.  I've solved a problem that doesn't really exist.  And I was feeling a little bit down at this point.  But it could be worse.  I mean, you guys have listened to me for 20 minutes telling you the wrong thing.  So anyway, I was a bit down, but then I thought about it some more.  And I thought, well, go with doing more than just telling me that it's broken.  The other thing it's doing is it's hinting about how to fix things.  I thought, that's cool. I've got that as well.  It's not just telling me that it's broken,  but it's giving me some hints as to how to fix it.  That's kind of useful.  And then I thought, when I'm writing objects,  they don't need to know about each other anymore.  They don't need to know about this interface in between.  And I also thought, well, interface is tangible again.  I can look at my code and I can think, hey,  I can look and see a list of messages that are going from one object to another.  And this is quite nice. I quite like this.  So I want to start over and I want to bear this in mind.  I want to look at how it's changed the way I wrote code.  Hello. My name is John.  Well, just talk and duck typing.  I want to look at how this drives our code forward now.  I want to look at how it changes my coding,  because this is obviously a picture of me photoshopped a little bit.  Okay, so let's build a duck.  Now, I want to focus on a little bit of detail here.  And I want to build just quite a lot of code coming up.  I'm going to try and step through it slowly.  But what you pay attention to is the way that I'm being driven forward  as I write the code.  So we had this bit of duck before,  and we got the eye here and it's looking around.  And I thought, well, how is this really going to work?  So I imagine the eye is kind of constantly sending image data back,  and it's going to go to something which is going to interpret that image data.  So I'm going to send it to something called the visual cortex.  And I was going to do things like shape detection  and proximity detection and so on.  And then when this thing is a duck nearby,  it's going to send a message to the brain.  It's going to say, hey, brain, there's a duck nearby.  And the brain will be responsible for the next part,  which is probably going to be quacking at it.  So it's going to trigger these other processes to make the quack happen.  Okay, so I'm going to build some scratch.  Now, when I started before with drawing the duck,  I could just put the bits of the duck onto the page.  And that works well in your drawing stuff.  But when you're writing code, you can't just put stuff nowhere.  We need a container to hold everything together.  So I'm going to start by writing a duck class.  I'm going to start by writing a spec,  because I'm a grown-up developer.  I'm going to start with just one little piece of functionality.  So I'm going to say, when we create a duck,  I want it to also create a visual cortex for us to use.  Okay, so how do we do this?  Well, we're going to block of code here,  which creates a new duck for us.  And when we do that, we're going to say,  we want to create a spec that's to also create a visual cortex object.  And then crucially, I'm going to say, with no arguments.  And we're very precise about what I expect to happen here.  Okay, so we run the spec and it fails for a very boring reason,  because we haven't written any code yet.  So I'm going to go and write the duck class.  So we start with an empty class.  I'm thinking, okay, what do I need to do?  What's the smallest amount of work I need to do to make this pass?  So I'll write an initializer,  which creates a visual cortex object.  And of course, this fails because there's no visual cortex.  You get a name error at this point.  So, the next thing to do is go and write visual cortex.  Now, if you have a little think about what visual cortex does,  it says, when is duck nearby?  I'm going to tell the brain about this.  So I'm going to implement that very small slice of functionality.  So let's start writing a test for that.  So this is a button to define the brain.  I'm missing some context here.  I'm going to imagine we set this up so that we are faking the image data  from the eye, which shows a duck nearby.  This is the context in which we're running this test.  Okay.  So how do we do this?  So we create a new visual cortex object.  I'm going to call it method call run.  I've got this kind of idea of just running in a thread on its own,  constantly processing the image data coming in.  And then we'll say, when we run this with a duck nearby,  with the right image coming in,  they'll make expected to call the brain and say,  hey, there's a duck nearby.  Okay.  So let's go and write some code for that.  We have the test sitting here.  So we'll write a run method,  and it's the smallest amount of work it can do,  which says, hey, brain, there's a duck nearby.  Okay.  We have a problem here.  I'm referencing brain, but I haven't actually written this yet.  It doesn't exist yet.  And in fact, if we go back to the spec, I did the same thing.  I was saying I expected you to call this on the brain,  but we haven't written brain yet.  We have no idea what this thing is.  So I'm going to use this on the trick from before.  I'm going to pass something in to the initializer when I create it.  I'm going to say, when I create a visual cortex,  I'm going to give it an object,  and I'm going to check that you call something on this object.  So what is this thing we're going to pass in?  Well, it's a contract double, of course.  It's the thing that I used before.  And I'm going to create a new contract,  and I'm going to call this contract greeter,  because this has to do with greeting nearby ducks.  Okay.  This spec will not fail because there's no contracts greeter.  So let's go and have a look at writing that.  If we write the same as before,  we just write a class and inherit from the lawyer gem,  and then we'll put a single declaration there saying,  you will have a method called duck nearby,  which takes no arguments.  Okay.  So we have our spec working now.  We have this thing named,  and then we pass it into visual cortex.  But this failed because we haven't written the initializer  in visual cortex to take this argument.  So the test is saying, you can't do this.  You cannot pass an argument here.  So we have to go and change that.  So we go back to our visual cortex class.  We need to add an initializer, which takes an argument.  And in fact, this will be the brain that we then try  and call later for duck nearby.  Okay.  At this point, when we run the spec for visual cortex,  it passes.  Everything is great, except we haven't written the brain yet.  So a little bit of our code is working.  We're quite happy with that.  We have a chunk to go.  And in fact, we're doing it to worry about this  because the test is going to tell us this.  If you go back to our duck spec,  you can see that we said we're going to create it  and we're going to create it with no arguments.  And this will now fail because visual cortex  cannot be created with no arguments  as it expects a particular argument to be passed in.  And in fact, you get an error like this coming up.  So you're saying, you can't do this.  Okay.  So what do we do at this point?  Well, we said that we're going to call it with no arguments.  What do we want to call it with?  Well, I've written this in such a way that you can just  give it a name of a contract.  You can say, I want you to call me with anything  that implements this particular contract.  Okay.  So we look at implementing this code.  We're going to say, we need to pass something in here.  But what's this thing going to be?  We don't have anything to pass in at this point.  So we need to add another thing.  So we go back to our spec.  This is saying we already expect to create a visual cortex.  But now we need to create another thing as well.  So we expect you to create a brain object.  And this is the same format.  We expect you to create a brain with no arguments.  Okay.  So now we can go back to our code, the actual code,  and we can say, right, let's create a new brain  and pass it in.  Now at this point, of course, the whole thing fails again  because we haven't defined brain.  So we can do this quickly.  We can say, okay, write a new class called brain.  And then we run the spec.  And the spec fails because it says,  you don't match this interface.  So we can say, okay,  let's do something of type contracts greater  into the visual cortex.  But the thing that you're passing in  doesn't meet that contract.  It has no duck nearby method.  So this is the thing that we need to go and implement  on brain to satisfy the spec.  Okay.  So we can write a spec for brain.  We can say it greets ducks nearby.  So we'll create a new brain object.  And then we're going to call duck nearby on it.  And then we need to expect some kind of behavior.  And actually generate a quack.  Okay.  Except that we don't have quack yet.  So this whole process repeats.  We can say, okay, we haven't got a quack.  We're going to create one. We're going to pass it into brain.  We're going to create an interface or a contract  that specifies what the behavior is from this.  And then we're going to go and find it.  When we create the duck object,  it's not passing this into brain.  And then we're going to repeat the whole process again and again  and again until all of our tests pass.  And when the tests pass,  we're going to be pretty confident that we know what's happening.  And of course, what we're doing here  is letting the tests guide us through this process.  This is just TDD, right?  This is nothing particularly new.  Except that we're adding contracts into the mix.  Now, this is great for writing new code,  but writing new code is easy.  I'm not really that interested in writing code.  I find that changing code is much, much harder.  Because not only do you have to put in your new functionality,  but you need to not break existing stuff.  So I think it's really important that we focus on making change easier  rather than  making writing new stuff easier.  So how do we make change easier?  Well, we already do this using TDD.  We use TDD to make refactoring easier.  And in fact, more specifically,  I think we use TDD to make refactoring of objects easier.  So we can go in and say,  I'm going to change the way this object works.  But by adding contracts into the mix,  I think we make refactoring of messages easier as well.  So when we get our object working the way we want,  we can think about the way these objects interact.  And we can think about the way these objects interact.  And we can think about the way these objects interact.  So we can think about the messages between the different objects.  And then if necessary,  we can go and change the contract.  We can say, the way these two things talk  is not the way that I expect.  And this will generate a load of failing tests.  Well, it will if you break something anyway.  And then we can go and just fix those things.  And then we can be in a nice working situation again  and start the process again  and think about the messages some more.  So look at two types of changes that this supports.  One is just changing the message that we have.  And the other is just changing the message that we have.  One is just changing the message  that we're going to send between objects.  So we had this contract before  and it defines a single duck nearby method  that takes no arguments.  I'm thinking, this isn't quite right.  I don't want to take no arguments. I want to know how close it is.  So I'm going to add a named argument  onto there called distance.  So I've changed the contract now.  So what happens when we run the specs?  Well, first of all, you can't even load the classes up  because we had this declaration saying that  something will already implement this contract.  And the fact of breaks, it says  you no longer implement the contract. There's a problem.  You don't have this named argument  in your duck nearby method.  And the other side of the equation,  when we have something that's using this contract double  and trying to call something,  we get a different type of failure coming up  saying you can no longer call this method  without any arguments.  We expect you to pass something in here,  something in the name.  So we can make these changes to the way two objects speak  and we can rely on the specs  to come and tell us if there's any implications  of that change.  The other nice thing we can do is we can swap out  implementations very easily.  A little caveat here.  They need to implement the same interface.  So if you've got two things with the same interface,  we can change one for the other without breaking any code.  So we had this idea of the brain  and we talked to the brain and said it's a duck nearby,  but actually that's the wrong abstraction.  As we develop our system, we might think  we're going to break the brain up into more details  pieces.  We might have something like the front lobe  being responsible for this high-level decision-making.  So what we do is we make this  implement the same interface as the brain did before.  And then we can go back to our duck class,  which originally created the brain  and passed it to the visual cortex,  and we can just replace it with front lobe.  And assuming these things have got the same interface,  they have the same contract,  then we can do this and break nothing.  And the tests, if they pass, will tell us  that this is a fine thing to do.  You know, we have no problem doing this.  And if you don't have the same contract,  the tests will blow up and say this is not a valid thing to do.  So again,  we're relying on a test here to tell us what to do next.  And what I find is I've learned to trust this.  I can trust the tests to tell me what to write next.  So what happens is I start  in a little isolated pieces of functionality within my system.  And I focus on this  and I get the test passed for that particular thing,  and I start throwing things into the system.  And I start to think,  what's the best way to do this?  And I start to think about this thing.  And I start throwing things into this contract  to say, remind me that I need to write this letter.  I need to send this message to some other part of the system.  So we focus on these little isolated things  about thinking about the bigger picture.  And then we focus on the messages.  Now, this is probably the most important thing  I want to say today.  That we start to focus on the messages  between parts of the system.  So this is a really big idea  and it's a really important idea.  Now, if you look at Alan Kay, Alan Kay is a guy  that coined the term object-oriented.  And then later on, he showed a little bit of regret  for doing this.  Because in his words, it put the focus too much  on objects.  And that's not the most important thing.  For him, the big idea is messaging.  And if you forget everything else I said today,  just think the big idea is messaging.  We want to think about not just  the bits of system we're building,  but how these things talk to each other.  Okay, so let's recap. What have we done today?  Well, first of all, we've built a duck.  We did it pretty badly.  But this is quite interesting because as we built it,  we noticed some accidental coupling creeping in.  And I said that this is caused by ignoring  the connections between objects.  And another way of saying that  is caused by ignoring the messaging between objects.  So that's not where we want to be.  So I took duck typing, really standard duck typing.  And I supercharged it  so that we can focus on the connections  between objects.  And then we get this to generate errors  when we break those connections.  But that's not the whole story.  What we did next is we took those errors  and we used it to drive our development forward.  And by approaching coding in this style,  we reduced this accidental coupling.  I think that this helps avoid  ball of mod code.  And to me, ball of mod code is the problem  I see most often when working in Ruby systems.  You get these systems that grow quite large,  and you get these systems that grow quite large,  and you can't touch one part of it  without that change rippling through  and affecting lots of other code.  So we fixed this.  I think this is a big win for everybody.  So this is strong duck type driven development  and why I think it's a good idea.  Thank you very much for listening.  APPLAUSE .
Strong_Duck_Type_Driven_Development_0_59.png Strong_Duck_Type_Driven_Development_60_131.png Strong_Duck_Type_Driven_Development_132_239.png Strong_Duck_Type_Driven_Development_240_347.png Strong_Duck_Type_Driven_Development_348_455.png Strong_Duck_Type_Driven_Development_456_1967.png Strong_Duck_Type_Driven_Development_1968_3143.png Strong_Duck_Type_Driven_Development_3144_7019.png Strong_Duck_Type_Driven_Development_7020_7547.png Strong_Duck_Type_Driven_Development_7548_8651.png Strong_Duck_Type_Driven_Development_8652_9563.png Strong_Duck_Type_Driven_Development_9564_9959.png Strong_Duck_Type_Driven_Development_9960_10067.png Strong_Duck_Type_Driven_Development_10068_10151.png Strong_Duck_Type_Driven_Development_10152_10727.png Strong_Duck_Type_Driven_Development_10728_13151.png Strong_Duck_Type_Driven_Development_13152_14219.png Strong_Duck_Type_Driven_Development_14220_18251.png Strong_Duck_Type_Driven_Development_18252_18839.png Strong_Duck_Type_Driven_Development_18840_20459.png Strong_Duck_Type_Driven_Development_20460_21227.png Strong_Duck_Type_Driven_Development_21228_21599.png Strong_Duck_Type_Driven_Development_21600_26387.png Strong_Duck_Type_Driven_Development_26388_27575.png Strong_Duck_Type_Driven_Development_27576_28715.png Strong_Duck_Type_Driven_Development_28716_30395.png Strong_Duck_Type_Driven_Development_30396_30575.png Strong_Duck_Type_Driven_Development_30576_31355.png Strong_Duck_Type_Driven_Development_31356_33047.png Strong_Duck_Type_Driven_Development_33048_36791.png Strong_Duck_Type_Driven_Development_36792_42515.png Strong_Duck_Type_Driven_Development_42516_45347.png Strong_Duck_Type_Driven_Development_45348_46715.png Strong_Duck_Type_Driven_Development_46716_47435.png Strong_Duck_Type_Driven_Development_47436_47555.png Strong_Duck_Type_Driven_Development_47556_49427.png Strong_Duck_Type_Driven_Development_49428_50099.png Strong_Duck_Type_Driven_Development_50100_50267.png Strong_Duck_Type_Driven_Development_50268_51371.png Strong_Duck_Type_Driven_Development_51372_51515.png Strong_Duck_Type_Driven_Development_51516_51743.png Strong_Duck_Type_Driven_Development_51744_51761.png