JEREMY WALKER: Hi, my name's Jeremy Walker.
I'm a Developer Advocate at Google.
And I'm joined here by Max Kanat-Alexander.
We're finishing our talk on the three software
flaws in software design.
So now you're going to talk a little bit
about the method of software design
that helps you avoid all of them.
Can you give us a little more information?
MAX KANAT-ALEXANDER: Sure, so I call this system Incremental
Development and Design.
I used a bunch of English words because I'm generally opposed
to buzz words.
And so I just spelled it out as like a bunch
of words that actually mean what they mean.
Instead of some word that I invented to sell consulting.
Before I start into this, let me say that as far as I know,
this system works.
And it always works as long as you
do the actual system and not something else,
and don't add something to it.
If you do this, and it doesn't work,
then you can email me and tell me.
And either I will publish something
that fixes what I said, or I will tell you
what you did wrong.
And my email is max@codesimplicity.com.
So, many people have heard about incremental development, where
you just write one thing, and then you
write another thing on top of that,
and then you write another thing on top of that.
And many people practice this.
What I'm adding to that is incremental development
and design.
Because a lot of what people do is,
they design something up front, and then they
make incremental steps toward it.
But what I try to do is I try to rethink
my design at every step.
At every increment, I rethink my design.
And what I say is, every time I want to add something new,
the resulting system should look like I designed it
from the beginning to do exactly what it does now.
This involves a lot of refactoring.
So get really good at refactoring.
At first, it will be a little slower for you,
but over time it will pick up, and also you'll
get real good at refactoring.
Like, I've got really good at refactoring
after I started to do this.
You can do it real fast, I promise.
But it's slow at first, but you know, keep it up.
The only important thing is that you
need to have a general notion of the order in which you
should build things.
Because if you do things in the wrong sequence,
then this system won't work.
In general, you want to kind of build from the inside out.
So the way that I would think about this
is, like if I was building a YouTube app,
the first thing that I would build is the video player.
Because that's the core of the application.
That's the thing that users are actually trying to do.
And you can also think of it as what
produces a useful product as fast as possible.
So like the last time I wrote a YouTube app, the first thing
I did was I just made a rendering
surface that could play a video.
And that was it.
And it's not a very useful application
but you could give it-- I could have given it to a software
developer and said, hey look, you
can change the Video ID string in here,
and you can watch any video that you want.
It's kind of useful.
It's more useful than if I had implemented, say,
the browse interface first.
You don't want to be able to browse videos and not
watch them.
That's not useful.
But being able to watch them is useful.
So you want to find the useful core and write that first.
Or the example that I give in the book for ordering
is, if you wanted to write a calculator
that did simple arithmetic, addition, subtraction,
multiplication, and division.
You would want to do either addition or subtraction first.
Probably addition because it's sort of the base
that other things build on, and then subtraction
you could implement as a form of addition.
And then on top of that, you can implement multiplication
because multiplication is a form of addition.
Right?
And probably subtraction is simpler,
so you probably start with that and then do multiplication.
And then finally, you do division
because division is the operation that
depends on all the other ones.
The ordering of the first two is not as important.
So subtraction and addition.
Or whether you do subtraction or multiplication first
doesn't matter.
But you would never, ever want to do division first
because you wouldn't have built up all the correct abstractions
or simplicities for addition and subtraction.
So let's give an example of this.
So let's say that we're going to implement a socket.
And we know that we need sort of Unix sockets
and UDP sockets and TCP sockets.
So the first step we want to do is
we want to write-- we just decided to write a UNIX socket.
We've decided that that's probably
the simplest socket that we need.
And so first we just write a class
called Socket and SocketTest.
And this follows all of our previous rules
about the implementation of things
for the three flaws of software design.
Because you notice there's no generic system here.
Like our first step looks like we
designed a system that only does Unix Sockets.
So there's just a class called Socket,
and then there's a test called SocketTest.
Now we're going to add UDP Sockets.
Don't do this by adding IF statements.
Don't hack it in.
Redesign the system to look like it was originally
designed to do exactly these two things.
So now we now create a superclass,
an abstract superclass called Socket.
And then two subclasses called UnixSocket and UdpSocket.
And then we create tests for both of those concrete classes.
And then we might need a base class for the tests
because they might need to share information between the two
tests.
So they might need a utility module
that has utility functions that they share.
But we wouldn't write any of that.
We wouldn't write any of that generic bit until we needed it.
Now the third step is, we need TCP.
So now we have two kinds of IP Sockets.
So now we need to abstract out an IP superclass that
inherits from the main Socket class
and then gives us UdpSocket and TcpSocket.
And this looks exactly like it was
designed to do all these things.
And then we also might need to share code between the two,
UdpSocket and TcpSocket tests for IP related things.
But notice we didn't pull out IP from TCP until we needed it.
Now, depending on specifics of your design,
you might have found that it was simple to have an IP Class,
but I suspect that not.
I suspect that like, parsing the IP Headers
and then parsing the TCP Headers would actually had been simpler
to start off if you were only writing TCP in one class.
I don't know for sure, but maybe it would have been.
And so, that gives us an overview
of the system of Incremental Development and Design.
I talk a little bit more about it in the book,
and I also talk a little bit more about it on my blog.
JEREMY WALKER: Great.
Well, I had a couple questions I wanted to ask you.
You'd given this talk in another environment,
and there's some questions that came up there
that I thought were great, that I thought
the audience would love to hear.
And the first one is, if your main users are
in a certain language, what's the best
way to build in internationalization
off the bat?
MAX KANAT-ALEXANDER: Sure.
So this question deals with a point
that I made earlier in one of our previous talks.
About that internationalization is
something that's really hard to bolt on later.
So you need to sort of know about it in advance.
But you don't want to be too generic.
You don't want to go beyond your incremental development step,
right?
And so, what you want is, you want some sort of layer
or some really simple code that allows
you to add internationalization in the future
but doesn't implement it now.
So for example, if you're using gettext,
you have the underscore method that you can surround strings
by.
So just make sure that every string
is surrounded by the right method that
would do the translation because that's really the hard part.
The hard part is figuring out the strings.
Making sure that you're not trying to build sentences out
of words because you can't translate things that way,
because you have to translate whole sentences.
Just implement good practices at the beginning
that have to do with internationalization
but which don't add any significant complexity
to your development.
JEREMY WALKER: OK, so adding on to that,
you said, internationalization is
something that's really hard to bolt
on later after you've made the app.
Could you give a couple items that you've
seen in your experience that are just as hard to bolt on later
that people should think about ahead of time?
MAX KANAT-ALEXANDER: So the first thing that comes to mind
is unit tests.
It is really, really hard to add unit tests
to a system that was not designed for unit tests.
People start off, they think, well, I'll
just write some big end to end test.
Because my system is really simple, and that's all
I need to do.
But then once your system reaches 50,000 or 100,00 lines,
and you want to go back and try to unit test all the things.
And you've designed them in a way
that for example, they're all tied to the database.
So Bugzilla was designed this way,
where I didn't have any unit tests,
and everything was designed as the constructor would
load things from the database.
And that is really, really hard to test.
Particularly when the constructor is writing raw SQL.
So there's not even like a layer that you can mock out
that can give you the data you need.
So that is probably the first thing that comes to mind.
I'm sure there's other things, but that's sort of
like the big one.
JEREMY WALKER: Great.
So when you train people in these three flaws
and how to avoid them, and you go back and look at their code
maybe two or three months later, what's their biggest failing?
MAX KANAT-ALEXANDER: That they didn't believe me.
Because this is not my opinion.
This is not me stating something that like, oh,
I think this is what I should do.
This is actually the result of a fair bit of research
and experience and experiment that I
did to develop the laws in the book and these rules.
So it's not just me saying like, well I
think you should do this because I'm some sort of authority.
You could-- you don't have to ignore it.
You can ignore me or not know anything about me,
and these should still be true.
You don't respect me or talk to me or anything.
Or hire me to do anything.
But people, they just didn't-- they weren't strict enough.
They thought, well I can be too generic sometimes.
Or I can-- this is really a situation
where I just need to be overly generic.
Or I'm sure that I can write this code,
even though I'm only going to need it--
you know, I'm just going to need it tomorrow,
and I'll just write it now.
And they just didn't actually follow the laws or the rules
here completely as though they were actual rules.
JEREMY WALKER: Great.
And the last question we got was around tools.
I mean, I feel like you kind of explained it
with the incremental design.
But is there any other tools you suggest
using to help you avoid the three flaws?
MAX KANAT-ALEXANDER: Yeah.
I think having a really strong code review
process is really good.
Having automated dead code detection
can be really helpful.
Particularly code that's only run by tests.
So you have code that doesn't actually
get used anywhere in your system even
though it gets exercised by tests.
Which is by the way, occasionally OK.
If the only time that I remember, like,
well-- whenever a developer says,
no, I'm really going to use this in like five minutes.
I'm really going to use it in five minutes.
Like my next change is going to use this code.
I say, OK well, write a test.
So that way, at least it's being used by something
so that I can prove that it's actually useful,
or I can see an API that makes sense.
But I still try to say like, just wait until-- normally I
would say just wait until you need it in the next time.
So I would say code review tools.
You know, having a good bug tracker.
Having a good way to keep track of either cleanup tasks
or refactorings that you need to do can really help.
But really, code review and discipline surrounding that
is probably the most important tool.
JEREMY WALKER: Great.
Well Max, thanks for taking the time to meet with us
and talk through the three flaws and ways to avoid them.
We really appreciate that.
And thank you, audience, for joining us.
Again, if this is the first video you've seen,
we have a whole series.
Please check them out.
And we hope to see you soon.