-
Not Synced
Hey, I am Sandi Metz and I am the
-
Not Synced
last but one speaker and that means
-
Not Synced
you have almost made it.
[audience laughter]
-
Not Synced
You get a break, there's another keynote
-
Not Synced
if you stay for that –
-
Not Synced
it's really bright up here, I'm going to have
-
Not Synced
to look at you some. So, yeah,
-
Not Synced
you've almost arrived. Even those of you who
-
Not Synced
are new have almost survived a total RailsConf
-
Not Synced
and so I think we should – let's do this –
-
Not Synced
sponsors pay the bills, they do, we're glad. [clapping]
-
Not Synced
Thank 'em.
-
Not Synced
But even more than that
-
Not Synced
"human people" organize this conference
-
Not Synced
and if you see – this is your job before you
-
Not Synced
leave today – find someone in one of those
-
Not Synced
red shirts, and say thank you.
-
Not Synced
Alright? Let's thank 'em here.
-
Not Synced
Thank 'em in person.
-
Not Synced
Going to start my clock, I have about –
-
Not Synced
I really do have about 40 minutes.
-
Not Synced
I don't have 500 slides of code this year,
-
Not Synced
though, so… it's not going to be that bad.
-
Not Synced
Yeah, let's just go. So
-
Not Synced
I'm Sandi Metz and I'm really happy to be here
-
Not Synced
and I have a talk. This years talk is
-
Not Synced
about code smells.
-
Not Synced
This is a term invented by this guy. So
-
Not Synced
it's really, uh, we did not plan that
-
Not Synced
I would follow Katrina
-
Not Synced
but it's the perfect talk to follow her
-
Not Synced
talk. She just mentioned this guy's name.
-
Not Synced
This guy's name is Kent Beck. This guy's
-
Not Synced
Martin Fowler, he's the man who wrote
-
Not Synced
this book, which is the book
-
Not Synced
that teaches us to do refactoring.
-
Not Synced
They collaborated together on the
-
Not Synced
third chapter of that book, and
-
Not Synced
it's like naming things wins and
-
Not Synced
the name "code smell", the reason why
-
Not Synced
you know that term today is because
-
Not Synced
of what these guys did back in the 1990s.
-
Not Synced
Now,
-
Not Synced
I wrote a book a couple of years ago
-
Not Synced
– before that, I wrote code for 35 years,
-
Not Synced
I went to my desk every day and
-
Not Synced
wrote code – and now, I don't do that.
-
Not Synced
I teach. I teach classes in
-
Not Synced
object-oriented design.
-
Not Synced
And in my classes,
-
Not Synced
I have occasion to ask people
-
Not Synced
if they've heard of code smells
-
Not Synced
and just like I suspect all of you
-
Not Synced
everyone in my class always says
-
Not Synced
"Oh yeah, we know what code smells
-
Not Synced
are." And then I ask them
-
Not Synced
to list five…
-
Not Synced
and no one can.
-
Not Synced
Alright, okay, now I can hear
-
Not Synced
you trying, but really most of you cannot.
-
Not Synced
I know that, okay.
-
Not Synced
And so, we all think
-
Not Synced
we know about this term
-
Not Synced
but it doesn't mean "I don't like your
-
Not Synced
code and I can't tell you why."
-
Not Synced
That is not what a code smell is.
-
Not Synced
There is some opinion involved
-
Not Synced
but really, it's not just that I
-
Not Synced
disagree with how you wrote your code,
-
Not Synced
the standard is higher. These smells –
-
Not Synced
these 22 different smells all have
-
Not Synced
very precise meanings…
-
Not Synced
and the power, the magic if you will
-
Not Synced
of this list is they've given things
-
Not Synced
names. Once you've given a complex idea
-
Not Synced
a name, if we could just
-
Not Synced
learn what that name stood for
-
Not Synced
it means we could just talk to each other
-
Not Synced
in an unambiguous way without
-
Not Synced
having miscommunications. And so
-
Not Synced
one of the things they talk about –
-
Not Synced
very often when people talk about
-
Not Synced
code smells, they prefix "code smell"
-
Not Synced
with the word "bad".
-
Not Synced
They say "bad smells".
-
Not Synced
But really, the definition of a code
-
Not Synced
smell is that it might indicate a problem.
-
Not Synced
You don't have an obligation
-
Not Synced
to filter out all the smells,
-
Not Synced
and it's actually important that you not.
-
Not Synced
It's also worth getting familiar
-
Not Synced
with code smells because they have
-
Not Synced
such great names.
-
Not Synced
Look at this list.
-
Not Synced
"Feature Envy" – that's cool.
-
Not Synced
I like this one, the one that
-
Not Synced
needs a code of conduct:
-
Not Synced
"Innappropriate Intimacy".
-
Not Synced
"Shotgun Surgery", that's another
-
Not Synced
favourite.
-
Not Synced
And so, the problem with this list
-
Not Synced
– first of all, okay, I'll confess –
-
Not Synced
I had that book for a really long time
-
Not Synced
before I read it. I had a really
-
Not Synced
hard time with it.
-
Not Synced
It's one of those books that's
-
Not Synced
like a recipe book and I've heard
-
Not Synced
people who – it would be like reading
-
Not Synced
a cookbook if you did not eat.
-
Not Synced
And so I really need the story
-
Not Synced
arc and I had very hard time
-
Not Synced
following along, like, persisting
-
Not Synced
with a bunch of recipes that were just
-
Not Synced
like etc., etc., etc.
-
Not Synced
But it turns out
-
Not Synced
it was really worthwhile
-
Not Synced
and I finally did it and actually
-
Not Synced
Katrina made me. I have to say it.
-
Not Synced
Katrina made me.
-
Not Synced
So there's 22 things on this list.
-
Not Synced
I had a Stack Overflow at 22.
-
Not Synced
It turns out there's a guy who's name
-
Not Synced
I can't pronounce – "Mäntylä" – it'll
-
Not Synced
be in the credits, he wrote a paper
-
Not Synced
where he grouped 'em. He grouped
-
Not Synced
'em in five different categories,
-
Not Synced
and through the magic of keynote,
-
Not Synced
I can do that.
-
Not Synced
This is the only reason we make
-
Not Synced
talks, so we can use the effects.
-
Not Synced
So here, let's just talk about
-
Not Synced
of things that just do not need
-
Not Synced
to be that big.
-
Not Synced
Long methods and large classes
-
Not Synced
are probably self-explanatory.
-
Not Synced
Data Clumps is where you have
-
Not Synced
two or more pieces of data that
-
Not Synced
always appear together; pass 'em
-
Not Synced
around and in together.
-
Not Synced
Long parameter list is obvious.
-
Not Synced
It might only occur once, but if
-
Not Synced
it's long enough, there's probably an
-
Not Synced
object in there somewhere.
-
Not Synced
And this other wonderfully named
-
Not Synced
thing called "Primitive Obsession", we saw
-
Not Synced
an example of that in the talk Katrina
-
Not Synced
just gave. This is like when you have
-
Not Synced
an instance of a base class
-
Not Synced
like a String, or a Number, or a Hash
-
Not Synced
or an Array, and you pass it
-
Not Synced
around to a bunch of objects
-
Not Synced
and they look at it and decide on what
-
Not Synced
to do based on something that
-
Not Synced
they know about it.
-
Not Synced
So you say, "I got a number,
-
Not Synced
it's six so I'll do thing X" or
-
Not Synced
"it's eight, I'll do something else."
-
Not Synced
If only the thing you got was
-
Not Synced
smarter, you could just send
-
Not Synced
it messages, so Primitive Obsession
-
Not Synced
is when the objects are too dumb
-
Not Synced
that you're passing around.
-
Not Synced
These things are grouped into
-
Not Synced
a category called "Bloaters".
-
Not Synced
They make code bigger than it needs to be
-
Not Synced
in the places where they use them.
-
Not Synced
The next group, this one,
-
Not Synced
these are ideas that are available in
-
Not Synced
object-oriented programming that you
-
Not Synced
can misuse.
-
Not Synced
Switch statements, you know they're
-
Not Synced
conditionals in normal people talk.
-
Not Synced
"Refused Bequest" is when it's an
-
Not Synced
inheritance problem. You have a subclass
-
Not Synced
that overrides a method that it
-
Not Synced
inherits from a superclass, and
-
Not Synced
throws an exception and says
-
Not Synced
like "I don't implement that thing."
-
Not Synced
"I refuse the bequest."
-
Not Synced
"Alternative Classes with Alternative
-
Not Synced
Interfaces" is pretty obvious.
-
Not Synced
The other thing is the Temporary Field –
-
Not Synced
it's interesting that Temporary Field is
-
Not Synced
on this list, right? Temporary Fields can
-
Not Synced
be really handy, but sometimes
-
Not Synced
they mean that you should have
-
Not Synced
made a method with that name, right?
-
Not Synced
Why are you giving it a name?
-
Not Synced
What is it about the code that you have
-
Not Synced
now that feels like it needs that name?
-
Not Synced
And so these things are all grouped
-
Not Synced
in a category that he called "Tool
-
Not Synced
Abusers". I work on a lot of
-
Not Synced
bikes, I have a garage full of bikes
-
Not Synced
and I'm an amateur mechanic
-
Not Synced
which means I have amateur tools
-
Not Synced
which sometimes involves a very short
-
Not Synced
wrench, a very long pipe, and a
-
Not Synced
hammer.
-
Not Synced
I can tell you that it almost always
-
Not Synced
turns out badly if you abuse your tools.
-
Not Synced
Alright, next. This group
-
Not Synced
this is stuff that makes change hard.
-
Not Synced
So "Divergent Change", "Shotgun
-
Not Synced
Surgery" – which we've talked about –
-
Not Synced
"Parallel Inheritance Heirarchies"
-
Not Synced
which is pretty obvious – sometimes
-
Not Synced
you have a couple of heirarchies
-
Not Synced
that each have two sides, and
-
Not Synced
every time you change something
-
Not Synced
you gotta go add or move
-
Not Synced
in both sides of the heirarchy.
-
Not Synced
These are the kind of things
-
Not Synced
that keep you from wanting
-
Not Synced
to change code or make code
-
Not Synced
hard to change. Now, notice that
-
Not Synced
almost everything that I'm talking
-
Not Synced
about… if nothing ever changes,
-
Not Synced
it's probably okay. Like, code that's
-
Not Synced
– really embarrasing code –
-
Not Synced
it's fine to keep that really embarrasing
-
Not Synced
code, you should be brave about
-
Not Synced
your ugly, embarrasing code
-
Not Synced
because it is not costing you money
-
Not Synced
if it's not changing. And so,
-
Not Synced
just because these smells exist,
-
Not Synced
you know, sometimes you should
-
Not Synced
just, like, own 'em. Be proud.
-
Not Synced
Walk away.
-
Not Synced
Don't let people make fun of you
-
Not Synced
for having bad code.
-
Not Synced
This next category…
-
Not Synced
"Lazy Class", "Speculative Generality" –
-
Not Synced
okay, on top of the effects
-
Not Synced
finding the pictures is also fun –
-
Not Synced
classes that don't do enough is a
-
Not Synced
lazy class, it doesn't justify its
-
Not Synced
existence. I'm going to skip Speculative
-
Not Synced
Generality for a minute. Data Class,
-
Not Synced
you know, we're object-oriented
-
Not Synced
programmers, classes oughta have data
-
Not Synced
and behaviour. Duplicated Code is
-
Not Synced
pretty obvious. Let me go back to
-
Not Synced
Speculative Generality.
-
Not Synced
I'm going to ask you to raise your hands
-
Not Synced
again. Who in here has ever
-
Not Synced
written some code for a feature you
-
Not Synced
thought might arrive in the future.
-
Not Synced
Keep your hands up for a minute.
-
Not Synced
Alright, I'm going to out myself
-
Not Synced
with you here.
-
Not Synced
Who in here has ever, after many
-
Not Synced
months of working around that code
-
Not Synced
ripped it out and thrown it
-
Not Synced
away? chuckles Yeah, okay.
-
Not Synced
We are bad guessers, and
-
Not Synced
you know, I love OO,
-
Not Synced
I love object-oriented design,
-
Not Synced
it's a thing that really interests me,
-
Not Synced
but this thing of Speculative Generality,
-
Not Synced
where we say, I'm going to do something
-
Not Synced
really cool in my code for some feature
-
Not Synced
I think we might need later…
-
Not Synced
this is why people say bad things
-
Not Synced
about OO. Right? This is what
-
Not Synced
they blame us for. It's primarily
-
Not Synced
things in that category.
-
Not Synced
You have to be right. The few times
-
Not Synced
that you are right have to really
-
Not Synced
be big wins that way the enormous
-
Not Synced
cost of being wrong – code is read
-
Not Synced
many more times than it is written.
-
Not Synced
The reason why we cost money
-
Not Synced
is the time spent reading code.
-
Not Synced
And if you add generality, you
-
Not Synced
increase the level of abstraction
-
Not Synced
of code. Very often that means
-
Not Synced
adding levels of indirection
-
Not Synced
which humans are terrible at
-
Not Synced
and every time you look at that code
-
Not Synced
it means its harder to understand.
-
Not Synced
So we should really try to
-
Not Synced
restrain ourselves, and not speculate
-
Not Synced
about the future. When the new
-
Not Synced
requirements come in, they'll tell us
-
Not Synced
how we wish we'd written the code
-
Not Synced
and we can do it then.
-
Not Synced
Dispensables. Sorry, here.
-
Not Synced
Ah, see I did that thing with the clicker!
-
Not Synced
Dispensables, okay, you've all
-
Not Synced
seen that now so we'll move on.
-
Not Synced
So the last category here is this group.
-
Not Synced
"Feature Envy", "Inappropriate Intimacy",
-
Not Synced
"Message Chains", and "Middle Man".
-
Not Synced
Feature Envy is when I have an object
-
Not Synced
uh, Joe down here is an object,
-
Not Synced
Joe's an object that I know about
-
Not Synced
and I send him way more messages
-
Not Synced
than I send myself. Could be
-
Not Synced
that I'm more tightly coupled to
-
Not Synced
Joe than I know, right?
-
Not Synced
Inappropriate Intimacy would be
-
Not Synced
when Joe had a bunch of private
-
Not Synced
methods and I reached in and
-
Not Synced
got them, okay, that would be bad.
-
Not Synced
laughs I really am sorta pushing
-
Not Synced
the code of conduct, aren't I?
-
Not Synced
I hope no-one was made uncomfortable
-
Not Synced
by that. Message Chains – there's
-
Not Synced
the Law of Demeter, those violations
-
Not Synced
right? You got dots. You send
-
Not Synced
messages to something you know about
-
Not Synced
and you get a response and you send
-
Not Synced
a message to that. If the types
-
Not Synced
change across those dot changes
-
Not Synced
that's a Message Chain.
-
Not Synced
Middle Man is if you have
-
Not Synced
an object that you send messages to
-
Not Synced
and it's sole purpose in life is to
-
Not Synced
forward those messages to somebody else
-
Not Synced
maybe you don't need that object.
-
Not Synced
These things are grouped together
-
Not Synced
in a group called "Couplers"
-
Not Synced
because the effect of this
-
Not Synced
is that it binds the objects together
-
Not Synced
such that even if they're
-
Not Synced
beautiful, even if you've tested
-
Not Synced
'em, even if they're little
-
Not Synced
works of art, you can't ever
-
Not Synced
reach in and get one out
-
Not Synced
and use it in another context.
-
Not Synced
They come as a bundle, all or nothing.
-
Not Synced
And so there you go.
-
Not Synced
10 minutes and 34 seconds
-
Not Synced
everything you need to know about
-
Not Synced
code smells.
-
Not Synced
Okay, but we're not done.
-
Not Synced
Now I'm going to talk about refactoring
-
Not Synced
but not very much
-
Not Synced
because you just heard a talk
-
Not Synced
on refactoring.
-
Not Synced
But there's a thing here
-
Not Synced
that people don't know,
-
Not Synced
that those guys discovered in the 90s,
-
Not Synced
that I want you to go away today
-
Not Synced
understanding, and it's this:
-
Not Synced
refactorings, just like code smells have
-
Not Synced
names and they mean very specific
-
Not Synced
things, refactorings have names
-
Not Synced
they're very specific, and they
-
Not Synced
come with recipes. Not hand-wavy
-
Not Synced
recipes, very, very specific, concrete
-
Not Synced
recipes. Here's one.
-
Not Synced
This is page 149 of Martin Fowler's
-
Not Synced
book, and it looks like a recipe, right?
-
Not Synced
It has numbers down the side.
-
Not Synced
There's little optional clauses here
-
Not Synced
for situations that might be different in
-
Not Synced
your case. You notice that it refers
-
Not Synced
to other recipes, here where the
-
Not Synced
things are in capital letters, that's
-
Not Synced
another whole recipe by itself.
-
Not Synced
It's recipes and recipes
-
Not Synced
within recipes.
-
Not Synced
All of the refactorings work in the
-
Not Synced
same way. This is not something –
-
Not Synced
we don't wave our hands and say
-
Not Synced
"go refactor" – refactoring has a
-
Not Synced
very specific definition, it's to
-
Not Synced
rearrange code without changing its
-
Not Synced
behaviour and all the ways
-
Not Synced
in which you can rearrange code are
-
Not Synced
already written down, with instructions
-
Not Synced
by people who really thought a lot
-
Not Synced
about this. And so now you know
-
Not Synced
code smells have names, and they're
-
Not Synced
real things, and refactorings have names
-
Not Synced
and they're real things, and they
-
Not Synced
come with recipes. I can give you
-
Not Synced
one last bit of news. Every code smell
-
Not Synced
maps to the Curative Refactoring Recipe.
-
Not Synced
Ponder that for a minute.
-
Not Synced
What does that mean?
-
Not Synced
Here's a cheat sheet. This one's
-
Not Synced
provided by the guys at Industrial
-
Not Synced
Logic. Notice at the top that the code
-
Not Synced
smell they're talking about is Data
-
Not Synced
Clumps. This is a little tiny definition
-
Not Synced
of a Data Clump. "[F 81]" is a
-
Not Synced
reference to page 81 in Martin
-
Not Synced
Fowler's book. The three things
-
Not Synced
on the bottom are the
-
Not Synced
refactoring recipes that are curative
-
Not Synced
for that code smell.
-
Not Synced
So this slide, I just blew it up
-
Not Synced
so you could see it,
-
Not Synced
I just extracted it from this PDF
-
Not Synced
which is a couple pages long. It
-
Not Synced
cross-references all the code smells
-
Not Synced
and refactorings in Martin Fowler's
-
Not Synced
book and also a book by
-
Not Synced
another guy named Joshua Kerievsky
-
Not Synced
called Refactoring to Patterns.
-
Not Synced
It turns out that this is all
-
Not Synced
you need to know. The problem
-
Not Synced
is solved. You do not have to
-
Not Synced
reinvent this wheel.
-
Not Synced
All you need to know is a few things.
-
Not Synced
And many of you –
-
Not Synced
at least, my experience –
-
Not Synced
the reason I wanted to give this talk
-
Not Synced
from my experience teaching is
-
Not Synced
somehow a generation has passed
-
Not Synced
since all these books were written, and
-
Not Synced
that people new to programming
-
Not Synced
in the last 15 years –
-
Not Synced
I'm a woman of a certain age,
-
Not Synced
you can tell –
-
Not Synced
if you're new in the last 15 years
-
Not Synced
you may not have this information.
-
Not Synced
I'm going to show you some code now.
-
Not Synced
I'm going to use the last 15-20 minutes
-
Not Synced
looking at code, and I'm going to
-
Not Synced
show you the practical effect of
-
Not Synced
recognizing code smells and doing
-
Not Synced
refactorings.
-
Not Synced
My class Sale is a subclass of
-
Not Synced
Persistence. You can think of that as
-
Not Synced
ActiveRecord. If you're in the back it
-
Not Synced
won't hurt my feelings if you get up
-
Not Synced
and come forward – that's the font
-
Not Synced
size of my code.
-
Not Synced
I didn't know I was gonna be in the
-
Not Synced
keynote, man, it just happened.
-
Not Synced
Let's say I have my class Foo that has
-
Not Synced
a sales_total method, takes some params,
-
Not Synced
and maybe this a controller-like thing
-
Not Synced
or something that a controller calls.
-
Not Synced
It knows the name of the Sale class and
-
Not Synced
it knows some other things, right?
-
Not Synced
It knows that Sale understands where
-
Not Synced
and it knows that the thing that comes
-
Not Synced
back as a response from sending the where
-
Not Synced
message knows sum.