00:00:18.240
Hi everybody! Welcome! My name is John. I'm a developer, and I'm pretty excited to be here.
00:00:24.000
I've been a little bit terrified, but I appreciate everyone for coming to see this talk.
00:00:31.039
For some reason, you’ve decided to come here and watch this talk. I’ve asked myself why that is.
00:00:40.320
Did you guys look at the title? You think, 'Yeah, Strong Duck Type Driven Development, that's the kind of thing that's relevant to me.'
00:00:45.440
I'm guessing most of you just looked at the title and probably don’t quite know what this talk is about.
00:00:51.039
Maybe you looked at the words, and you thought, 'I don't know, somebody said that's driving, maybe this is about duck typing, I'm not quite sure.'
00:00:57.039
Well, another way to phrase it is that we have strong duck typing.
00:01:03.359
It's something that sounds confusing, and the title remains a bit unclear. But actually, I don’t really want to explain the title quite yet.
00:01:10.000
I want to give a bit of context first. But I will say this is not a talk entirely about ducks.
00:01:15.439
So let's start by building a duck.
00:01:22.080
I must say, I'm not a professional duck builder. So, before I can start holding it up, I really have to answer the question: How do you build a duck?
00:01:27.439
I haven’t built ducks before, but I have built other non-duck-related things.
00:01:34.000
I know that to build something, you really need to understand what it is you're building.
00:01:39.200
So the question really becomes: What is a duck?
00:01:45.680
I’m not completely in the dark—I have some idea of what a duck is. But my past experience suggests that I don't know enough detail.
00:01:51.280
So, we need to kind of understand the duck in a lot of detail before we can build it.
00:01:56.880
Now, my experience suggests that I can't hold all that detail in my head at once; I need to break it down into smaller, more manageable chunks.
00:02:02.719
So, I guess the final thing I need to do before I build a duck is to construct it by breaking it up into these smaller chunks.
00:02:08.239
Luckily for me, that's pretty common; it’s going to be quite easy to find some kind of reference material.
00:02:14.080
So, I’ve chosen this chart. This is a mother duck—a pretty typical duck.
00:02:20.000
I’ll kind of break this down into manageable chunks so we can build it up again.
00:02:25.040
Now, I don’t build ducks for a living, but I do write Ruby, so I like to think that I understand some important aspects of a duck.
00:02:31.200
I know it has to walk like a duck and quack like a duck. We can find those bits!
00:02:36.959
We can find a bit of dust quacking and perhaps find a bit about walking. But that doesn't cover much of the duck—it leaves a lot still.
00:02:43.440
Now, I know ducks float, so perhaps we've got a floaty bit as well.
00:02:49.440
With a flying bit, there’s not much detail there, but it covers enough of the duck that I'm confident I can take this and start to reconstruct it.
00:02:56.239
So we can start with a quacking bit, which I think looks a bit like that, and then add the walking bit, which looks a little bit like this.
00:03:02.840
Next, the floating bit, and then the flying bit. So this is our duck.
00:03:08.319
It’s a pretty rough duck, but it’s my first attempt. We can refine this.
00:03:13.760
One of the things I notice when looking at this is that we have all this negative space. This wasn’t present in the original duck we examined.
00:03:19.440
So, I'm going to do what any good developer would do at this point: I’m going to remove the whitespace—or in this case, the black space.
00:03:25.760
This is still a pretty rough design. The next thing that strikes me is that all these joints are really jarring; the parts don't fit together very well.
00:03:33.360
Looking at these connections, I think we can improve this.
00:03:38.959
Everything attaches to the floaty bit, so maybe we can change the shape of that floaty bit; this would let them fit together much better.
00:03:46.640
We could also add some support for the quacking bit, and a little support for the flying bit, and finally something for the walking bit.
00:03:52.239
If we look at this now, it’s still a pretty rough duck, but there’s nothing obviously wrong with what we’ve done at the moment.
00:03:58.799
Except it doesn't really look much like a duck.
00:04:04.640
Going back to our original source duck—which is this guy—I’ll just concentrate on the quacking bit.
00:04:09.920
If we take the quacking bit that we built and superimpose it, we get something that looks like this.
00:04:15.680
It’s not a very good fit; it’s too big and at the wrong angle, so we can improve that.
00:04:21.120
If it gets like that, we’re just not quite right, but it’s a much better approximation.
00:04:27.759
If we take this and put it back into our original duck, we get this.
00:04:32.880
I’ve improved the shape quite a bit, but overall our duck is worse.
00:04:39.199
And it’s worse because it doesn’t really float properly.
00:04:44.240
I can fix this, obviously. If we look at the floaty bit, we can see that the angle is wrong and this thing sticks up too far.
00:04:50.400
We can easily repair that; it’s easy to do.
00:04:56.160
But I’m a little bit uncomfortable because something isn’t quite right here.
00:05:03.520
What happened was I went back to my source and changed the quacking bit to be more accurate. I thought this would make everything better.
00:05:10.080
But this forced me to change the floating bit too, and that’s kind of weird.
00:05:16.080
I wasn’t trying to change the floating bit; this change was forced upon me.
00:05:21.280
This is just really bad coupling creeping in.
00:05:27.520
So, I don't want to get too excited about that, but I want to bear it in mind as we go on.
00:05:33.280
Look at our duck—I mean, this is still a duck, isn’t it? So maybe let’s look at improving this.
00:05:39.600
When we last looked, we examined the quacking bit, and I was thinking there’s all this detail being missed.
00:05:45.520
We’ve got the neck bit, the braiding bit, and the eye bits; these are all missing from our model.
00:05:52.800
I’m going to add them into the duck like that. It’s not quite right, so I’ll adjust the quacking bit.
00:05:58.639
Superficially, I think this is great; we've made a bit of progress. This looks more like a duck than it did previously.
00:06:04.240
But actually, it’s highly problematic; I’ve caused some serious damage.
00:06:09.440
If I highlight the floating bit, you'll see what the problem is. We have this thing sticking up into the neck.
00:06:16.240
So, we’ve built the duck, but it’s going to die a slow, horrible, lingering death.
00:06:21.600
That’s probably not what we want unless we’ve got some duck sadists here.
00:06:28.720
We’ve actually been asked to leave. We can easily fix this; we can just remove that.
00:06:35.520
Because this is going to be very bad for a duck, so we can just get rid of it.
00:06:41.759
This is the second half of what happened; we tried to change something and then forced us to change it.
00:06:48.479
I think what’s happening is we’re focusing on the bits that we’re building as we go along.
00:06:54.479
But we’re not thinking about how these bits fit together, and this is causing problems.
00:07:00.960
This is much more interesting than building a duck. I didn’t bring it here today to show you how to build a duck.
00:07:06.080
This is a problem that I’m really quite interested in. So I want to start over.
00:07:12.400
But I want to start over by focusing on this kind of problem.
00:07:19.360
Hello, my name is John. Welcome to the talk.
00:07:24.560
This is what ducks are about—driving ducks. They are very muscular, obviously.
00:07:30.240
Let’s build a duck. But actually, I’m not going to build a duck again from scratch; I’ll get a bit competitive instead.
00:07:35.599
I’ll just tell you what problem I came across. I was a contractor in London.
00:07:41.680
I had a client, and they had previously built a duck and called me in to make some changes to it.
00:07:47.840
They had a piece of code that looked like this, and this is the thing responsible for quacking.
00:07:54.240
It's fine; it works very well. But they were saying, 'Your quack is slightly different; we don’t just want to quack.
00:07:59.840
We want to quack loudly and we want to quack quietly.' I thought this was a great contract; it was a nice, easy change.
00:08:06.000
So, I took the quack method and realized that that’s never going to happen in isolation.
00:08:12.000
I didn’t have software, so I just renamed the methods to prepare for the large quack.
00:08:17.440
That worked, and I was about to go like a big pilot contractor cash and go home.
00:08:25.199
I thought, 'I’m going to see what else is affected by this change.'
00:08:31.599
So I ran the test suite, and it looked like this. If you haven’t seen OxFAM before...
00:08:37.279
The green dots mean everything’s working fine; crucially, at the end, it says zero failures.
00:08:43.919
I was like, 'What? This doesn’t make sense! I’ve gone live, taken the method out, and replaced it with two new methods, but everything keeps working.'
00:08:49.839
So either the code is not used in the first place, in which case I can just delete it.
00:08:57.360
So, I did some grappling. I found some code that looked a bit like this. Crucially, there's a line in here.
00:09:03.600
This one calls the old quack method, so the code was in use, which means the test must have been wrong.
00:09:09.279
This was a bit of a surprise because this client is very good at those tests.
00:09:14.480
I had a look at the test with this piece of code, and it looked like this.
00:09:20.560
The problem is in this expect line.
00:09:26.240
When we write this line, it effectively adds a receiver for that method onto the quacking object.
00:09:32.720
So it changes the interface before we run the code.
00:09:39.200
Now, you can avoid this in RSpec 3, for example, using instance double.
00:09:45.839
It raises an exception in the trendiness.
00:09:51.680
My concern is not that we can't avoid this kind of problem; my concern is that it's all too easy to have this kind of problem.
00:09:57.360
And not notice because, as you saw before, the tests all passed.
00:10:04.880
Around this time, I was playing with Go quite a lot and I thought, 'This is the kind of thing you can’t get wrong.'
00:10:10.640
So, I thought, 'I’m writing in Go.'
00:10:16.000
Don’t worry if you don't know any Go; the code should be pretty simple.
00:10:21.120
I’ll start with the duck brain. Now, I understand it’s a struct, which is a little bit like declaring a class.
00:10:27.440
I’m saying it’s got a single attribute called quacker, which is a type of quacker. I’ll come back to this type quacker in a moment.
00:10:34.560
But before that, I'm going to add the method onto our duck brain, and we do it like this.
00:10:41.280
We have to say hello, methadone, and all that does is call the quack.
00:10:48.000
Now let’s come back to this quacker, because in Go, everything has to be typed.
00:10:55.680
So, I said the type is quacker, and because this is Go again, I’m going to write quacker as an interface.
00:11:02.399
We do it like this. All this says is that we have an interface called quacker.
00:11:08.640
It has a single message called quack, which takes an argument and returns nothing.
00:11:14.560
Interfaces in Go are a little bit like interfaces in Java or maybe protocols in Clojure or similar constructs in other languages.
00:11:21.120
You can't instantiate an interface directly; all you’re saying is that something implementing this interface is guaranteed to have these methods.
00:11:27.440
Okay, so let’s write something that implements this interface.
00:11:33.520
I’m going to write a struct called ‘Beak,’ which is a little bit like an empty class here.
00:11:39.280
I’m going to add a method onto it called quack and all this does is print the standard out saying quack.
00:11:44.320
Okay, this is pretty much the equivalent of the original Ruby code I showed you.
00:11:51.760
So, we can stick it all together now—we can instantiate a new Beak object and then instantiate a new Duck Brain object.
00:11:57.760
We can set the attribute quacking bit to be this Beak and finally, we can call hello on this brain object, which will call the quack on the Beak.
00:12:04.928
And it will just print ‘quack’ as the standard output.
00:12:10.240
All works very well.
00:12:16.320
Now, I’m going to make the same change to the Go code that I made in the Ruby code.
00:12:22.000
So, we have this Beak and we've got single pack methods; we replaced it with quack loudly, and now the new method is called ‘duck world quack.’