< Return to Video

Ruby Conf 2013 - The Big Picture by Jim Weirich

  • 0:16 - 0:19
    JIM WEIRICH: I think that means it's about
    time to start.
  • 0:19 - 0:26
    Are you guys enjoying Miami? Awesome!
  • 0:26 - 0:29
    So why are you in here and not down at the
    beach?
  • 0:29 - 0:30
    AUDIENCE: Cause you're cool!
  • 0:30 - 0:33
    J.W.: Oh, yes, thank you. Yeah.
  • 0:33 - 0:36
    How many people recognize this picture, right
    here? Yeah.
  • 0:36 - 0:38
    Can you name it?
  • 0:38 - 0:43
    Nighthawks yeah by Edward Hopper. It was painted
    in
  • 0:43 - 0:46
    1942. If you recognize it, it might be because
  • 0:46 - 0:49
    it's one of the standard Mac backgrounds that
    you
  • 0:49 - 0:51
    can select on your desktop. And I had this
  • 0:51 - 0:54
    on my desktop for a long time. And I
  • 0:54 - 0:56
    really, really enjoy this picture. This is
    a really
  • 0:56 - 0:58
    cool picture.
  • 0:58 - 1:00
    Just a little bit of details about it. It
  • 1:00 - 1:04
    was painted in 1942, I believe. It was sold
  • 1:04 - 1:07
    to the Chicago Art Institute for about $3,000
    just
  • 1:07 - 1:10
    a few months after it was painted. It's hanging
  • 1:10 - 1:13
    up in the Institute since that time.
  • 1:13 - 1:17
    My daughter, who is a, goes to art school,
  • 1:17 - 1:20
    said she took a field trip to Chicago and
  • 1:20 - 1:22
    actually saw the actual painting up there.
    So while
  • 1:22 - 1:24
    I was describing it to her, she immediately
    recognized
  • 1:24 - 1:29
    it, said, oh yeah that's, that's the Hopper
    picture.
  • 1:29 - 1:31
    But this is, this is fascinating to look at.
  • 1:31 - 1:33
    And because it was on my background, I would,
  • 1:33 - 1:35
    I would open my laptop up and I would
  • 1:35 - 1:39
    see this and I would think about, maybe the
  • 1:39 - 1:41
    story behind it. I mean, look at this. It's
  • 1:41 - 1:45
    a diner. It's in New York somewhere. It's
    got
  • 1:45 - 1:46
    a cigar add at the top - it's hard
  • 1:46 - 1:48
    to see in the washed-out lighting here - for
  • 1:48 - 1:52
    five cent cigars. It's dark outside but the
    inside
  • 1:52 - 1:55
    of the diner is bright light and there's a
  • 1:55 - 1:57
    couple characters in there.
  • 1:57 - 2:00
    I mean look at this couple. Look at their
  • 2:00 - 2:04
    body language. What is their body language
    telling you
  • 2:04 - 2:07
    about them? They're sitting together. They're
    some kind of
  • 2:07 - 2:11
    couple. But notice how closed off they are.
    Their
  • 2:11 - 2:16
    hands are almost touching but not touching.
    Look at
  • 2:16 - 2:19
    her face - how serious she looks, the dark
  • 2:19 - 2:22
    eyes. Maybe she's been crying. Maybe she's
    sad.
  • 2:22 - 2:24
    I can't quite tell what she's holding in her
  • 2:24 - 2:26
    hand, but it looks like it might be a
  • 2:26 - 2:28
    wad of money of some type. Maybe a little
  • 2:28 - 2:31
    bit of money. Maybe this, these two people
    are
  • 2:31 - 2:34
    a couple that are having problems. Maybe it's
    money-related
  • 2:34 - 2:37
    problems. That's why she's looking at the
    money so
  • 2:37 - 2:37
    hard.
  • 2:37 - 2:40
    Look at the guy's face. He is not a
  • 2:40 - 2:47
    happy camper. Someone wrote a poem about this
    picture,
  • 2:47 - 2:50
    and she says, and the poem says, I bet
  • 2:50 - 2:52
    she wrote him a letter and he is no
  • 2:52 - 2:56
    longer the guy that reads her letters twice.
    Wow.
  • 2:56 - 2:57
    Wow.
  • 2:57 - 3:01
    Night Hawks, probably so named because the
    Hawk beak
  • 3:01 - 3:04
    of the nose for this guy actually. That's
    an
  • 3:04 - 3:07
    interesting little tidbit. So there's something
    wrong there. You
  • 3:07 - 3:10
    know, a couple problems. Money problems, maybe
    something about
  • 3:10 - 3:13
    other kinds of problems. But definitely tension
    in that
  • 3:13 - 3:14
    couple.
  • 3:14 - 3:16
    Now from a distance, I looked at this guy
  • 3:16 - 3:17
    and I thought, oh wow, he looks like he's
  • 3:17 - 3:20
    really happy to have these customers late
    at night
  • 3:20 - 3:22
    in his diner. But when I zoomed in and
  • 3:22 - 3:25
    looked closer, that's not a smile he has on
  • 3:25 - 3:28
    his face. That's a grimace.
  • 3:28 - 3:30
    And he's looking at that couple. So what is
  • 3:30 - 3:32
    going on with the couple that is making the
  • 3:32 - 3:37
    waiter unhappy? You know, is, did they just
    get
  • 3:37 - 3:38
    done with a fight and they're sitting there
    sullenly
  • 3:38 - 3:42
    and he's like, OK, what's gonna happen next?
    You
  • 3:42 - 3:45
    know, it's, it's, you know, there's some interaction
    going
  • 3:45 - 3:47
    on there as well.
  • 3:47 - 3:50
    And then this guy. What's he doing there?
    He's
  • 3:50 - 3:54
    sitting alone. He's all by himself. He's got
    a
  • 3:54 - 3:57
    newspaper under his left elbow there, I believe
    that's
  • 3:57 - 3:59
    a newspaper. You can see it just a little
  • 3:59 - 4:00
    bit in the photo. It looks like he's holding
  • 4:00 - 4:02
    a glass of water. He's got a cup of
  • 4:02 - 4:03
    coffee right by him.
  • 4:03 - 4:04
    I don't actually see any food in front of
  • 4:04 - 4:07
    him but it looks like he's drinking something.
    And
  • 4:07 - 4:09
    he's sitting there all alone kind of in the
  • 4:09 - 4:11
    shadows, his hat's kind of down over his eyes
  • 4:11 - 4:12
    so you can't see what's going on. Is he
  • 4:12 - 4:16
    watching the other couple? Is he tailing them?
    Is
  • 4:16 - 4:19
    this a gangster type thing, where maybe they're
    involved
  • 4:19 - 4:20
    in some kind of gangster thing and that's
    the
  • 4:20 - 4:23
    money problem and he's an enforcer and he's
    fo
  • 4:23 - 4:24
    - I don't know.
  • 4:24 - 4:26
    I mean the possibilities of this are, are
    wild.
  • 4:26 - 4:29
    And notice he's got- his pocket, his coat
    pocket
  • 4:29 - 4:33
    right down there, is, is open. He's got something
  • 4:33 - 4:35
    in it. Is that his, is that his gun
  • 4:35 - 4:37
    that he's got in his coat pocket? I don't
  • 4:37 - 4:39
    know. I don't - there's all kinds of possibilities
  • 4:39 - 4:40
    with this picture.
  • 4:40 - 4:42
    That's why I love this picture. I don't know
  • 4:42 - 4:45
    what it's about exactly, but the possibilities
    of the
  • 4:45 - 4:50
    stories behind this is really interesting.
    Now this painting
  • 4:50 - 4:55
    has been referenced in, in literature. There's
    been stories
  • 4:55 - 4:58
    about it. Speigal did a - published five short
  • 4:58 - 5:03
    stories based upon what author's thought might
    be going
  • 5:03 - 5:05
    on in this picture. So five different stories.
    At
  • 5:05 - 5:07
    least one of which ended in a massacre.
  • 5:07 - 5:13
    It's used in movies, I think, Pennies, Pennies
    from
  • 5:13 - 5:20
    Heaven reproduced this scene when, oh the
    guy's name
  • 5:20 - 5:22
    escapes me. Who did, who did Blade Runner?
  • 5:22 - 5:25
    AUDIENCE: (indecipherable guesses)
  • 5:25 - 5:27
    J.W.: No, the director.
  • 5:27 - 5:29
    AUDIENCE: Ridley Scott.
  • 5:29 - 5:30
    J.W.: Ridley Scott. Ridley Scott. Thank you.
  • 5:30 - 5:32
    When Ridley Scott did Blade Runner, he would
    take
  • 5:32 - 5:35
    a reproduction of this film and shove it under
  • 5:35 - 5:38
    the noses of his production team and saying,
    this
  • 5:38 - 5:40
    is the feel that I want for my movie.
  • 5:40 - 5:45
    This kind of dark noir feel. And that's kind
  • 5:45 - 5:48
    of what pushed Blade Runner, the feel of Blade
  • 5:48 - 5:50
    Runner was inspired, very much, by the feel
    of
  • 5:50 - 5:53
    this picture as well.
  • 5:53 - 5:56
    Art says a lot. Pictures speak a lot. Now
  • 5:56 - 5:58
    they don't say exactly what's going on but
    they
  • 5:58 - 6:01
    open up so many other questions. And I find
  • 6:01 - 6:04
    it fascinating to look at pictures.
  • 6:04 - 6:06
    So I'm Jim Weirich. I am Chief Scientist for
  • 6:06 - 6:09
    Neo and I'm here to talk to you about
  • 6:09 - 6:12
    the big picture. People have been asking me
    this
  • 6:12 - 6:13
    week, Jim, what are you gonna talk about at
  • 6:13 - 6:16
    RubyConf? What's your talk about? And I say,
    I'm
  • 6:16 - 6:20
    going to talk about UML at a Ruby conference.
  • 6:20 - 6:27
    Yeah. Yeah. I get two reactions from that.
    Oops.
  • 6:33 - 6:35
    Yeah, like, huh, what's UML? I do not know
  • 6:35 - 6:37
    of this UML of which you speak. The other
  • 6:37 - 6:44
    reaction is - this is probably the Java developer
  • 6:44 - 6:46
    who has been immersed in UML for so long,
  • 6:46 - 6:48
    he is sick and tired of it and never
  • 6:48 - 6:50
    wants to see it again.
  • 6:50 - 6:52
    Truthfully, as I work with other Rubyists,
    I discover
  • 6:52 - 6:57
    that they have not used diagramming to any
    great
  • 6:57 - 7:00
    degree, and they're not aware of what UML
    can
  • 7:00 - 7:02
    do for you. So I'm here to give you
  • 7:02 - 7:05
    some very basics in UML.
  • 7:05 - 7:06
    What I'm gonna do is I'm gonna give you
  • 7:06 - 7:10
    a vocabulary. A vocabulary in pictures that
    you can
  • 7:10 - 7:12
    use to build diagrams. And then I'm going
    to
  • 7:12 - 7:15
    talk about three or maybe four of my own
  • 7:15 - 7:19
    libraries and the diagrams that I drew of
    those
  • 7:19 - 7:23
    libraries, and then what I learned from those
    diagrams
  • 7:23 - 7:25
    that I did not see by just looking at
  • 7:25 - 7:26
    the code.
  • 7:26 - 7:28
    So it's kind of my plan for this talk.
  • 7:28 - 7:31
    That's a road map. That's where we're gonna
    go.
  • 7:31 - 7:33
    So let's start talk, and just mention UML
    just
  • 7:33 - 7:36
    a little bit. There are basically three ways
    people
  • 7:36 - 7:37
    use UML.
  • 7:37 - 7:42
    One is the sketch language, to capture quick
    ideas
  • 7:42 - 7:43
    and to get them down on paper so they
  • 7:43 - 7:47
    can communicate with each other. UML as sketch
    omits
  • 7:47 - 7:52
    details. UML as a sketch will lie about the
  • 7:52 - 7:54
    software, because the lie is better than what
    the
  • 7:54 - 7:58
    reality is there. You want to convey an idea,
  • 7:58 - 8:01
    you know, the idea's what's important, not
    necessarily the
  • 8:01 - 8:04
    details. So UML as sketch.
  • 8:04 - 8:05
    You can use it in both ways. You can
  • 8:05 - 8:08
    sketch up an idea before you implement it,
    just
  • 8:08 - 8:10
    to kind of get an idea of the roadmap
  • 8:10 - 8:12
    you want to go to. You can take an
  • 8:12 - 8:15
    existing piece of code and draw the diagrams
    afterwards
  • 8:15 - 8:18
    to kind of get a better understanding of what
  • 8:18 - 8:20
    the software's doing. That's what I've done
    on the
  • 8:20 - 8:22
    examples that follow.
  • 8:22 - 8:25
    UML as a blueprint is probably what most,
    gives
  • 8:25 - 8:29
    most Java developers the eh feeling. It's
    when you
  • 8:29 - 8:32
    use UML down to such a detailed degree that
  • 8:32 - 8:37
    a designer- architect can take the UML diagram
    and
  • 8:37 - 8:39
    hand it off to a coder and the coder
  • 8:39 - 8:41
    just implements it.
  • 8:41 - 8:43
    I don't believe that works very well at all,
  • 8:43 - 8:45
    and I'm not a fan of UML as a
  • 8:45 - 8:49
    blueprint. Even worse than UML as a blueprint
    is
  • 8:49 - 8:52
    UML as a programming language. I used to work
  • 8:52 - 8:55
    for a company called CompuWare. We had a product
  • 8:55 - 8:59
    called OptimalJ, and the salesman for CompuWare,
    they said,
  • 8:59 - 9:01
    Jim, you gotta push OptimalJ for us, you know.
  • 9:01 - 9:05
    It's so great. You just draw the pictures,
    and
  • 9:05 - 9:07
    then you push a button and you get an
  • 9:07 - 9:10
    application out of it.
  • 9:10 - 9:12
    Yeah. That's exactly what I did. I said, uh-huh,
  • 9:12 - 9:14
    yeah. I laughed. But Jim it really works.
    It's
  • 9:14 - 9:18
    got to work. We use it. Patterns. And I
  • 9:18 - 9:20
    said, you don't, guys, really don't know what
    patterns
  • 9:20 - 9:21
    are, do you?
  • 9:21 - 9:25
    No, but we know they're good.
  • 9:25 - 9:28
    So I was never a big believer in OptimalJ.
  • 9:28 - 9:31
    It turns out that when you dig deeper, for
  • 9:31 - 9:34
    every diagram you draw, you have to accompany
    it
  • 9:34 - 9:38
    with something called the expression language,
    to kind of
  • 9:38 - 9:39
    tie it down and kind of map it into
  • 9:39 - 9:41
    a programming language. I, and I told my sales'
  • 9:41 - 9:44
    guys, this kind of looks like programming
    right here.
  • 9:44 - 9:46
    He says, oh no, no, it's not. It's not.
  • 9:46 - 9:49
    Don't worry. It's nothing like programming.
    OK.
  • 9:49 - 9:52
    So UML as a programming language, no. I'm
    not
  • 9:52 - 9:54
    a big believer in that. But UML as sketch,
  • 9:54 - 9:56
    I am still a big fan of.
  • 9:56 - 9:58
    So let's go ahead and start. Let's start with
  • 9:58 - 10:01
    the first example. And this is talking about
    dependencies
  • 10:01 - 10:02
    in my software. I think this is one of
  • 10:02 - 10:04
    the strongest features of UML is to get a
  • 10:04 - 10:10
    broad overview of what your code depends on.
  • 10:10 - 10:11
    Before we do that, I got to build up
  • 10:11 - 10:14
    the vocabulary of the diagram so you know
    what
  • 10:14 - 10:15
    I'm talk about.
  • 10:15 - 10:20
    First of call, if you have a class in
  • 10:20 - 10:22
    Ruby, such as a Car class, you can represent
  • 10:22 - 10:24
    it as a diagram. It's just a simple box
  • 10:24 - 10:26
    with the name of the class right in here.
  • 10:26 - 10:29
    This represents this bit of code right here.
  • 10:29 - 10:31
    If you wish to get more detailed and you
  • 10:31 - 10:33
    wish to include the methods in it, you can
  • 10:33 - 10:36
    add a second box. Divide your box in too.
  • 10:36 - 10:38
    The name goes on the top and the methods
  • 10:38 - 10:41
    go down here into this second box. So you
  • 10:41 - 10:45
    talk about particular methods on that particular
    class.
  • 10:45 - 10:47
    And like I said, UML, a sketch means that
  • 10:47 - 10:49
    you include the methods that you wish to talk
  • 10:49 - 10:53
    about right now. You don't include every single
    method.
  • 10:53 - 10:55
    You just include what's important to the idea
    that
  • 10:55 - 10:58
    you wish to convey in that particular diagram.
  • 10:58 - 11:01
    If you want to get even more detailed, and
  • 11:01 - 11:04
    I rarely do this, is that if there are
  • 11:04 - 11:06
    internal attributes, you can list them in
    a third
  • 11:06 - 11:09
    box that goes between the name and above,
    below
  • 11:09 - 11:12
    the name and above the actual methods.
  • 11:12 - 11:16
    I, like I said, I rarely go to the
  • 11:16 - 11:18
    attribute level.
  • 11:18 - 11:20
    If one class uses another class, and you can
  • 11:20 - 11:22
    always tell it uses it because it will reference
  • 11:22 - 11:26
    the class by name, here, if so, then you
  • 11:26 - 11:30
    could create a dependency between this class
    and that
  • 11:30 - 11:32
    class. The direction of the array goes in
    the
  • 11:32 - 11:35
    direction of the dependency, and this is always,
    always,
  • 11:35 - 11:39
    always true in UML. Whenever you draw an arrow,
  • 11:39 - 11:40
    it means it's a dependency, and it goes in
  • 11:40 - 11:43
    the direction of the thing that's doing the
    depending
  • 11:43 - 11:47
    towards the thing that it is being depended
    on.
  • 11:47 - 11:49
    This means that if I use an Engine object,
  • 11:49 - 11:52
    I can use it independently. But if ever I
  • 11:52 - 11:54
    used a car object, I also need to drag
  • 11:54 - 11:57
    in an engine object along with it. And we
  • 11:57 - 12:00
    can see that because, man, we're referencing
    Engine right
  • 12:00 - 12:03
    here in the code base. That's a dependency,
    and
  • 12:03 - 12:06
    UML is great for capturing these dependencies.
  • 12:06 - 12:10
    Here's a dependency for cars also using wheel,
    and
  • 12:10 - 12:12
    you can say on your dependency line, you can
  • 12:12 - 12:16
    say one car has many wheels. In this case,
  • 12:16 - 12:19
    four wheels. You could put a four here for
  • 12:19 - 12:21
    the star, or you could just say star, it
  • 12:21 - 12:22
    says x, one to many. So it's kind of
  • 12:22 - 12:25
    a one to many relationship right there. Again.
    Dependency
  • 12:25 - 12:29
    goes from Car to Wheel.
  • 12:29 - 12:33
    If you inherit, the inheritance relationship
    is also an
  • 12:33 - 12:36
    arrow. This arrow is an open triangle pointing
    from
  • 12:36 - 12:39
    the subclass to the superclass. So, again,
    I can
  • 12:39 - 12:41
    use car by itself, but if I want to
  • 12:41 - 12:44
    use a SportsCar class, I get Car automatically
    because
  • 12:44 - 12:49
    it's dragged in by that dependency.
  • 12:49 - 12:53
    Ruby has modules. And this is how I designate
  • 12:53 - 12:57
    modules in a UML diagram when I'm using, talking
  • 12:57 - 13:00
    about Ruby, is essentially the same as a class,
  • 13:00 - 13:05
    but I put this, it's called a stereotype.
    I
  • 13:05 - 13:08
    say it's a module in this, I use angle
  • 13:08 - 13:11
    brackets, but what they really should be are
    French
  • 13:11 - 13:16
    quotes, which I cannot pronounce the real
    name for.
  • 13:16 - 13:18
    But that's a stereotype right there, and that
    says
  • 13:18 - 13:20
    it's, it's kind of like a class but it
  • 13:20 - 13:22
    has these special properties and it's a module.
    And
  • 13:22 - 13:24
    if you're doing Ruby programming, you know
    what a
  • 13:24 - 13:26
    module is. And that's all it's telling you,
    that
  • 13:26 - 13:27
    Driveable is a module.
  • 13:27 - 13:32
    I use the same arrow to indicate include as
  • 13:32 - 13:36
    inheritance here, because essentially it's
    the same relationship. The
  • 13:36 - 13:39
    difference between inheritance and including
    a module in Ruby
  • 13:39 - 13:43
    is very subtle and I don't really call out
  • 13:43 - 13:47
    the difference in a UML diagram because of
    that.
  • 13:47 - 13:51
    OK. So there's one more thing I want to
  • 13:51 - 13:57
    show you and this is really important. Here,
    Car
  • 13:57 - 14:02
    is being passed an Engine object. And so there
  • 14:02 - 14:05
    is no longer a direct reference to the Engine
  • 14:05 - 14:09
    class inside my Car class anymore. So Car
    no
  • 14:09 - 14:13
    longer depends upon the Engine class, but
    it does
  • 14:13 - 14:17
    depend upon some kind of object that behaves
    like
  • 14:17 - 14:18
    an Engine does.
  • 14:18 - 14:22
    In other words it does, it's duck-typed to
    an
  • 14:22 - 14:26
    Engine. I capture this in U- in Java. If
  • 14:26 - 14:27
    you're doing this in Java, this would be an
  • 14:27 - 14:30
    interface. And you have to actually write
    code that
  • 14:30 - 14:32
    had the start and stop method on it and
  • 14:32 - 14:35
    say this is an interface and that the Engine
  • 14:35 - 14:39
    implements the interface. In Ruby, the stuff
    for this
  • 14:39 - 14:41
    thing right here doesn't exist. There is no
    source
  • 14:41 - 14:44
    code for this box right here. But it's an
  • 14:44 - 14:47
    important concept, which you need to capture
    and be
  • 14:47 - 14:49
    able to talk about.
  • 14:49 - 14:51
    Car does not depend upon Engine, but it does
  • 14:51 - 14:55
    depend upon an object that obeys this protocol,
    this
  • 14:55 - 15:00
    start and stop method on it.
  • 15:00 - 15:03
    Engine implements that protocol. So it gets,
    it's kind
  • 15:03 - 15:05
    of like the inheritance line, but dotted instead
    of
  • 15:05 - 15:08
    solid. And so I'm saying Engine implements
    this car
  • 15:08 - 15:12
    independence- uses it, Car does not depend
    upon Engine.
  • 15:12 - 15:14
    That means if I want to test a Car,
  • 15:14 - 15:16
    I can just drop anything in that acts sufficiently
  • 15:16 - 15:20
    like a Car- or, sufficiently like an Engine
    for
  • 15:20 - 15:22
    my testing, and I can test Car without having
  • 15:22 - 15:24
    an Engine available at all.
  • 15:24 - 15:27
    And this is an important concept in drawing
    these
  • 15:27 - 15:30
    dependency diagrams is to recognize that,
    hey, that dependency
  • 15:30 - 15:32
    no longer goes all the way to Engine, but
  • 15:32 - 15:34
    is just using a protocol at that point.
  • 15:34 - 15:38
    All right. So now we got some basic vocabulary
  • 15:38 - 15:43
    to talk about dependencies in our programs.
  • 15:43 - 15:46
    So this is a pretty standard Rails application
    right
  • 15:46 - 15:50
    here. This is actually an implementation of
    the pay
  • 15:50 - 15:56
    employee problem that is common in literature.
    You probably
  • 15:56 - 15:58
    run into it. You have three kinds of employees.
  • 15:58 - 16:00
    Hourly, salaried, and commissioned.
  • 16:00 - 16:03
    Hourly employees are paid according to the
    time cards
  • 16:03 - 16:06
    they turn in. Salaried employees are paid
    a yearly
  • 16:06 - 16:09
    salary, paid once a month. So they get one
  • 16:09 - 16:11
    twelfth of their annual salary once a month.
    Commissioned
  • 16:11 - 16:14
    employees get a salary plus a commission based
    upon
  • 16:14 - 16:16
    the sales receipts that they turn in. So there's
  • 16:16 - 16:21
    three different ways of calculating their
    pay check.
  • 16:21 - 16:23
    Here, what's important to notice, is that
    in this
  • 16:23 - 16:28
    Rails version of this solution, we have an
    employee
  • 16:28 - 16:31
    controller. It inherits from application controller,
    which inherits from
  • 16:31 - 16:35
    action, action controller base.
  • 16:35 - 16:39
    The red classes are Rails classes. They are
    part
  • 16:39 - 16:43
    of Rails. The pink classes are our application
    classes
  • 16:43 - 16:46
    that depend upon Rails. So, if I want to
  • 16:46 - 16:49
    test my employee controller, I've gotta bring
    in Rails
  • 16:49 - 16:50
    to do it. If I want to test my
  • 16:50 - 16:53
    employee object, I gotta bring in ActiveRecord
    to do
  • 16:53 - 16:54
    that testing.
  • 16:54 - 16:58
    So they are dependent upon the framework.
    However, the
  • 16:58 - 17:01
    way I chose to implement the salary calculation
    was
  • 17:01 - 17:05
    as a set of strategies that the employee picks
  • 17:05 - 17:08
    a strategy based upon what type of employee
    he
  • 17:08 - 17:12
    is and then just calls the strategy. Hourly
    paycheck,
  • 17:12 - 17:15
    salaried paycheck, commissioned paycheck,
    with all implement the protocol
  • 17:15 - 17:19
    that includes calculating pay amount and gets
    passed in
  • 17:19 - 17:20
    an employee object.
  • 17:20 - 17:23
    There is nothing in these guys that directly
    reference
  • 17:23 - 17:27
    the employee class. They just depend upon
    something that
  • 17:27 - 17:30
    acts like an employee. That means these guys
    can
  • 17:30 - 17:33
    be tested very simply by - like, if I
  • 17:33 - 17:35
    want to test Salaried Paycheck, I just need
    to
  • 17:35 - 17:38
    pass in an object that has an annual salary
  • 17:38 - 17:41
    field on it and I can test that without
  • 17:41 - 17:43
    loading Rails at all. That's why they are
    green.
  • 17:43 - 17:46
    These can be tested, the green things can
    be
  • 17:46 - 17:47
    run very quickly and very safely.
  • 17:47 - 17:50
    And we can tell that by examining the arrows.
  • 17:50 - 17:54
    Notice that in this dotted box here, all of
  • 17:54 - 17:58
    the arrows are pointing inwards. There is
    nothing pointing
  • 17:58 - 18:01
    outwards from this box. That means I do not
  • 18:01 - 18:03
    depend upon the framework and that tells me
    I
  • 18:03 - 18:07
    can test those very efficiently and very quickly.
  • 18:07 - 18:09
    However, if I want to test the employee object
  • 18:09 - 18:11
    directly, I've got to load Rails. If I want
  • 18:11 - 18:14
    to test controller directly, I've gotta load
    Rails again.
  • 18:14 - 18:18
    I'm teaching a class with Bob Kauss right
    now,
  • 18:18 - 18:21
    on testing in Rails and refactoring in patterns
    and
  • 18:21 - 18:23
    things like this, and we use this example
    in
  • 18:23 - 18:27
    our class.
  • 18:27 - 18:29
    One of the things we do is to push
  • 18:29 - 18:32
    this system. You see how much we can get
  • 18:32 - 18:36
    decoupled from the Rails framework. So we
    can test
  • 18:36 - 18:40
    as much logic as we possibly can without invoking
  • 18:40 - 18:41
    Rails.
  • 18:41 - 18:43
    One of the techniques we use is, some of
  • 18:43 - 18:46
    the techniques from the hexagonal architecture
    concept Matt Winn
  • 18:46 - 18:49
    does, and Kevin Rutheford has done.
  • 18:49 - 18:51
    And if you look at that, they have basically
  • 18:51 - 18:59
    take this approach. And this concentrates
    on the controller
  • 18:59 - 19:02
    now. They take the employee controller, and
    they say
  • 19:02 - 19:05
    some of the logic in the controller is Rails
  • 19:05 - 19:09
    dependent. Things that say redirect to this
    URL. Render
  • 19:09 - 19:14
    this template. Here is the params hash. Those
    are
  • 19:14 - 19:15
    our Rails things.
  • 19:15 - 19:19
    However, some of the logic is really business
    logic.
  • 19:19 - 19:22
    Even in the standard dumb Rails controller,
    there's still
  • 19:22 - 19:25
    business logic in there. How do I create an
  • 19:25 - 19:28
    employee object? How do I save an employee
    object?
  • 19:28 - 19:31
    What ha- how do I validate and how do
  • 19:31 - 19:33
    I, what, you know, how do I detect whether
  • 19:33 - 19:37
    it's saved or not? Validated or not? It's
    all
  • 19:37 - 19:39
    really kind of business logic.
  • 19:39 - 19:43
    So they very carefully picked that controller
    apart into
  • 19:43 - 19:46
    two pieces. One piece remains here in the
    controller.
  • 19:46 - 19:48
    The other piece, they pull out and, I'm calling
  • 19:48 - 19:50
    it a runner, cause they, they tend to give
  • 19:50 - 19:54
    it the method called run. And the run, into
  • 19:54 - 19:56
    the run they pass in a couple things.
  • 19:56 - 19:59
    They pass in a protocol that is essentially
    the
  • 19:59 - 20:03
    context object, which is the controller. They
    pan, and
  • 20:03 - 20:07
    I have also pulled out a repository object
    here,
  • 20:07 - 20:09
    so all the database related stuff is done
    through
  • 20:09 - 20:12
    a repository. And it's, it's a little tedious
    but
  • 20:12 - 20:15
    it's really not hard, at all. You can almost
  • 20:15 - 20:18
    automate that piece very easily.
  • 20:18 - 20:21
    So the runner now depends upon something that
    has
  • 20:21 - 20:25
    save and find_employee type methods on it.
    It depends
  • 20:25 - 20:29
    upon some call backs the context provides.
    But there
  • 20:29 - 20:32
    is no direct reference to Rails anywhere in
    the
  • 20:32 - 20:33
    runner anymore.
  • 20:33 - 20:35
    That means I can test the business logic in
  • 20:35 - 20:38
    here very carefully. Now I've got a whole
    bunch
  • 20:38 - 20:42
    more logic that is totally free from Rails,
    and
  • 20:42 - 20:44
    then I can easily test.
  • 20:44 - 20:47
    There's one more stage I like to do, and
  • 20:47 - 20:49
    this - I'd like to get most of the
  • 20:49 - 20:52
    business logic in here free from Rails as
    well.
  • 20:52 - 20:57
    There's many ways to do this. Here's one.
  • 20:57 - 21:01
    Let's treat employee, the ActiveRecord employee
    object, as a
  • 21:01 - 21:05
    dumb data holder. I'd, I'm gonna let three
    things
  • 21:05 - 21:09
    go in there. Number one, I let database fields
  • 21:09 - 21:12
    be in that object. I let relationships be
    in
  • 21:12 - 21:15
    that object, cause Rails is really good at
    defining
  • 21:15 - 21:17
    relationships. Doesn't make sense to pull
    those out.
  • 21:17 - 21:20
    Likewise, validations are in that object.
    You can make
  • 21:20 - 21:22
    an argument, you could pull validations out
    - yeah,
  • 21:22 - 21:25
    OK, you can do that too. I tend to
  • 21:25 - 21:26
    leave them in.
  • 21:26 - 21:28
    So it tends to be dumb, without any business
  • 21:28 - 21:33
    logic in it. Then I create a business employee
  • 21:33 - 21:36
    object. I usually just namespace that, put
    it in
  • 21:36 - 21:40
    a module called biz or whatever. And then
    key
  • 21:40 - 21:44
    proxies to the employee object and all he
    needs
  • 21:44 - 21:47
    to do is assume that he has an object
  • 21:47 - 21:51
    that supports the dumb data portions of employee.
  • 21:51 - 21:54
    That means he knows about the employee name.
    He
  • 21:54 - 21:57
    knows about the annual salary. But that's
    all. There's
  • 21:57 - 22:00
    no business logic in here, or represented
    by this
  • 22:00 - 22:04
    protocol at all. Now my whole application
    can use
  • 22:04 - 22:08
    this business employee as if it were the ActiveRecord
  • 22:08 - 22:11
    object. But he himself doesn't actually depend
    upon ActiveRecord,
  • 22:11 - 22:15
    he just depends upon the protocol for dumb
    data.
  • 22:15 - 22:18
    This is pretty easy actually.
  • 22:18 - 22:23
    And now, with that, the whole thing here actually
  • 22:23 - 22:27
    my entire application is now inside the red
    box.
  • 22:27 - 22:30
    I can test stories here at this level, cause
  • 22:30 - 22:35
    the, you know the, create a employee stories
    is
  • 22:35 - 22:39
    actually implemented by this code here. The
    employee specific
  • 22:39 - 22:42
    business is in here, and all I have to
  • 22:42 - 22:43
    do, you know, so I can test all of
  • 22:43 - 22:46
    this very easily. I can actually run unit
    tests
  • 22:46 - 22:48
    at this level.
  • 22:48 - 22:49
    If I want to, I can go ahead include
  • 22:49 - 22:52
    the ActiveRecord part of this, and do story-level
    testing
  • 22:52 - 22:55
    all the way to the database without going
    through
  • 22:55 - 22:58
    the web interface, cause I'm hitting this
    guy right
  • 22:58 - 23:01
    here. And then I can do just a little-
  • 23:01 - 23:03
    the only thing outside the box is now is
  • 23:03 - 23:04
    just a little bit of wiring that happens in
  • 23:04 - 23:07
    the controller. I can easily test that at
    a
  • 23:07 - 23:10
    integration level test by hitting the web
    UI.
  • 23:10 - 23:13
    So my web UI testing is light-weight and small
  • 23:13 - 23:15
    and just enough to make sure the connections
    are
  • 23:15 - 23:18
    made. My story-level testing gets here and
    can go
  • 23:18 - 23:20
    all the way to the database. And then my
  • 23:20 - 23:22
    unit tests - excuse me, my unit tests are
  • 23:22 - 23:25
    this level here, and they can be fast and
  • 23:25 - 23:27
    very fine-grained and have a lot of them to
  • 23:27 - 23:29
    really exercise the logic.
  • 23:29 - 23:32
    I think that's a good division of labor between
  • 23:32 - 23:34
    your tests. And I really like the architecture
    that
  • 23:34 - 23:37
    I've been experimenting here with this idea.
    But notice
  • 23:37 - 23:40
    how the diagram tells you all that information.
    I
  • 23:40 - 23:41
    can look at this diagram. I can tell, here
  • 23:41 - 23:43
    are the arrows, and this is the direction
    they
  • 23:43 - 23:45
    poi- are pointing and this green stuff has
    no
  • 23:46 - 23:49
    arrows leaving it, going after any of my ActiveRecord
  • 23:49 - 23:49
    stuff.
  • 23:49 - 23:54
    So the diagram really helps convey that information
    without
  • 23:54 - 23:55
    me going through and showing you a lot of
  • 23:55 - 23:58
    code, code, code.
  • 23:58 - 24:03
    OK. Next example, let's talk about structure.
  • 24:03 - 24:05
    Excuse me.
  • 24:05 - 24:12
    This is a diagram I drew based on Rake.
  • 24:12 - 24:14
    I was actually rather surprised when I got
    done
  • 24:14 - 24:17
    with this thing, diagram. This had, has very
    little
  • 24:17 - 24:21
    mapping in, in how my mind thinks about Rake.
  • 24:21 - 24:24
    So the diagram, to me, was very interesting.
  • 24:24 - 24:26
    First of all, the first thing that kind came
  • 24:26 - 24:27
    out to me is that Rake has a lot
  • 24:27 - 24:32
    of large classes with lots of methods on it.
  • 24:32 - 24:34
    So few classes, but the classes have lots
    of
  • 24:34 - 24:36
    meth- and you don't see all the methods here
  • 24:36 - 24:39
    because this is sketch. And I omitted the
    methods
  • 24:39 - 24:41
    I wasn't interested in showing.
  • 24:41 - 24:44
    But as I was going through the diagram, I
  • 24:44 - 24:47
    saw, oh, this task manager's got a bazillion
    methods
  • 24:47 - 24:52
    on it. Application has a lot of methods on
  • 24:52 - 24:54
    it. Task has a bazillion and a half methods
  • 24:54 - 24:59
    on it. They're just not being shown here.
  • 24:59 - 25:00
    So that was kind of odd. I was kind
  • 25:00 - 25:03
    of surprised by that. The other thing I miss-
  • 25:03 - 25:06
    noticed, is there's lots of things in here,
    domain
  • 25:06 - 25:09
    knowledge about Rake that is not represented
    anywhere by
  • 25:09 - 25:12
    a class. This bothers me just a little bit.
  • 25:12 - 25:14
    Rake has a concept of rules. There is no
  • 25:14 - 25:17
    rules class in Rake at all.
  • 25:17 - 25:20
    That's kind of odd.
  • 25:20 - 25:24
    Rake also attacks locations where a task is
    defined
  • 25:24 - 25:25
    so you can find it easily in your source
  • 25:25 - 25:29
    code. There's no domain object representing
    locations in Rake.
  • 25:29 - 25:31
    And this is kind of bothersome to me as
  • 25:31 - 25:34
    well.
  • 25:34 - 25:36
    And this one's really odd. So what is happening?
  • 25:36 - 25:39
    Your task manager is the guy who contains
    the
  • 25:39 - 25:41
    tasks. And the way Rake is designed, task
    manager
  • 25:41 - 25:44
    is a module that is included into your application
  • 25:44 - 25:47
    so your application is the thing that holds
    the
  • 25:47 - 25:51
    tasks. It attracts the current scope. There
    are name
  • 25:51 - 25:54
    spaces in Rake. And that's represented by
    the scope.
  • 25:54 - 25:55
    But I really like this part about, this has
  • 25:55 - 25:58
    worked really well here, but it's a little
    bit
  • 25:58 - 26:01
    odd in that, as you read a Rake file,
  • 26:01 - 26:03
    the scope is constantly changing, and I'm
    defining a
  • 26:03 - 26:05
    task in this name space, I pop out of
  • 26:05 - 26:07
    the name space, and as you're doing it, the
  • 26:07 - 26:08
    current scope keeps changing.
  • 26:08 - 26:11
    And as you define a task, he gets, he
  • 26:11 - 26:14
    grabs whatever current scope the task manager
    has at
  • 26:14 - 26:16
    that point. And that works fairly well, but
    what
  • 26:16 - 26:19
    I end up with is a flat list of
  • 26:19 - 26:21
    all the tasks in the system, and there's nothing
  • 26:21 - 26:24
    that captures the structure of the name spaces
    at
  • 26:24 - 26:26
    all. And I was kind of surprised by that,
  • 26:26 - 26:28
    when I went back and actually looked at how
  • 26:28 - 26:32
    I implemented it, it seemed a little bit weird.
  • 26:32 - 26:35
    The other weird thing is that file_task essentially
    ignores
  • 26:35 - 26:39
    scope, because they're defining files and
    files have no
  • 26:39 - 26:41
    idea of what the name space are, so they,
  • 26:41 - 26:44
    they kind of ignore scope when they're do-
    being
  • 26:44 - 26:46
    defined. So why does file_task inherit from
    a task
  • 26:46 - 26:49
    which has a scope?
  • 26:49 - 26:52
    That struck me in, in reading this diagram
    as
  • 26:52 - 26:55
    something a little bit odd. So maybe I should
  • 26:55 - 27:02
    rewrite Rake. Version 20, yeah.
  • 27:04 - 27:06
    And here's an idea, here's one way I might
  • 27:06 - 27:08
    approach it. So this is now UML as a
  • 27:08 - 27:13
    sketch, kind of exploring an idea that we
    could
  • 27:13 - 27:16
    go in. So here's your application, but rather
    than
  • 27:16 - 27:20
    inheriting from task manager, make task manager
    a object
  • 27:20 - 27:23
    in and of itself. And task manager is now
  • 27:23 - 27:28
    responsible for managing all the tasks in
    that scope,
  • 27:28 - 27:30
    but no other scope.
  • 27:30 - 27:33
    The scope object kind of goes away, and rather
  • 27:33 - 27:35
    than a linked list, the task manager now becomes
  • 27:35 - 27:38
    a tree of name spaces. Now I can represent
  • 27:38 - 27:40
    the name space structure of your Rake file
    explicitly
  • 27:40 - 27:42
    in my code base. Seems to me that would
  • 27:42 - 27:46
    be a good thing.
  • 27:46 - 27:48
    Tasks still have - and this is mis-labeled,
    this
  • 27:48 - 27:51
    should say scope right here. That's another
    problem with
  • 27:51 - 27:57
    UML. It doesn't always accurately reflect
    your code base.
  • 27:57 - 27:59
    I would, this would actually be scope not
    task.
  • 27:59 - 28:02
    But there would have one task would point
    to
  • 28:02 - 28:06
    a particular scope. Task manager would have
    many tasks.
  • 28:06 - 28:09
    And then task and rule and file_task would
    all
  • 28:09 - 28:13
    implement some kind of task protocol that's
    there.
  • 28:13 - 28:15
    And I think that might be an interesting way
  • 28:15 - 28:17
    to go. It might be worth exploring through.
    The
  • 28:17 - 28:19
    problem, of course, is Rake is a well-defined
    application
  • 28:19 - 28:22
    and if I change the internal structure too
    much
  • 28:22 - 28:25
    I might break somebody's code, so. Gotta treat
    this
  • 28:25 - 28:26
    with care.
  • 28:26 - 28:29
    But here's an idea of a direction to go.
  • 28:29 - 28:34
    So, so how am I representing scopes now in
  • 28:34 - 28:36
    here? So I gotta give you some new vocabulary.
  • 28:36 - 28:40
    So now, let's talk about objects rather than
    classes,
  • 28:40 - 28:42
    we'll talk about objects. So here is a Car
  • 28:42 - 28:45
    object, my car, and we can represent that
    in
  • 28:45 - 28:48
    UML as my_car colon Car, and we underline
    the
  • 28:48 - 28:50
    whole thing. And it looks a lot like a
  • 28:50 - 28:52
    class box except it's got an underline thing
    in
  • 28:52 - 28:57
    it that means it's an object, not a class.
  • 28:57 - 28:58
    If we don't care what the thing is called,
  • 28:58 - 29:00
    we can leave off the name. If we don't
  • 29:00 - 29:01
    care what class it is and we just want
  • 29:01 - 29:03
    to talk about this object with this name,
    we
  • 29:03 - 29:06
    can leave off the colon and the class name.
  • 29:06 - 29:08
    So either way works. Any three of these are
  • 29:08 - 29:09
    valid.
  • 29:09 - 29:12
    So here is a car with an engine and
  • 29:12 - 29:19
    four wheels. So this object diagram, so, so
    a
  • 29:19 - 29:23
    class captures kind of a static nature of
    the
  • 29:23 - 29:27
    class relationship. An object diagram captures
    a snapshot in
  • 29:27 - 29:30
    time of an object and what it has. At
  • 29:30 - 29:33
    this point in time, this car has an engine
  • 29:33 - 29:35
    and a wheel.
  • 29:35 - 29:37
    If I leave it out on the street and
  • 29:37 - 29:41
    somewhere steels the hu- the wheels off of
    it
  • 29:41 - 29:43
    and all of the sudden it's got less wheels.
  • 29:43 - 29:45
    So that would be a different snapshot in time.
  • 29:45 - 29:47
    Or someone takes out the engine and replaces
    the
  • 29:47 - 29:49
    engine. Well that would be a different snapshot.
  • 29:49 - 29:52
    So an object diagram captures, this is how
    your
  • 29:52 - 29:56
    objects look right now at this point in time.
  • 29:56 - 29:58
    So this is how Rake might look at a
  • 29:58 - 30:02
    point in time. Here we have a top-level task
  • 30:02 - 30:06
    manager name space and we have a test name
  • 30:06 - 30:08
    space here and he has a task called units,
  • 30:08 - 30:12
    so test colon units would be the name of
  • 30:12 - 30:16
    this task. DB test prepare would be the name
  • 30:16 - 30:19
    of this task. DB migrate would be the name
  • 30:19 - 30:20
    of this task.
  • 30:20 - 30:22
    So I'm representing the scopes and the name
    spaces
  • 30:22 - 30:25
    of Rake in a data structure inside of Rake
  • 30:25 - 30:29
    as well. So object diagram can capture that
    kind
  • 30:29 - 30:32
    of snapshot idea of your program. And I really
  • 30:32 - 30:34
    like that. OK.
  • 30:34 - 30:40
    Let's talk about creation of objects.
  • 30:42 - 30:45
    I have a goal this year to talk about
  • 30:45 - 30:51
    flying robots in every single talk I give.
    I-
  • 30:51 - 30:56
    Thank you. Thank you. I think I've only missed
  • 30:56 - 30:57
    on talk so far, and I slipped it kind
  • 30:57 - 30:59
    of in in the comments so then at the
  • 30:59 - 30:59
    end.
  • 30:59 - 31:01
    So here. So let's talk about the flying robot
  • 31:02 - 31:03
    that we're playing with back in the office.
    This
  • 31:03 - 31:06
    is a parrot AR drone. It's a quadacopter.
    It
  • 31:06 - 31:09
    has two cameras on it. It runs Linux on
  • 31:09 - 31:12
    the copter itself. And it talks to your laptop
  • 31:12 - 31:15
    via wifi.
  • 31:15 - 31:19
    I have written a library called Argus that
    you
  • 31:19 - 31:21
    can use to control an AR drone. And here's
  • 31:21 - 31:23
    a simple program where we create a drone,
    we
  • 31:23 - 31:27
    tell it to start, all its subprocesses up.
    We
  • 31:27 - 31:29
    tell the drone to take off, tell it to
  • 31:29 - 31:32
    turn right, turn left, hover, and then land,
    and
  • 31:32 - 31:34
    then shut down.
  • 31:34 - 31:39
    So let's see if that program works. K. Take
  • 31:39 - 31:44
    off. Turn right. I think I actually turn right
  • 31:44 - 31:51
    for five seconds instead of two. Turn left.
    Hover
  • 31:51 - 31:52
    and then land.
  • 31:52 - 31:55
    OK. So cool. So that's, that's, that's all
    controlled
  • 31:55 - 31:58
    by Ruby.
  • 31:58 - 32:03
    A good way to talk about the Argus library
  • 32:03 - 32:06
    is to use an Argus diagram. I can show
  • 32:06 - 32:07
    you this diagram and I can talk about the
  • 32:07 - 32:12
    pieces of this architecture and how, what
    the responsibilities
  • 32:12 - 32:14
    for each piece is. The drone object is the
  • 32:14 - 32:17
    drone that the application plays with. It
    is the
  • 32:17 - 32:20
    front facing object that you send all your
    commands
  • 32:20 - 32:22
    to. You don't have to worry about anything
    behind
  • 32:22 - 32:24
    the drone.
  • 32:24 - 32:29
    The controller is responsible for, for translating
    these high-level
  • 32:29 - 32:31
    commands like go up, go down, turn left, turn
  • 32:31 - 32:35
    right, into lower-level drone commands. And
    then taking those
  • 32:35 - 32:38
    commands and then calling the right commands
    on the
  • 32:38 - 32:43
    AT commander. AT, AT because every command
    on the
  • 32:43 - 32:46
    drone begins with the letters AT. It's like
    the
  • 32:46 - 32:48
    guy who wrote this protocol was really hung
    out
  • 32:48 - 32:51
    up on the haze modem protocol.
  • 32:51 - 32:56
    It's AT star, the name of the command, and
  • 32:56 - 33:00
    then strings after that, yeah. So, so the
    high-level
  • 33:00 - 33:02
    commands here, like turn left, get turned
    into a
  • 33:02 - 33:05
    progress command, a key command here, with
    a particular
  • 33:05 - 33:09
    amount of data. This class is responsible
    for generating
  • 33:09 - 33:12
    the stream of text messages that get sent
    to
  • 33:12 - 33:15
    the drone and then the UDP sender class is
  • 33:15 - 33:19
    responsible for actually sending this packet
    over the wire.
  • 33:19 - 33:21
    So it's very clear division of responsibility.
    I really
  • 33:21 - 33:23
    like this design.
  • 33:23 - 33:25
    On this side we have a nav naviga- nav
  • 33:25 - 33:29
    monitor, which monitors the navigation coming
    back from the
  • 33:29 - 33:32
    drone. So it watches for commands like saying,
    OK,
  • 33:32 - 33:34
    I am now this high. Oh, my battery is
  • 33:34 - 33:36
    running out, somebody do something, you know,
    a little
  • 33:36 - 33:39
    messages like that come back over the navigation
    data
  • 33:39 - 33:42
    stream. And then the nav streamer is responsible
    for
  • 33:42 - 33:46
    handing timeout issues on that navigation
    stream.
  • 33:46 - 33:48
    We'll get more on the nav streamer here in
  • 33:48 - 33:49
    a moment.
  • 33:49 - 33:53
    But this is an object diagram. So I thought
  • 33:53 - 33:55
    it would be interesting to look at the class
  • 33:55 - 33:59
    diagram for this, and it looks like this.
  • 33:59 - 34:03
    We can still see the seven objects listed
    here,
  • 34:03 - 34:05
    but now we're showing them at a protocol level.
  • 34:05 - 34:09
    Protocol's the implement. So the drone uses,
    assumes something
  • 34:09 - 34:16
    with this protocol. The controller implements
    the protocol. The
  • 34:16 - 34:21
    drone also then uses a AT commander protocol,
    which
  • 34:21 - 34:22
    the controller also uses.
  • 34:22 - 34:25
    The nav monitor uses this protocol and so
    on
  • 34:25 - 34:27
    and so forth. And so this is really nice.
  • 34:27 - 34:29
    This seems I can test each of these concrete
  • 34:29 - 34:33
    classes very easily, despite providing something
    that responds to
  • 34:33 - 34:34
    the protocol, and they can all be tested independently.
  • 34:34 - 34:38
    It's a little weird, though, looking at this
    diagram,
  • 34:38 - 34:40
    because I have these objects hanging out here
    that
  • 34:40 - 34:44
    nothing connects to. And so this diagram lies
    just
  • 34:44 - 34:47
    a little bit. What's really going on is that
  • 34:47 - 34:49
    I have code that looks like this in the
  • 34:49 - 34:55
    drone. It says, OK, create these concrete
    objects here,
  • 34:55 - 34:57
    unless you override it with something. So
    I can
  • 34:57 - 35:00
    override any of the concrete implementations
    very easily. So
  • 35:00 - 35:03
    it's a really cheap kind of dependency injection
    technique
  • 35:03 - 35:05
    that you can use in Ruby.
  • 35:05 - 35:07
    So that makes it easier to test, but makes
  • 35:07 - 35:09
    it so that if I just use it by
  • 35:09 - 35:12
    default, the right things get built up and
    used.
  • 35:12 - 35:15
    So let's go ahead and draw these relationships
    in
  • 35:15 - 35:17
    and let's mark it with a style that says
  • 35:17 - 35:20
    create, and I'm gonna, I'm gonna do these
    lines
  • 35:20 - 35:23
    in red so we can see them. So the
  • 35:23 - 35:25
    drone will create the monitor, will create
    the controller.
  • 35:25 - 35:28
    It'll create the AT sender. Now everything
    is attached
  • 35:28 - 35:30
    by lines.
  • 35:30 - 35:36
    Notice anything really unusual in this diagram?
  • 35:36 - 35:39
    The drone does almost all the creation, but
    almost
  • 35:39 - 35:41
    all the creation, except for this guy right
    down
  • 35:41 - 35:44
    here. And for some reason nav monitor thought
    it
  • 35:44 - 35:47
    was his responsibility to create the nav streamer
    down
  • 35:47 - 35:51
    here. I'm not sure why.
  • 35:51 - 35:55
    And it wasn't apparent to me, looking at the
  • 35:55 - 35:56
    code, this did not stand out to me looking
  • 35:56 - 35:58
    at the code, until I kind of drew the
  • 35:58 - 36:01
    diagram and saw the create lines pop up here
  • 36:01 - 36:03
    that was different from all of the others.
    So
  • 36:03 - 36:06
    again, the diagram helped me see things that
    I
  • 36:06 - 36:11
    did not see in the code itself.
  • 36:11 - 36:17
    I think, I want talk about that nav streamer
  • 36:17 - 36:19
    thing that handles time outs. but then to
    do
  • 36:19 - 36:21
    that we need to be able to talk about
  • 36:21 - 36:25
    dynamic behavior. So here is a UML diagram
    that's
  • 36:25 - 36:27
    different than we've seen before. This is
    a state
  • 36:27 - 36:32
    diagram and essentially says this class here,
    this toggle
  • 36:33 - 36:37
    class has two states, on and off, ands when,
  • 36:37 - 36:38
    OK so you start in the off state so
  • 36:38 - 36:42
    the black dot indicates where you start.
  • 36:42 - 36:44
    The arrows are transition from state to state
    and
  • 36:44 - 36:48
    the transition happens when you hit a trigger.
    The
  • 36:48 - 36:50
    trigger here is called button push and we
    implement
  • 36:50 - 36:54
    triggers as methods on objects. When you're
    in the
  • 36:54 - 36:56
    off state and you hit a button, then the
  • 36:56 - 36:59
    action you want to take is called turn on.
  • 36:59 - 37:03
    So the trigger happens, button, you look at
    your
  • 37:03 - 37:05
    state you say oh we're off, then we want
  • 37:05 - 37:09
    to turn ourselves on then we switch the state
  • 37:09 - 37:11
    to being on as well. So thats the next
  • 37:11 - 37:12
    state there.
  • 37:12 - 37:14
    So you can look at this, this is a
  • 37:14 - 37:19
    pretty simple state implementation here, but
    looking at the
  • 37:19 - 37:26
    diagram here gives you a lot more information.
    OK,
  • 37:26 - 37:28
    here is another one, I just wanted to show
  • 37:28 - 37:30
    this, this is a recognizer for an imager,
    you
  • 37:30 - 37:32
    start here on the empty state if you get
  • 37:32 - 37:34
    a digit, then you're good as you move to
  • 37:34 - 37:36
    the integer state as long as you keep getting
  • 37:36 - 37:40
    in digits you get that. If you get non-digit
  • 37:40 - 37:41
    then you say, oh yep, we're done, we got
  • 37:41 - 37:44
    our integer. It's just a little recognizer
    here. The
  • 37:44 - 37:46
    dot with the circle is the stop state.
  • 37:46 - 37:50
    So let's talk about the nav streamer now.
    Nav
  • 37:50 - 37:54
    streamer is responsible for handling time
    outs. This is
  • 37:54 - 37:56
    how it works: we start up, we go into
  • 37:56 - 38:02
    the wait state. In the wait state everything,
    unless
  • 38:02 - 38:04
    the thing we expect to get is a start
  • 38:04 - 38:07
    command. The start will issue a reconnect
    that will
  • 38:07 - 38:12
    essentially go out and create a UDP socket
    and
  • 38:12 - 38:17
    will start listening on it right away. It
    also
  • 38:17 - 38:20
    requests the nav data as well. Going to a
  • 38:20 - 38:22
    wait state and as soon as we receive data,
  • 38:22 - 38:25
    we go into a run-state. This is the expected
  • 38:25 - 38:27
    place to be in. If we time out during
  • 38:27 - 38:30
    the run state, either with a short time out,
  • 38:30 - 38:31
    we ignore it.
  • 38:31 - 38:33
    We receive data in the run state. We stay
  • 38:33 - 38:34
    in the run state. But if we get a
  • 38:34 - 38:38
    long time out, long time out is, I think
  • 38:38 - 38:42
    a second or so. Short time outs are like
  • 38:42 - 38:44
    fifty milliseconds, the longer timeouts are
    like a second.
  • 38:44 - 38:47
    So if we get a long time out then
  • 38:47 - 38:49
    I need to reconnect, I need to clobber my
  • 38:49 - 38:54
    UDP socket object, recreate it, re-request
    the nav data
  • 38:54 - 38:55
    and go back to the wait until I receive
  • 38:55 - 38:57
    data again.
  • 38:57 - 38:58
    And in the wait state, if I get a
  • 38:58 - 39:00
    short out, short time out, I gotta keep requesting
  • 39:00 - 39:03
    the nav data because the UDP, it might have
  • 39:03 - 39:05
    missed it. I gotta resend it. So this very
  • 39:05 - 39:11
    succinctly tells me exactly the algorithm
    used by the
  • 39:11 - 39:15
    time out mechanism in UD... in nav streamer.
    So,
  • 39:15 - 39:17
    I like state diagrams, I think we should use
  • 39:17 - 39:20
    more of them.
  • 39:20 - 39:24
    Let's see, what are we dong on time here?
  • 39:24 - 39:28
    You know what? I'm in trouble because I didn't
  • 39:28 - 39:31
    hit the start button on my timer up here.
  • 39:31 - 39:35
    So we've got 10 minutes? Thank you. All right,
  • 39:35 - 39:38
    interactions. We'll go through this really
    quick.
  • 39:38 - 39:42
    Here's flex-mock, a library I wrote for mocking.
    It
  • 39:42 - 39:45
    contains a mock container. Mock containers
    are responsible for
  • 39:45 - 39:48
    managing mocks within a test. This is the
    mock
  • 39:48 - 39:51
    object right here, so a mock container contain
    many
  • 39:51 - 39:55
    mock objects. The mock object records by method
    names,
  • 39:55 - 40:00
    a set of expectations here, and particular
    detailed expectations
  • 40:00 - 40:02
    here.
  • 40:02 - 40:04
    Describing this whole thing here and how these
    interact
  • 40:04 - 40:07
    is very hard to do in words. It's even
  • 40:07 - 40:09
    harder to look at the code and figure out
  • 40:09 - 40:12
    what's going on, so we need a new vocabulary
  • 40:12 - 40:16
    to talk about these. And these are sequence
    diagrams.
  • 40:16 - 40:18
    They're essentially objects here, so it's
    like a object
  • 40:18 - 40:22
    diagram with life times on it. So here in
  • 40:22 - 40:24
    this class we call def drive, def drive calls
  • 40:24 - 40:29
    go_faster, go_faster calls accelerate.engine.
    def drive is- so this
  • 40:29 - 40:31
    is the method called def drive, this is how
  • 40:31 - 40:34
    long its alive. Def drive calls go_faster,
    so this
  • 40:34 - 40:38
    is go_faster right here. Inside of go_faster
    we call
  • 40:38 - 40:41
    accelerte.engine. accelerate.engine returns
    the result. Returns here, go_faster returns
  • 40:41 - 40:43
    to def drive and then def drive returns to
  • 40:43 - 40:46
    the bottom here. It's just a sequence of calls
  • 40:46 - 40:51
    and kind of timing related. So here is the
  • 40:51 - 40:53
    interaction in flux-mock.
  • 40:53 - 40:59
    This is, let's walk through this. A mock gets
  • 40:59 - 41:05
    a message called foo. That triggers a method,
    a
  • 41:05 - 41:09
    message missing, which goes into here. So
    this is
  • 41:09 - 41:13
    message missing right here. Message missing
    immediately creates a
  • 41:13 - 41:15
    call record to record the fact that foo has
  • 41:15 - 41:18
    been called. So we can query it later to
  • 41:18 - 41:21
    see what messages have been called, and then
    goes
  • 41:21 - 41:25
    and locates the proper expectation director.
    That's based upon
  • 41:25 - 41:27
    the name foo. So that's just a hash look
  • 41:27 - 41:27
    up.
  • 41:27 - 41:29
    I didn't record the hash look up in my
  • 41:29 - 41:32
    sequence director because the detail I don't
    want to
  • 41:32 - 41:35
    talk about right now. So then we call call
  • 41:35 - 41:39
    on the hash expectation director and give
    in the
  • 41:39 - 41:43
    arguments to foo and the call record . So
  • 41:43 - 41:47
    then expectation director immediately calls
    find_expectation on itself, passing
  • 41:47 - 41:50
    in the arguments. And then it goes to each
  • 41:50 - 41:55
    of the expectations that it's managing and
    says oh,
  • 41:55 - 41:57
    expectation one, do you match the argument
    that just
  • 41:58 - 42:01
    got passed in and expectation one says, nope,
    false,
  • 42:01 - 42:02
    return.
  • 42:02 - 42:06
    Director says let's go to expectation two.
    And do
  • 42:06 - 42:08
    we match the arguments for this? And this
    expectation
  • 42:08 - 42:12
    says yes, I expect to be called with no
  • 42:12 - 42:14
    arguments, and thats exactly how we're calling
    foo. So
  • 42:14 - 42:17
    yes, I match and I return true and then
  • 42:17 - 42:19
    the director says, oh so you match the arguments.
  • 42:19 - 42:21
    Now are you eligible to be called? We ask
  • 42:21 - 42:25
    eligible because some expectations expect
    to be called once
  • 42:25 - 42:28
    or twice or three times and so have we
  • 42:28 - 42:31
    run out of times you're allowed to call this
  • 42:31 - 42:33
    expectation or not, are we eligible? And says
    yeah,
  • 42:33 - 42:35
    yeah you can still call on me. So eligible
  • 42:35 - 42:41
    returns true. Find_expectation returns expectation
    two here. That's the
  • 42:41 - 42:44
    return value to here, to our call thing.
  • 42:44 - 42:47
    Call then sets the expectation field on the
    call
  • 42:47 - 42:52
    record to indicate which expectation we called,
    and then
  • 42:52 - 42:56
    it calls verify_call and then it asks the
    expectation
  • 42:56 - 43:02
    to calculate the return value for this mocked
    call.
  • 43:02 - 43:05
    And then it returns here to call. Call returns
  • 43:05 - 43:09
    for Message Missing and foo returns from there.
    So
  • 43:09 - 43:12
    that's how we find the expectations in flux-mock.
  • 43:12 - 43:14
    That's a lot of details there, but when I
  • 43:14 - 43:17
    walk you through this, and kind of walk you
  • 43:17 - 43:20
    through it, it's a very easy way to describe
  • 43:20 - 43:24
    it. I like , I like and dislike sequence
  • 43:24 - 43:28
    diagrams. They are the most fragile diagram
    to write
  • 43:28 - 43:29
    because they break all the time. As soon as
  • 43:29 - 43:33
    I change anything, this diagram will be critically
    wrong
  • 43:33 - 43:38
    in some manner. They're also a pain to draw.
  • 43:38 - 43:40
    There's lots of details in here and getting
    everything
  • 43:40 - 43:42
    to match up right, ehh, thats a pain. This
  • 43:42 - 43:45
    took me probably the longest diagram of anything
    to
  • 43:45 - 43:46
    call and to draw it. I have to run
  • 43:46 - 43:49
    through the code myself to understand it.
  • 43:49 - 43:52
    However, the process of walking through the
    code to
  • 43:52 - 43:56
    draw this diagram is worth everything. This
    is one
  • 43:56 - 43:59
    case where I feel the diagram, eh, I have
  • 43:59 - 44:02
    ambivalent feelings about it. But the process
    of writing
  • 44:02 - 44:05
    the diagram means I really gotta understand
    what's going
  • 44:05 - 44:07
    on down underneath the covers and that, to
    me,
  • 44:07 - 44:09
    is the big win of this kind of thing.
  • 44:09 - 44:12
    So UML, you, I find, I draw diagrams, not
  • 44:12 - 44:15
    so much for the diagram's benefit, but a lot
  • 44:15 - 44:18
    for the learning that happens when I draw
    the
  • 44:18 - 44:23
    diagram. So lets summarize here, just really
    quickly. UML
  • 44:23 - 44:27
    is great for detecting dependencies, and that's
    my favorite
  • 44:27 - 44:30
    thing about UML all together. Yeah, lets knock
    down
  • 44:30 - 44:33
    the sign. I guess my favorite thing about
    UML
  • 44:33 - 44:38
    is doing the dependency looks there, looking
    at structure,
  • 44:38 - 44:41
    looking for anomalies in structure when I
    draw the
  • 44:41 - 44:43
    diagram there, it's good for that. It's good
    for
  • 44:43 - 44:46
    denoting dynamic behavior in a way that the
    code
  • 44:46 - 44:50
    kind of obscures sometimes. And then object
    iteration is
  • 44:50 - 44:53
    another feature of UML that is, probably,
    a less-used
  • 44:53 - 44:56
    feature of UML that I personally use, but
    well-worth
  • 44:56 - 44:57
    knowing about.
  • 44:57 - 45:01
    Some tips, if you want to start drawing diagrams,
  • 45:01 - 45:04
    here's some ideas. Decide what idea you want
    to
  • 45:04 - 45:07
    communicate with this particular diagram and
    draw it with
  • 45:07 - 45:11
    that in mind. Don't worry about capturing
    all the
  • 45:11 - 45:14
    details, capture only enough detail so that
    the diagram
  • 45:14 - 45:16
    makes sense to the audience that you're addressing,
    so
  • 45:16 - 45:19
    they can understand the idea that you wish
    to
  • 45:19 - 45:22
    convey.
  • 45:22 - 45:25
    Explore ideas, like I did with that rake re-design
  • 45:25 - 45:28
    thing. Maybe we could re-do it like this.
    Now,
  • 45:28 - 45:30
    that diagram is probably wrong, I probably
    missed some
  • 45:30 - 45:33
    details somewhere, but it was worth exploring,
    gives me
  • 45:33 - 45:35
    an idea of where I might want to go
  • 45:35 - 45:40
    in the future. I recommended you draw the
    diagram.
  • 45:40 - 45:43
    Don't depend upon automated drawing tools
    that examine your
  • 45:43 - 45:46
    source code and put up diagrams. They put
    way
  • 45:46 - 45:48
    too many details in the diagram, they don't
    convey
  • 45:48 - 45:51
    an idea, they convey exactly what the source
    code
  • 45:51 - 45:53
    conveys, so you might as well just look at
  • 45:53 - 45:56
    the source code at that point. It's the editing
  • 45:56 - 45:59
    process that makes the diagram useful.
  • 45:59 - 46:04
    And keep the ephemeral. Don't try to generate
    lots
  • 46:04 - 46:06
    and lots of diagrams for your application,
    thinking, oh,
  • 46:06 - 46:08
    its going to help lots and lots of programmers
  • 46:08 - 46:13
    in the future. A few well-designed, high level
    UML
  • 46:13 - 46:17
    diagrams, placed in the document directory:
    excellent. Lots of
  • 46:17 - 46:20
    detailed diagrams, placed in the document
    directory: gonna get
  • 46:20 - 46:22
    out of date before you know it. It's just
  • 46:22 - 46:24
    not worth it. So, keep the ephemeral. And
    I
  • 46:24 - 46:26
    love white boards for drawing UML.
  • 46:26 - 46:30
    Presentation tips. If you're going to do a
    talk
  • 46:30 - 46:33
    and you're putting UML documents up, make
    the lines
  • 46:33 - 46:37
    two pixels. Who knew they look so much better
  • 46:37 - 46:40
    like that? They look like, oh they mean something.
  • 46:40 - 46:44
    This is, ah, this is wimpy. A good book
  • 46:44 - 46:48
    on UML is UML Distilled. It's this thin book,
  • 46:48 - 46:50
    unlike the thick books you've been buying
    on UML
  • 46:50 - 46:52
    that go into all the gory details. UML Distilled
  • 46:52 - 46:55
    talks about just the essentials of UML and
    can
  • 46:55 - 46:57
    get you going in getting your diagrams up
    and
  • 46:57 - 46:59
    running. It's still pretty good. Some tools?
    White boards,
  • 46:59 - 47:01
    get a white board. We have an office that
  • 47:01 - 47:06
    has three walls of white boards. Humm, I love
  • 47:06 - 47:10
    it. If you want to do it programmeticlly,
    on
  • 47:10 - 47:15
    the cheap, I recommend UMLet. It is a Java
  • 47:15 - 47:18
    application. It's really lightweight, it's
    got a really unusual
  • 47:18 - 47:21
    editing feature, but you can get good looking
    diagrams
  • 47:21 - 47:24
    up and running fairly quickly with UMLet.
  • 47:24 - 47:26
    All the diagrams I did for this talk were
  • 47:26 - 47:30
    done with OmniGraffle, which is, does really
    pretty diagrams.
  • 47:33 - 47:35
    If pretty is important.
  • 47:35 - 47:37
    I think sometimes making them pretty makes
    you feel
  • 47:37 - 47:40
    like you need to keep them around longer than
  • 47:40 - 47:44
    you need to. So I'm not actually recommending
    UML
  • 47:44 - 47:47
    for your day to day UML diagram. White boards
  • 47:47 - 47:50
    is my first choice, UMLet is my second choice.
  • 47:50 - 47:51
    If you're doing a presentation and you want
    it
  • 47:51 - 47:55
    to look pretty, OmniGraffle then is a good
    choice
  • 47:55 - 47:55
    for that.
  • 47:55 - 47:57
    OK, so you're all gonna go and start drawing
  • 47:57 - 47:59
    diagrams instead of writing ruby code?
  • 47:59 - 48:02
    CROWD: Woo-hoo!
Title:
Ruby Conf 2013 - The Big Picture by Jim Weirich
Description:

more » « less
Duration:
48:33

English subtitles

Revisions