-
STEVEN G. HARMS: Hi. Good afternoon everyone.
-
We're starting a little bit late, I think,
-
because of AV issues. So I think we're gonna
have to breeze through.
-
So you are in the right place if you wanted
to hear
-
about preferring object-orientation to metaprogramming.
-
My name is Steven Harms, just a brief rundown.
-
I live in San Francisco like a great many
-
of you. You can Tweet at me @SGHarms. I'll
-
also supply an email address if you like to
-
interact in a slower form of communication.
-
What I'd like to do is talk to you
-
about preferring object-orientation to metaprogramming.
Now I have to
-
admit I'm a little bit scared to be up
-
here, because two years ago I was extolling
the
-
virtues of metaprogramming left and right
in New Orleans.
-
So, well thank you very much.
-
But I, you know, you can all tell your
-
significant other that, apparently, one time,
a programmer did
-
admit that he or she was wrong. So I
-
was wrong. And I hope to light, guide you
-
on that journey, sitting up here, or, rather,
standing
-
up here and saying you're wrong is a very
-
interesting experience. But I have been advised
that I
-
should take my fear out of my back pocket
-
and put it into me.
-
I would like to say, I love metaprogramming.
It's
-
a fascinating topic. It's rich. It's something
very special
-
to Ruby and I first got exposed to it
-
at RubyConf 2007, hosted by the, our friend
Dr.
-
Jim Freeze - Jim might be here. I don't
-
see him.
-
But I can't remember who it was, but somebody
-
at lunch showed me this thing here, this thing
-
on line four, where I- I don't know where
-
you are, but when I saw that I was
-
like, this is crazy. What, what language is
this?
-
At the time, I was coming from Perl and,
-
regrettably, Perl made solving some problems
exceedingly painful.
-
So I was pretty much on, I was undecided
-
between Python and Ruby, but when I saw that
-
thing, I was like, whatever language uses
that to
-
do something like define methods, I, I was
won
-
over.
-
And then I saw something crazy like this,
is
-
that you could create instances and just put
methods
-
only on that instance and not let other classes
-
have access to it. I was thinking, this is
-
why my Perl has sucked so bad. The reason
-
Perl sucks is because Perl sucks and it doesn't
-
have awesome constructs like this. It is not
because
-
I'm an ignorant, uninformed programmer. It's
because Perl sucks.
-
And if you're looking for something that was
absolutely
-
about to prove to you how bad Perl sucked
-
and how awesome I was, it was that I
-
could basically invoke methods that didn't
exist, and Ruby
-
would help me out. It would let me just
-
keep stringing that noose along so that I
could
-
hang myself good and proper later on. It would
-
not blow up on me and I could say,
-
hey, don't blow up, I want you to do
-
something else. In this case, summon hateful
spirits of
-
the netherworld as inspired by H.P. Lovecraft.
-
But time passed, and thanks to my tools that
-
I showed you, the metaprogramming tools, I
was able
-
to build really, really complex software.
And I was
-
so proud of what metaprogramming made possible
that I
-
went to New Orleans in 2011 and told all
-
of you - some of you - how great
-
metaprogramming was and what it could provide
you.
-
I had to live with that code for two
-
years. Which involved me having to refactor
it, having
-
to own it, and some of my opinions might
-
have changed. So that's what this talk is
about,
-
is how might your opinions change if you are
-
the maintainer of the heavily metaprogrammed
library.
-
We're gonna be guided by three questions here.
-
The first question is, when should I use metaprogramming?
-
The second is, when should I prefer something
else?
-
And if something else, what is that something?
-
Regrettably, every time you talk about metaprogramming,
you have
-
to define it first. Ruby Rogues number twelve,
Ruby
-
Rogues number eighty, my talk in 2001, you
always
-
have to define the terms, or else you're liable
-
to get cited and get kicked out of RubyConf
-
to come.
-
So my definition - oh, excuse me, wrong button.
-
My definition, definition is that you're writing
code that
-
redirects passed messages at runtime. Or you're
altering the
-
structures that do the passing at runtime.
At runtime.
-
You see, Ruby is an interpreted language.
So there's
-
really no difference between compile time
and execution time.
-
Everything lives in the space of runtime.
But I
-
would like to ask everyone's indulgence for
a moment
-
to imagine that there is a magical phase right
-
before runtime called parse time. And parse
time is
-
where your constant tree is established. It's
where all
-
of your libraries are required. And then there's
something
-
else that happens once you enter the main
thread
-
of execution.
-
It's that main thread part is runtime, the
part
-
that happens before is parse time.
-
So redirected parse, past messages at run
time, providing
-
and altering those structures at runtime.
-
That's metaprogramming. If we've all agreed
that that's the
-
standard base of reference, the question that
I asked
-
in 2011 was how will I know that I
-
should use metaprogramming? And I took that
question and
-
that time to be a reflection on, how do
-
I know I'm smart enough to use metaprogramming?
-
And at that time I was feeling pretty damn
-
smart, and I wanted everyone else to feel
that
-
smart and to jump off that metaprogramming
cliff.
-
I think the question now is, when should I
-
ever use metaprogramming? And I think I have
a
-
new answer for that one. I think the answer
-
is never.
-
Oh, all right, all right, I'm gonna hedge
my
-
bets. Practically never. On the cons- in the
contrary
-
case, the question should be, well, when should
I
-
use something else? Always. Eh, practically
always.
-
The trouble I said in 2011 was that we
-
had unclear guidance about how to move forward
in
-
metaprogramming. It tended to be something
that was kind
-
of showed by people at conferences and something
that
-
was kind of obliquely referred to. But it
was
-
never really explained as, here's a technique.
Here's how
-
you can grow better in it. Here's how you
-
can learn more about it.
-
And there's a good reason for that. I'll quote
-
Tim Connor, who I also quoted in 2011, was
-
the first rule of metaprogramming is you don't
talk
-
about it, because you'll get people to use
it.
-
Accurate.
-
And then the second rule is that, when you
-
do introduce it, you introduce a level of
complexity
-
that most people, due to just unfamiliarity,
will not
-
understand how to parse. And now here's the
sentence
-
that kills me, is that unfortunately, you
cannot simply,
-
sorry, that was a typo, be told not to
-
metaprogram. You must see it for yourself.
-
That's the part I take issue with. I can
-
show you, I believe, in the remainder of this
-
presentation, of why you should not use metaprogramming.
In
-
short, I want you to say no to metaprogramming.
-
In fact, if you're from the Pacific Northwest,
I
-
want you to say cacao to metaprogramming.
-
Now, I'm gonna take a bit of a, a
-
side long step here, and I'm going to kind
-
of fall in the spirits, follow in the spirit
-
of the philosophers Gilles and Guattari. I'm
going to
-
take apart the term metaprogramming itself.
It is a
-
bad term.
-
First of all, it's hard to define. Every speaker,
-
every time they use the word metaprogramming,
has to
-
come in and define what they mean in order
-
to try to establish some sort of consensual
basis.
-
If the term has to be renegotiated all the
-
time, what is its value? Nothing.
-
Secondarily, I, I have a theory that it gets
-
by a lot of time because it has this
-
really awesome Greek prefix at the beginning
of meta.
-
When I was that young programmer in Austin,
somebody
-
showed me metaprogramming, and I thought,
my gosh I
-
am so stupid. I am so ignorant. I don't
-
know what metaprogramming is. I, I, I missed
that
-
class in the CS curriculum. I don't know what
-
it's about.
-
And, and having dug into it, I've dug into
-
it and I understand it now and it's just
-
a bad idea. And it skates by because it
-
has this cool topic. Write a CFP, include
the
-
word metaprogramming, you'll get a speaker
slot. I know.
-
It's a bad term. But it's also a bad
-
technique. Recall, well, foremost, let me
say that it
-
has a bad conceptual framework, and I will
demonstrate
-
this. The code itself, Ruby will tell you
don't
-
do this. You can choose to ignore it, like
-
me, but Ruby will try to help you avoid
-
this trap. And lastly, I want to talk a
-
little bit about normative social standards
visa vis metaprogramming.
-
So recall that when we talked about my definition
-
of metaprogramming, is we focused relentlessly
on this concept
-
of runtime. And here's the interesting this
is that
-
runtime specifies a temper, a temporarily
to these clauses,
-
but here's the thing. Check out the verb -
-
alters, redirects.
-
These are verbs that express surprise. These
are verbs
-
that express something not doing what was
expected. Metaprogramming
-
is writing code that willfully does something
that's surprising
-
and contrary to convention. I think there's
a special
-
word for that, right. You write code sometimes
and
-
it does something that you don't expect, right.
-
That one. Yeah. Metaprogramming, in effect,
is engineering bugs
-
that do the right thing. Not only that, but
-
they do it adventitiously. I'm including this,
not because
-
I'm talking down to you, but I do realize
-
English isn't the first language of some people
in
-
the audience.
-
Adventitious - coming from another source.
Not inherent or
-
innate. If your code does not innately do
the
-
right thing, that means that it's more likely
to
-
do the wrong thing. So you are quite literally
-
putting yourself in a position of possible
accident.
-
Or, in short, metaprogramming is a series
of aberrations
-
that just happen to produce the right output
most
-
of the time. Or, at least, as much as
-
your test coverage says that they produce
the right
-
output.
-
Missing image. Again, another form of bug.
It's a
-
reminder of that when you think things are
OK,
-
they are, in fact, not OK. So let's talk
-
about how a, whoa, it's a broken image. Well,
-
that's a, that's a new bug for me too.
-
Let's see. OK. Well, I'm sorry. I can't show
-
you this one cause the image isn't on this
-
asset.
-
But the point being is that if you try
-
to use a heavily metaprogrammed library, you
know that
-
thing in IRB or Pry where you can do
-
tab tab to complete a method name? Metaprogrammed
methods
-
do not appear as part of that. That is
-
Ruby trying to tell you, hey, I don't know
-
what you're talking about, and the conventions
and expectations
-
that I have, you are not following. If you
-
choose not to follow those conventions, it's
on you.
-
And because it's on you, you have the obligation
-
to write extensive amounts of test coverage.
In this
-
case, I had to write one thousand six hundred
-
and forty-six assertions to feel like my library
was
-
doing the right thing, whereas if I had chosen
-
smaller, more constrained scopes of my objects,
I would
-
have felt more comfortable having fewer of
them.
-
As it stands, I had to write near two
-
thous- well, all right, near sixteen hundred
assertions to
-
feel comfortable in my code. You should never
have
-
to write that many assertions to feel comfortable
in
-
your code.
-
I'd also like to point out that, as I
-
showed in the earlier sample, when you have
metaprogrammed
-
code hinging on method missing, if something
blows up,
-
you're catching the method missing error.
Instead of your
-
error bubbling up to something saying hey,
you messed
-
up, you need to backwar, backtrack this and
fix
-
it. Instead now you bear the responsibility
for handling
-
how method missing works.
-
And because of that, you're taking on an additional
-
cognitive burden, and you're taking on an
additional -
-
that you just should not have to take on.
-
I spoke about social conventions. You don't
have to
-
listen to me and you don't necessarily have
to
-
listen to the code, but you could listen to
-
some dude on Twitter, which is what a lot
-
of people do apparently. Joshua Timberman
said, well actually,
-
he didn't say, he metasaid, somebody- he metaTweeted
that
-
someone said that his amount of disdain for
Ruby
-
projects is directly proportional to the amount
of magic
-
it contains.
-
Metaprogramming and intercepting method missing,
bolting on behavior onto
-
instances. All of these things, in sum total,
account
-
for magic.
-
So, what I would like to do is put
-
an end to quote metaprogramming. What I would
like
-
for us to do is to retire the term,
-
retire the talks, and move on. I would like
-
for this to be, you know, apologies to Francis
-
Fukiyama, I'd like to be the, the last man
-
standing on the topic of metaprogramming.
I think we
-
all need to move on and let's just close
-
the door.
-
Now the question is, if you're going to say
-
that something is bad, what do you recommend
you
-
replace it with? So what I would like to
-
do is talk about the replacement to metaprogramming.
The
-
replacement to metaprogramming would, of course,
be something like
-
anti-metaprogramming. It would be taking out
all of that
-
magic. It would be taking out all of your
-
method missing calls, your conts get calls.
It would
-
be taking out all those instance evals, class
evals.
-
It would be taking out all these weird clojure
-
things.
-
Anti-metaprogramming code would be deducible
from the parse time
-
state, that is to say, you could look at
-
the code at rest and figure out what's going
-
on. I alluded earlier that I considered metaprogramming
often
-
to be a type of bug. Often to understand
-
the state of the application at the time,
you
-
wind up having to use debugging tools.
-
As you're saying, well why is this not doing
-
what I expect? What do you have to do,
-
you have to drop in a Pry binding or
-
you have to put in ByeBug or a debugger
-
statement just to figure out what's going
on. And
-
the reason is is because you're doing weird
stuff
-
at runtime. Don't do it.
-
I also believe that code, anti-metaprogramming
code, also known
-
as good code, demonstrates its reason and
its purpose
-
in itself. That is to say, it's obvious. So
-
let's take a look at some anti-patterns that
I
-
implemented around metaprogramming.
-
First one - def - oh man, that's really
-
unfortunate. Hmm. Let's see here, what can
I do
-
about this? I want to know why it's showing
-
up on my screen. Is that? Is it? I
-
don't know. OK. Yes!
-
AUDIENCE: Yay!
-
S.G.H.: Thank you. Thank you all. Whew. Yeah,
master
-
debugger back here. Thank you. Wow, OK. Thanks
so
-
much. That was really helpful. Go team. Obviously
some
-
garbage collectors in the audience.
-
I would like to point out define method. Define
-
method - Rubyists new to, Rubyists who are
new
-
to language may be surprised to find out that
-
you can define methods based on taking out
terms
-
and then, and creating them dynamically at
runtime. Don't
-
do this. This is bad. And you may say,
-
oh well, this isn't so bad, and you have
-
this thing called prefix. You have an inner
and
-
an outer. I get what's going on here.
-
But the trouble you're gonna have is that
it's
-
not grep-able. And by grep I mean you can
-
use Ack or Rack or some sort of search
-
or, through your code. If you're looking for
the
-
method that's called tear_down_the_pop_singer,
you're not gonna find it,
-
because it's somehow being fabricated at runtime.
You basically
-
made your code opaque to other introspective
tools. Don't
-
do that. It's so much better just to write
-
it out.
-
And if you're complaining about writing it
out, get
-
a better editor. Because, really, your editor
should be
-
able to take care of this amount of pain
-
for you.
-
Again, it has low grepability and it has very
-
poor graspability. An alternative I propose
is just to
-
use plain old, good old def, right. Here it
-
is. Where is tear_down_the_pop_singer defined?
Right there. Or excuse
-
me. Right, right there. Yeah.
-
The ability to resolve problems is so much
easier
-
when you have this available to you.
-
I'd also like to talk about another anti-pattern
that
-
I've seen recently discussed is the junk drawer
module.
-
Now if you took my previous recommendation
that you
-
actually define your methods, you may say,
well I've
-
created a large class. I don't like that.
So
-
what I'm going to proceed to do is I'm
-
going to bubble that out into a module and
-
then I'm gonna include that module into the
class.
-
Don't do this.
-
This is a classic bad anti-pattern. Because
what you've
-
basically done is you've created a name space
that
-
has absolutely no purpose for its existence.
It is
-
important that we, as programmers, when communicating
with other
-
programmers who will read our code and not
our
-
comments, we need to be able to understand
what
-
is going on in this module. What is the
-
relationship? Why is raise_the_roof with tear_down_the_pop_star?
There is no
-
good reason. We have no intentionality behind
that module.
-
And as a result of it, our class and
-
our module name will be entirely opaque to
any
-
other programmer who comes along.
-
Again, it's obvious, moderately, because it's
grepable. But the
-
graspability is it is poor, and as you add
-
additional modules, that graspability will
go down precipitously.
-
So don't create junk drawer mixins using Ruby's
modules.
-
I think Sarah may have brought this up recently.
-
She said, you know, modules may solve the
size.
-
You've got fewer lines of code. But you've
done
-
nothing to illuminate, to open the mind of
a
-
programmer who's coming along to this particular
bit of
-
code.
-
You could get slightly better. What if you
change
-
those mixin names and gave them something
like, some
-
hint of what they are. But really, you're
not
-
getting much for that level. You still have
the
-
greppability. Moderate graspability. But it's
trending down.
-
Here's a nifty pattern that totally sucks.
I did
-
this one heavily and I'm so embarrassed to
show
-
it. I'm gonna show it right now.
-
What would happen if, instead of actually
creating modules,
-
you decided to create anonymous modules? Wow.
You just
-
completely hung yourself. That was awesome.
And the reason
-
you've hanged yourself is because, look, you
get this
-
really nice thing by looking at Ruby's ancestor
chain.
-
Cause you can ask an object, or rather, ask
-
an object's class what the inheritance chain
of it,
-
of it is.
-
We'd say, where'd you get methods? Where do
you
-
get properties? So I can see class, method
deffer,
-
gets modules from pop_singer_moves and housing_moves
and object and
-
kernel and basic object. That's great. Guess
what? When
-
you use anonymous modules, you get none of
that.
-
So congratulations. You got to use a really,
really
-
cool stylistic invocation that made your code
more opaque.
-
That one hurt.
-
So, again, there is really no hope at this
-
point. You've really, really shot yourself
in your foot.
-
Here's another anti-pattern that I completely
committed. How about
-
this one? What if you wanted to make a
-
class that's including a module do something
crazy when
-
it included that module? Wouldn't that be
completely opaque?
-
Wouldn't that be impossible to understand?
yes.
-
Look at this. This is, this is humiliating.
You
-
may not be aware that module implements a,
a
-
call-back method, so that when you include
a module,
-
magic happens. And what if, in that silent
bit
-
of magic, you decided to do magic back on
-
the thing that included the module?
-
This is just pure insanity. I don't even know
-
what I was thinking. I, I don't do drugs,
-
but I don't know what I was thinking. I,
-
I can kind of see, like, a bit of
-
nobility in here. There's a hint of the desire
-
to want to invert dependencies, but if you
choose
-
to invert a dependency, which we'll talk about
in
-
just a moment, there are many more obvious
ways
-
of doing it. So don't do this.
-
So, again, low greppability, abandon all hope.
Low graspability.
-
Abandon all hope. Do not do this.
-
Here's an interesting pattern. Here's where
things start getting
-
a little bit better. What if you chose to
-
use the strategy pattern to apply behavior
to the
-
inverted class? So let's take a look at this.
-
So what if I decided to put those housing
-
moves in a module that I'm gonna call a
-
strategy? Now I realize someone's gonna take
me to
-
task on Twitter and say, you're dumb. You
don't
-
understand what the strategy pattern's about.
It's not modules,
-
it's classes. OK, I get it.
-
But for the sake of this argument, let's kind
-
of keep with the idea that what, what is
-
happening in these strategies is that I've
basically given
-
this mixin a meaningful name. I've said, this
mixin
-
isn't just a mixin of some random mod- rad-
-
random methods that you want to throw into
your
-
class. What I'm saying is that there's an
intention
-
behind it. It's that if you're interested
in housing
-
moves, you're going to have some relationship
with this
-
particular strategy.
-
So here's how I chose to invert that dependency.
-
Is what happens is that when you create a
-
method deffer class, it then proceeds to instantiate
a
-
class called apply_core_strategies, passing
itself. The apply_core_strategies then looks
-
at the essential strategies, intelligible
for the next programmer,
-
of housing_move strategy and pop_movesto_strategy,
then it proceeds to
-
bolt those on, on the calling class.
-
So I feel like, at this place, we're actually
-
getting a hint of the, of, we're starting
to
-
tease apart some of the metaprogramming. We're
starting to
-
create small, tiny classes that bear responsibility
for certain
-
tasks of thinking. And I can definitely say
the
-
woman who taught me to start thinking this
terms
-
was Sandy Metts. So I can't say enough about
-
how she dug me out of my conceptual bad
-
spot by introducing me to some of these ideas.
-
Again, the obviousness is moving, is moving
upward. The
-
reason is is that we can always take a
-
look, you say oh well he implemented this
method
-
poorly or this method poorly, or this strategy
is
-
poorly named, or why are we doing this with
-
modules? Why don't we use classes so that
they
-
can have a meaningful state? We're trending
in a
-
good direction. We're trending out of opaqueness
and difficulty
-
that we normally associate with metaprogramming,
and we're moving
-
to something that's more deducable, that has
smaller scope
-
that's greppable.
-
It's also more graspable. Again, fewer lines
of code,
-
higher graspability. that's it.
-
On the topic of good O-O, I, I don't
-
have to say Sandy taught me everything I can
-
stand to know on the topic. The heart of
-
what makes metaprogramming so bad is that
it will
-
pry- that it puts a very heavy cognitive burden
-
on the developer. And what I like to say
-
is that it puts a mind of god burden
-
on the developer.
-
Specifically, if you look at metaprogramming
techniques that break
-
object incapsulation, you can actually start
to see that
-
metaprogramming is the last refuge of the
procedural programmer.
-
You have to hold in your mind all of
-
the possible methods and all of the possible
variables
-
that could be called and all the possible
code
-
paths.
-
If you're saying no, Ruby, don't do your default
-
blow-up behavior on Method Missing, you're
saying, I'll take
-
that responsibility on. If you're cracking
over someone else's
-
class, you're saying, don't worry, thread
class, I'll take
-
responsibility in making sure that all your
interfaces always
-
work in all the possible code.
-
And if you basically say, oh I need to
-
define core methods within the Ruby language
by defining
-
a kernel method, what you're saying is, don't
worry
-
Ruby, I got you on this one. You are
-
deficient, I know better. Am I really ever
gonna
-
say that to Matz?
-
No. I'm not.
-
Loveable angry panda Rein Henrichs has this
pretty, pretty
-
succinctly said, is if you can go around monkeying
-
with the core object class or the core fundaments
-
of the Ruby universe, he and his loved ones
-
should be under no obligation to maintain
your level
-
of insanity.
-
In fact, what I love about RubyConf is that,
-
as you write your talk, you write it in
-
a vacuum. Then all of the sudden you come
-
into RubyConf and you pick up these pneumatic
currents
-
that are floating about. And what I've seen
in
-
a number of talks, particular yesterday, was
Ruby is
-
maturing. And as a result of it, we now
-
have a nice variety of gems where people have
-
shared their solutions to famous problems
that other developers
-
might encounter.
-
But when you metaprogram, you make it so that
-
your code can't interact predictably with
other peoples' libraries.
-
Jason Clark talked about extending gems. He's
talking about
-
problems that he had at New Relic with other
-
developers stomping on his name space. I mean,
these
-
are developers who sit, you know, in San Francisco,
-
so it's not a very big place.
-
So he could see these developers every day
and
-
they still managed to step on each others'
toes.
-
What happens in the case that your gem does
-
something where it overrides some poor kernel
functionality, or
-
it overrides the core functionality of thread
or module
-
or object? Your mind of god is going to
-
be put in direct contention with someone else's
mind
-
of god, and I'm not sure how that ends,
-
depending on your theology, but I'm pretty
sure it's
-
bad for us.
-
Also, Emily, yesterday, talked a lot about
writing good
-
APIs for other developers to be able to make
-
use of your gems. Again, metaprogramming requires
that everyone
-
else enter your mind of god in order to
-
code around the barriers that you built. So
I
-
really, really discourage any pattern which
looks anything like
-
taking on the mind of god, taking on the
-
full level of responsibility for managing
all levels of
-
interaction.
-
Again, these three particular recipes, and
the metaprogramming cannon,
-
are extremely dangerous. Greppable? Eh, I
don't know. Sometimes.
-
In, depending on how things are made. Are
they
-
graspable? Not really. They usually have very
unpredictable behavior.
-
What I prefer instead are these two bread
and
-
butter solutions out of the object-orientation
playbook. Strategies and
-
delegates. I showed strategies a little bit
earlier, where
-
what would happen is that you say, OK, well
-
including class, I want you to take on some
-
behavior, but managing that bolt onto the
behavior can
-
be handled somewhere else.
-
And this is a type of a interaction that
-
should be intimately familiar to all of us.
As
-
Americans, well, those of us who are Americans,
we
-
are bred on the model of the assembly line.
-
The Henry Ford model. The great innovation
of Ford
-
was not the car but the assembly line.
-
We think about the chassy coming down that
assembly
-
line, it stops at a little station. That station
-
puts on wheels. The next station puts on windows.
-
The next station puts on doors. Hopefully
it puts
-
on the doors before the windows, but, yeah.
Depending
-
on which car you have, I suppose.
-
But the point being is that the idea that
-
you need to have the chassy go hey, I
-
need wheels and bolts it on itself. Hey, I
-
need windows, hey I need doors. You're making
that
-
chassy participate in the mind of god type
behavior.
-
You should think of the classes as you construct
-
them as being on an assembly line, delegate
that
-
big piece you're building to a station. Ask
for
-
it back. Move down to the next station. Ask
-
it back.
-
One other anti-pattern is laziness lookups.
Oh, excuse me,
-
whoops.
-
Constant_get and constantize. These make your
code virtually ungreppable,
-
as it's very hard to find that place where
-
somebody chose to, why did they constantize
some string
-
that came from the user? Who knows. It's ungreppable.
-
Don't do it. I like to type it out,
-
and I'll just ask the simple question - what's
-
wrong with a hash? I mean, a hash is
-
so greppable, a hash is so friendly. You look
-
at it, you know what's going on. Why do
-
you need to use constantize? Just, to be cool?
-
Don't. Don't do that. Don't do it.
-
So I'd like to talk about principle techniques
for
-
happier programmer. Make lots of small, greppable
classes. Lots
-
of them. There's nothing wrong with lots of
classes.
-
A lot of people say, well, it requires me
-
to open up a lot of files. If that's
-
the problem, learn your editor better. Because
editors are
-
now very good at cutting vertically as well
as
-
horizontally.
-
Things like C-tags, I know, Sublime, FuzzySearch.
Be more
-
comfortable creating lots and lots of tiny
classes. Prefer
-
composition and delegation. That is to say,
don't look
-
to have a mind of god object that rigs
-
itself together. Look for collaborators within
your object space
-
to provide small, little objects, which are
experts in
-
singular particular fields.
-
The pattern, or the, the fancy name for this
-
is, is injection. That's when you create a
something
-
special and then pass it in to an obect
-
that will create a, a concert of those passed-in
-
objects.
-
I encourage you to love dep- inversion. Inversion
is
-
just, it opens up so many pathways of thought,
-
is that if you think that you need to
-
manually bolt everything on yourself, participate
in that god
-
pattern, inversion is, is freedom from that.
When you
-
engage in the god pattern delusion, what you
are
-
basically saying is that I don't trust anyone.
You're
-
being a totalitarian. Build small objects.
Yield to those
-
objects. And trust those tiny objects to do
the
-
right thing.
-
Lastly, a, a thing that's kind of been in
-
the, in the medics of this conference is well,
-
what to do about comments. Should we have
comments
-
or not comments? If you embrace the strategy
patterns,
-
your strategies will usually reflect that
thing you're commenting.
-
Like, deal_with_bobs_brain_dead_hack_for_dead
locks. If you name a strategy that
-
way, it's very obvious why you did it, what
-
it's for, and it turns out that the object
-
name space can teach other readers of your
code
-
as much about your code as a comment could.
-
Further, comments age rapidly. Code is always
gonna be
-
executed. So keep in mind that your code will
-
always speak louder than your comment.
-
For further reference, practical object-oriented
design with Ruby. I
-
can't sing it highly enough. I was, as a
-
programmer, I was very frustrated. I was very
painted
-
into a corner. In seven chapters, Sandy Mets
can
-
help you out of your particular corner and
will
-
invite you beyond. By beyond, the next book
that
-
helped me get further out was refactoring
the Ruby
-
edition. And thirdly, the design patterns
in Ruby book.
-
I don't know if they intended it, but Adam
-
and Wesley have basically built a stack of
free
-
books that are superb at moving you from a
-
beginner to intermediate Rubyist to maybe
an intermediate advanced
-
object-oriented, object-loving Rubyist.
-
So winding up, metaprogramming. Don't write
more of it.
-
But let's just stop. Do understand it. The
reason
-
you have to understand it, is well there's
a
-
whole lot of legacy code out there that needs
-
some refactoring. And the other part is that
it's
-
also a very helpful technique when you're
in a
-
really, really difficult debugger situation.
If you need to
-
live update something it's very handy. Although,
that said,
-
I saw some things in Pry yesterday that make
-
this less and less of a necessity, so.
-
Use it only to refactor. It seems to be
-
the future direction.
-
I'd like to thank everyone I work with at
-
Shop it To Me. All of them have dealt
-
with my kooky ideas about metaprogramming
for a long
-
time, and some of them have let me know
-
quite noisily that they don't like it. I want
-
to thank the Addison Wesley authors who have
really
-
tren, a great transitional series for developers.
I thank
-
my lovely girlfriend Lauren who put up with
me
-
yelling about this sort of stuff at dinner.
And
-
I want to thank everyone here because you
are
-
all my favorite garbage collectors.
-
There is no shame in garbage collecting. It
is,
-
it is a great and noble profession. You have
-
to keep in mind that the scarab was holy
-
in Egypt so, and that's the lowliest of the
-
garbage collectors of all. So I hope that
you'll
-
take forward a lot of the object-oriented
techniques that
-
I've presented to you. I hope that you'll
use
-
them to attack code and furthermore, hope
that you'll
-
forgive me for spreading a bad meme that metaprogramming
-
was an awesome thing to do.
-
Thanks so much, and I'll say one last word
-
is that I hope all of you always have
-
the courage to face your problems, and when
they
-
feel a little bit too large, just remark to
-
your heart, all is well. And be ready to
-
give those talks. I'm ready to hear some new
-
garbage collectors next year. So thank you
again.