Return to Video

Ruby Conf 2013 - Preferring Object-Orientation to Metaprogramming

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

more » « less
Duration:
35:06

English subtitles

Revisions