< Return to Video

RailsConf 2014 - Bring Fun Back to JS: Step-by-Step Refactoring Toward Ember by Brandon Hays

  • 0:17 - 0:18
    Brandon:Oh, hi.
  • 0:18 - 0:21
    A hush falls over the room
    because I'm not paying attention.
  • 0:21 - 0:23
    My slides came up. Hi.
  • 0:26 - 0:27
    Really quick first,
  • 0:28 - 0:31
    there are seats in the middle
    if people can squish together,
  • 0:32 - 0:34
    otherwise people are
    going to be sitting in the
  • 0:34 - 0:37
    aisles and the fire marshal
    is going to get angry.
  • 0:39 - 0:42
    I don't know that, I'm not a building guy.
  • 0:43 - 0:45
    Hi everybody, sorry to
    make you move around
  • 0:45 - 0:46
    but also maybe that will
    wake you up a little bit.
  • 0:46 - 0:48
    This is going to be a shot of espresso,
  • 0:48 - 0:49
    we've got to go, go, go, go.
  • 0:49 - 0:52
    I have a very serious talk
    about the heart of architecture.
  • 0:54 - 0:58
    As you know, as DHH said at the
    first talk, we are engineers.
  • 0:58 - 1:00
    What we do is build bridges with code.
  • 1:02 - 1:05
    We are architects, we build
    centuries old castles.
  • 1:06 - 1:09
    We are craftspeople, we are
    old-timey metal workers.
  • 1:09 - 1:11
    And we live in the cloud.
  • 1:11 - 1:13
    I think Javascript is ready
    for all of these things.
  • 1:14 - 1:17
    I feel like Javascript is
    ready for Cloudgineering.
  • 1:21 - 1:22
    If anybody knows what any of the things
  • 1:22 - 1:24
    I said with the pretty pictures are,
  • 1:24 - 1:26
    please grab me after the
    talk and explain them to me.
  • 1:27 - 1:29
    I just say them to sound smart and serious
  • 1:29 - 1:31
    about programming, it is serious business.
  • 1:31 - 1:32
    Hi I'm Brandon Hayes,
  • 1:32 - 1:35
    I work with Charles
    actually at The Frontside.
  • 1:35 - 1:42
    I'm a dedicated Cloudgineer
    and no one ever asks which of
  • 1:42 - 1:44
    us is the smart one when
    we converse together,
  • 1:44 - 1:46
    which is a little weird.
  • 1:46 - 1:47
    These are my credentials.
  • 1:47 - 1:49
    As you can see I'm highly credentialed and
  • 1:49 - 1:51
    ready to tell you all about programming.
  • 1:52 - 1:54
    My wife gave me a few of these,
  • 1:54 - 1:56
    most of them are actually true.
  • 2:00 - 2:02
    I'm not here to talk about some
  • 2:02 - 2:07
    core ideal or some big fancy thing.
  • 2:07 - 2:08
    I live in the real world.
  • 2:09 - 2:13
    I have to write programs that
    people want written fast and
  • 2:13 - 2:17
    want them yesterday and it's
    very challenging some times.
  • 2:17 - 2:21
    I understand that
    architecture is great but
  • 2:21 - 2:23
    I don't have a lot of use
    for ivory tower people,
  • 2:23 - 2:25
    I think the universe has
    plenty of uncles in it.
  • 2:27 - 2:29
    We live in a place,
  • 2:29 - 2:31
    and I'm going to tell you a
    tale about a couple of places.
  • 2:32 - 2:34
    It's actually a meta talk about the
  • 2:34 - 2:35
    ball of mud architecture pattern,
  • 2:35 - 2:37
    that's one I can really get behind.
  • 2:37 - 2:40
    If you're not familiar
    with this, Brian Foote,
  • 2:40 - 2:43
    I believe in the late 1970s,
    described an architecture
  • 2:43 - 2:46
    pattern that everyone here has
    seen called the ball of mud.
  • 2:47 - 2:49
    To do that I need to
    talk about city planning.
  • 2:50 - 2:52
    Most cities are not designed for growth.
  • 2:52 - 2:54
    Salt Lake City would be a rare exception.
  • 2:55 - 2:57
    You'll see it handled its
    eventual growth pretty well.
  • 2:58 - 3:01
    From layout to infrastructure
    it seems to have avoided
  • 3:01 - 3:04
    many of the problems
    that plague large cities.
  • 3:04 - 3:06
    Our code does not live in Salt Lake City,
  • 3:06 - 3:07
    they don't work like that.
  • 3:08 - 3:11
    My current home town of
    Austin is a lot more typical.
  • 3:13 - 3:16
    I look at that every day
    on my drive home while
  • 3:16 - 3:18
    Charles rides his bike
    home, which is great.
  • 3:18 - 3:20
    I get to sit in that every day for
  • 3:20 - 3:21
    about 45 minutes on the way home.
  • 3:22 - 3:24
    The city layout and
    infrastructure was not prepared
  • 3:24 - 3:26
    for the kind of growth
    that they've experienced.
  • 3:26 - 3:28
    That results in the dreaded urban sprawl.
  • 3:29 - 3:32
    But we don't actually even live here.
  • 3:32 - 3:33
    Let's be honest about our
    code for a minute people.
  • 3:34 - 3:35
    We live here.
  • 3:38 - 3:40
    It's not a sprawling metroplex
  • 3:40 - 3:41
    or a beautifully planned city.
  • 3:41 - 3:43
    We live in a favela.
  • 3:43 - 3:45
    A favela is a Brazilian slum, basically.
  • 3:45 - 3:47
    It looks like cool though, right?
  • 3:47 - 3:51
    It's the definition of a
    walkable city -- well, hikeable.
  • 3:52 - 3:53
    Let's zoom in.
  • 3:55 - 3:58
    A favela is a Brazilian
    shanty town made permanent.
  • 3:58 - 4:02
    The structures require little
    skill to create and they
  • 4:02 - 4:06
    pop up everywhere out of
    whatever materials can be found.
  • 4:06 - 4:08
    The problem is these structures are
  • 4:08 - 4:10
    difficult to grow, to maintain or protect.
  • 4:11 - 4:13
    There's little police
    presence or fire presence,
  • 4:13 - 4:16
    and safety and crime
    issues are pretty rampant.
  • 4:17 - 4:19
    Forget architecture stuff,
  • 4:19 - 4:21
    we're going to go in to a code favela,
  • 4:22 - 4:23
    it will look familiar to you.
  • 4:23 - 4:25
    You've probably had some that made you
  • 4:25 - 4:27
    nearly go crazy trying to maintain it.
  • 4:27 - 4:29
    I apologize in advance
    for making you look at
  • 4:29 - 4:32
    this but I really need
    you to feel my pain.
  • 4:34 - 4:37
    That favela is a
    manifestation of the ball of
  • 4:37 - 4:39
    mud pattern, which is
    really easy to create.
  • 4:39 - 4:42
    You just need to build
    something temporary,
  • 4:42 - 4:45
    add to it, and then rely
    on it for your business.
  • 4:45 - 4:47
    They're so easy to create
    that it's the dominant
  • 4:47 - 4:51
    architecture pattern, I would
    contest, in software today.
  • 4:52 - 4:53
    Let's talk about how this happens.
  • 4:54 - 4:55
    Should be pretty easy right,
  • 4:55 - 4:57
    you can probably make
    this happen this week.
  • 4:59 - 5:02
    I need a show of hands.
    How many of you hate being
  • 5:02 - 5:04
    asked to raise your hands in a talk?
  • 5:06 - 5:08
    I should see no hands, that is insane.
  • 5:10 - 5:11
    How many of the rest of you have a
  • 5:11 - 5:14
    prototype that is shipped to production?
  • 5:15 - 5:16
    Pretty good balance there.
  • 5:20 - 5:22
    They say, "This is a two week feature,
  • 5:22 - 5:23
    "let's ship this thing in two weeks."
  • 5:23 - 5:24
    I don't believe in two week features,
  • 5:24 - 5:26
    I don't think that's actually a thing.
  • 5:26 - 5:29
    We do try to cram features
    in to two weeks and then make
  • 5:29 - 5:31
    sacrifices to get them out the
    door, or we inherit code from
  • 5:31 - 5:34
    less experienced developers
    and it has to ship.
  • 5:35 - 5:38
    But mostly these shanty towns
    start as a quick prototype.
  • 5:39 - 5:41
    Let's go ahead and build a shanty town.
  • 5:41 - 5:43
    It starts off like pretty much any other.
  • 5:44 - 5:46
    Let's say we're all working on Giffindor.
  • 5:47 - 5:49
    It's a social network for animated gifs.
  • 5:50 - 5:52
    The founder is a huge Harry
    Potter fan, cosplayer,
  • 5:52 - 5:55
    the whole thing. Has the
    glasses, it's adorable.
  • 5:55 - 5:56
    Personally I'm more a Hufflepuff,
  • 5:56 - 5:57
    this is not my website though.
  • 5:58 - 6:00
    It's a vanilla server-side app in Rails.
  • 6:01 - 6:05
    One note on pronunciation.
    I'm going to stake a stand.
  • 6:05 - 6:07
    I'm going to say that gif is
    pronounced like GitHub Gist.
  • 6:09 - 6:11
    I do the same thing
    with JSON and [JAY-sin].
  • 6:12 - 6:13
    I like to make everybody mad.
  • 6:13 - 6:15
    Mix tabs and spaces, people love me.
  • 6:16 - 6:17
    Back to work.
  • 6:18 - 6:20
    Let's just sprinkle in
    a little interactivity.
  • 6:21 - 6:22
    Let's start with sprinkles, they're fun,
  • 6:22 - 6:24
    sprinkles are fun, yay!
  • 6:26 - 6:28
    Your boss calls. She says,
    "We want a better experience
  • 6:28 - 6:30
    "on the site. Our users
    demand it. They should not
  • 6:30 - 6:32
    "have to go through a
    page refresh all the way
  • 6:32 - 6:35
    "to the new page to submit
    a new animated gif."
  • 6:36 - 6:37
    You look at your Javascript file.
  • 6:39 - 6:42
    Nothing there, undaunted
    you march forward.
  • 6:42 - 6:45
    Easy right? Just make a little HTML form
  • 6:45 - 6:47
    on the page with show hide, all done.
  • 6:48 - 6:51
    That worked, except it submits and
  • 6:51 - 6:53
    does a full page refresh on submit.
  • 6:53 - 6:54
    "Can you do that by AJAX,
  • 6:54 - 6:56
    "it's kind of irritating to our users?"
  • 6:56 - 6:58
    All right, that's what AJAX is for, right?
  • 6:58 - 7:00
    We submit this thing via AJAX.
  • 7:01 - 7:03
    That seems to work, all right.
  • 7:04 - 7:06
    But now you actually
    have to add that new POST
  • 7:06 - 7:08
    to the list of POSTs
    that are on that page.
  • 7:09 - 7:10
    All right, no problem.
  • 7:10 - 7:12
    Okay, a little bit of a problem.
  • 7:13 - 7:16
    We're starting to duplicate
    some DOM code here in your
  • 7:16 - 7:19
    Javascript so you get to
    edit stuff in two places.
  • 7:19 - 7:24
    A little duplication. We know,
    we don't de-duplicate first.
  • 7:25 - 7:27
    You're agile so you agile that code right
  • 7:27 - 7:29
    in there until this whole thing is agile!
    (laughter and applause)
  • 7:30 - 7:33
    By the way that's a trademark
    of Cloudgineering Inc.
  • 7:33 - 7:36
    so do not use that without
    written permission.
  • 7:37 - 7:40
    So this sprinkle is starting
    to turn in to a little more
  • 7:40 - 7:43
    of a rain shower, a little
    bit of a steady rain.
  • 7:43 - 7:45
    But cheer up Keanu, we
    shipped some software, right?
  • 7:46 - 7:49
    Okay, sport. The product
    manager, who tends to look
  • 7:49 - 7:52
    like Fred MacMurray for some
    reason, is really happy.
  • 7:53 - 7:55
    He has more ideas. He wants
    users to be able to click
  • 7:55 - 7:57
    a cancel button so that
    they zero out the form,
  • 7:57 - 7:59
    because if you open it
    it's just stuck there.
  • 8:01 - 8:03
    Dutifully you implement the cancel button
  • 8:03 - 8:05
    and zero out the form with jQuery.
  • 8:05 - 8:08
    Awesome, except now users
    are hitting submit on
  • 8:08 - 8:10
    empty and invalid forms,
    so we need some sort of
  • 8:10 - 8:13
    client-side validation to
    prevent that from happening.
  • 8:13 - 8:14
    It shouldn't be too hard to tell if
  • 8:14 - 8:17
    somebody has attached
    an animated gif link.
  • 8:19 - 8:22
    It wasn't super, super
    easy but it was relatively
  • 8:22 - 8:24
    straight forward. We disable
    the submit button unless
  • 8:24 - 8:27
    it's valid and show messages with jQuery.
  • 8:27 - 8:29
    This is starting to look
    a little weird, right?
  • 8:29 - 8:31
    It's starting to really come down.
  • 8:32 - 8:34
    Poor Al Roker.
  • 8:35 - 8:37
    Your CEO comes in to congratulate you
  • 8:37 - 8:38
    on all the great work you've done.
  • 8:38 - 8:41
    You've really shipped a lot
    of code and agiled everything
  • 8:41 - 8:44
    and you just need a
    couple more enhancements.
  • 8:44 - 8:47
    Let's add an inline preview
    for that image so users know
  • 8:47 - 8:49
    what they're about to
    post before they post it,
  • 8:49 - 8:52
    and a little character
    count that doesn't ding them
  • 8:52 - 8:54
    for long urls. We want
    a smart character count.
  • 8:56 - 8:57
    That's working but
    actually broke a couple of
  • 8:57 - 9:00
    other things about the state of this form.
  • 9:00 - 9:03
    We do some double checking
    and enable or disable submit.
  • 9:05 - 9:07
    Now you're caught
    between these two worlds.
  • 9:07 - 9:10
    You want to craft code that
    you can be proud of and that
  • 9:10 - 9:13
    lets you feel good about
    the things that you do,
  • 9:13 - 9:14
    but you also want to
    be able to ship stuff.
  • 9:14 - 9:17
    Your business needs you to
    move fast and break things.
  • 9:17 - 9:20
    You need to get stuff done,
    GSD. Craftsmanship, ship it.
  • 9:21 - 9:22
    I say craftmanship it.
  • 9:22 - 9:25
    (laughter)
  • 9:25 - 9:28
    (hesitant applause)
  • 9:29 - 9:31
    It's a good thing you're
    a cloudgineer and you
  • 9:31 - 9:33
    can straddle these two
    worlds just perfectly.
  • 9:34 - 9:37
    Look at all this code that
    we've craftsmanshipped.
  • 9:38 - 9:41
    Sandy Metz talked
    yesterday about code shape
  • 9:41 - 9:43
    and the squint test as an indicator.
  • 9:43 - 9:46
    When I squint this code has a shape and
  • 9:46 - 9:48
    that shape is a sack of hot garbage.
  • 9:48 - 9:50
    (laughter)
  • 9:50 - 9:52
    I don't know if Chicago
    has this but in Manhattan
  • 9:52 - 9:54
    in the summer time you get this nice smell
  • 9:54 - 9:56
    wafting off of the hot
    garbage, it's great.
  • 9:56 - 9:58
    That's kind of how it feels.
  • 9:58 - 10:03
    Here we are, a total tsunami
    of entangled jQuery code.
  • 10:03 - 10:06
    (laughter)
  • 10:06 - 10:08
    Let's ship a feature against that.
  • 10:10 - 10:13
    Please, it's really important!
  • 10:14 - 10:16
    Your CEO is now putty in your hands,
  • 10:16 - 10:19
    you are a superstar
    developer and the expectation
  • 10:19 - 10:21
    is now that you just shipped so fast.
  • 10:21 - 10:24
    And a light button, let's do it.
  • 10:24 - 10:27
    Here's the thing. I was going
    to implement this in jQuery,
  • 10:27 - 10:29
    I was going to do it
    but there was already so
  • 10:29 - 10:31
    much double checking and
    interwoven states that
  • 10:31 - 10:34
    I physically couldn't
    without getting really ill.
  • 10:35 - 10:37
    The thought of touching
    this code made me want
  • 10:37 - 10:38
    to quit writing the talk and just be like,
  • 10:38 - 10:40
    "You know what RailsConf, thanks anyway."
  • 10:41 - 10:43
    Now what, what do we do?
  • 10:43 - 10:46
    Actually Brian Foote has prescriptions for
  • 10:46 - 10:47
    dealing with the ball of mud pattern,
  • 10:47 - 10:49
    and it's not always what you think.
  • 10:49 - 10:51
    You don't necessarily dive
    right into a refactor.
  • 10:51 - 10:53
    Addressing a ball of
    mud is pretty difficult.
  • 10:54 - 10:55
    We can sweep it all under the rug,
  • 10:55 - 10:57
    or put it inside of a black box.
  • 10:58 - 10:59
    You can reconstruct it,
  • 10:59 - 11:03
    tear the whole thing down
    and raze it and rebuild it.
  • 11:03 - 11:04
    You can renovate block-by-block,
  • 11:04 - 11:06
    which he calls keeping it working,
  • 11:06 - 11:09
    or you can quit you job,
    which in some cases,
  • 11:09 - 11:11
    sometimes it's the thing to do.
  • 11:12 - 11:13
    Black box is fine if you know you're never
  • 11:13 - 11:15
    going to have to touch that code again.
  • 11:15 - 11:17
    If it's some complicated math equation or
  • 11:17 - 11:18
    something I've seen that done, where you
  • 11:18 - 11:21
    just hide it in the
    closet and that's fine.
  • 11:21 - 11:24
    A rewrite is a great way
    to learn really amazingly
  • 11:24 - 11:27
    hidden lessons about your business logic.
  • 11:27 - 11:29
    Things that are encoded
    in very strange places.
  • 11:29 - 11:31
    It's a really great way
    to make something that
  • 11:31 - 11:33
    sounds like it takes two
    weeks take six months.
  • 11:36 - 11:38
    I feel like you always
    discover that hidden
  • 11:38 - 11:41
    business logic so let's
    talk about a refactor.
  • 11:42 - 11:43
    Why would we do that?
  • 11:44 - 11:45
    We decided that refactor
    is probably the right
  • 11:45 - 11:47
    thing to do because the feature has to be
  • 11:47 - 11:49
    maintained but it's now
    too expensive to manage.
  • 11:49 - 11:51
    Users are starting to
    actually have a bad time with
  • 11:51 - 11:53
    it because the longer
    they stay on the page the
  • 11:53 - 11:55
    more likely they are to
    have problems with it.
  • 11:56 - 11:59
    And more importantly to me personally is
  • 11:59 - 12:01
    that you are tossing
    and turning all night.
  • 12:01 - 12:03
    You cannot sleep because
    you're dreaming about the JIRA
  • 12:03 - 12:05
    tickets that are waiting
    for you in the morning.
  • 12:05 - 12:06
    Why are we still using
    JIRA, why is that a thing?!
  • 12:06 - 12:08
    Okay, anyway, separate deal.
  • 12:10 - 12:13
    You think about your
    frustrated users, your gut is
  • 12:13 - 12:15
    telling you to fix it and
    your gut is totally right.
  • 12:16 - 12:18
    You have two paths out of here.
  • 12:18 - 12:21
    I think the person in this
    room, super smart guy, is like,
  • 12:21 - 12:25
    "Why don't you refactor this
    to smart Javascript objects?"
  • 12:25 - 12:29
    He's largely right. That's an
    ideomatic way to dig out of this.
  • 12:30 - 12:32
    He also asked me if I
    did that as a strawman
  • 12:32 - 12:35
    of how to build really
    terrible jQuery code.
  • 12:35 - 12:39
    I was like, "Yeees. I
    was not doing my best."
  • 12:41 - 12:42
    The other option is to use a framework
  • 12:42 - 12:45
    to abstract away the DOM and handle data.
  • 12:46 - 12:48
    Our goal is to get the heck out of
  • 12:48 - 12:49
    the DOM as fast as humanly possible.
  • 12:50 - 12:52
    That's our biggest pain point right now.
  • 12:52 - 12:54
    For me I'll choose a framework.
  • 12:54 - 12:55
    The framework will manage the DOM and
  • 12:55 - 12:57
    we'll just manage the underlying data.
  • 12:58 - 13:01
    All we need to do now is
    five steps to get out.
  • 13:03 - 13:05
    These steps will probably
    apply for people that
  • 13:05 - 13:08
    use plain Javascript and
    don't use a framework,
  • 13:08 - 13:10
    or any framework that you choose.
  • 13:10 - 13:12
    It's just nice to build up against one,
  • 13:12 - 13:14
    personally I certainly prefer it.
  • 13:15 - 13:17
    On our blog we'll talk more about why
  • 13:17 - 13:19
    we choose Ember and why we like it,
  • 13:19 - 13:21
    and you heard Charles mention
    earlier if you were here,
  • 13:21 - 13:23
    about why we like Ember's model layer.
  • 13:23 - 13:26
    I feel like it's a really
    strong model layer for
  • 13:26 - 13:28
    the case that we're
    trying to accomplish now.
  • 13:28 - 13:30
    It has really great
    bindings and managed state,
  • 13:30 - 13:31
    and it's got a great drop in component
  • 13:31 - 13:33
    library to tie it all together.
  • 13:33 - 13:37
    Step one, let's rap it. Rap
    it, rap it, rap it, wrap it.
  • 13:40 - 13:42
    A little sidetrack, a lot
    of people don't realize
  • 13:42 - 13:44
    that you can sprinkle Ember into an app.
  • 13:45 - 13:47
    A lot of people think that
    Ember only works if you want to
  • 13:47 - 13:50
    start an app from scratch and
    build up from the ground up,
  • 13:50 - 13:53
    from floor zero all the way to
    the top, but you can actually
  • 13:53 - 13:54
    apply it to a lot of
    codebases and it's really
  • 13:54 - 13:57
    great for refactoring
    existing codebases toward it.
  • 13:58 - 14:02
    That's just these three steps right here.
  • 14:02 - 14:04
    At The Frontside we do
    that pretty often where
  • 14:04 - 14:08
    we take an existing Rails
    application and move
  • 14:08 - 14:11
    it towards Ember, but it's
    actually not that hard.
  • 14:11 - 14:13
    First things first it's
    time for some justice.
  • 14:13 - 14:16
    We're going to put that
    terrible code in code jail.
  • 14:16 - 14:19
    That code jail is this
    initLegacyCode function.
  • 14:19 - 14:22
    We're going to create an Ember
    component, we're going to
  • 14:22 - 14:25
    put the stuff in initLegacyCode,
    which is not a special name,
  • 14:25 - 14:29
    I just chose it to tell
    me that this is the jail.
  • 14:29 - 14:32
    It bootstraps the old
    code inside the component.
  • 14:32 - 14:34
    We do not alter that code at all.
  • 14:34 - 14:37
    Also we move the HTML in to a handlebars
  • 14:37 - 14:39
    template associated with this component.
  • 14:40 - 14:42
    No structure of that
    HTML actually changes,
  • 14:42 - 14:44
    we're just isolating.
  • 14:45 - 14:48
    Then we can sprinkle. Now we
    use jQuery to stuff all of
  • 14:48 - 14:52
    this old stuff that we had
    before back in to the DOM.
  • 14:54 - 14:57
    Another thing Sandy said
    yesterday that I hope
  • 14:57 - 14:59
    it's self evident, it's certainly
    made itself self evident
  • 14:59 - 15:03
    to me over the course of the
    last year or two doing this,
  • 15:03 - 15:04
    that you have to test it.
  • 15:05 - 15:09
    If you do not test your code a refactor is
  • 15:09 - 15:12
    essentially impossible, I
    cannot imagine trying to do it.
  • 15:12 - 15:14
    I was not a big testing advocate earlier.
  • 15:14 - 15:17
    I was very skeptical,
    let's say, about testing.
  • 15:17 - 15:20
    I was raised by cowboy coders in my first
  • 15:20 - 15:22
    place when I was learning to program.
  • 15:22 - 15:25
    But we're going to do it and
    we're going to see that it's
  • 15:25 - 15:27
    actually not that hard to
    actually test the thing itself.
  • 15:28 - 15:30
    We're going to test that
    it shows up and it passes.
  • 15:34 - 15:35
    I'm doing a little bit of a hand wave
  • 15:35 - 15:38
    here over Javascript testing setup.
  • 15:39 - 15:43
    Javascript test setup story
    for getting Ember applications
  • 15:43 - 15:47
    bootstrapped in Rails can
    be a little challenging.
  • 15:47 - 15:49
    There's a growing body
    of knowledge about it.
  • 15:49 - 15:51
    I want to give you guys
    a quick note on that.
  • 15:51 - 15:53
    On its own, Javascript
    testing is pretty easy
  • 15:53 - 15:55
    but when you add in frameworks
    and tie it to Rails,
  • 15:55 - 15:56
    add in the asset pipeline,
  • 15:56 - 15:58
    things can get a little complicated.
  • 15:58 - 16:00
    It's a little bit of a wild west,
  • 16:00 - 16:01
    there's a lot of choices out there.
  • 16:01 - 16:03
    There's a little bit of
    paralysis of choice I think.
  • 16:03 - 16:05
    It's really wide open,
    but not like home on the
  • 16:05 - 16:09
    range wide open, more like
    this kind of wild west.
  • 16:10 - 16:14
    It can lead to that, you
    look at the thing of,
  • 16:14 - 16:16
    "I don't know what brand
    of toothpaste I want,
  • 16:16 - 16:17
    "I just want some toothpaste."
  • 16:18 - 16:19
    There's not really a truly accepted happy
  • 16:19 - 16:21
    path just yet but it is getting better.
  • 16:22 - 16:23
    Things are maturing,
    we're building schools,
  • 16:23 - 16:25
    we're building hospitals still.
  • 16:26 - 16:28
    There's a lot of a need
    for libraries and blog
  • 16:28 - 16:31
    posts and people finding
    these happy paths.
  • 16:31 - 16:33
    Taking aside for 15 minutes,
    there are screen casts
  • 16:33 - 16:35
    being released right now,
    there's a thing called
  • 16:35 - 16:38
    Ember Sparks where he's
    teaching people how to
  • 16:38 - 16:40
    set up and bootstrap your
    application environment.
  • 16:40 - 16:43
    We're all still figuring this
    out there, so be prepared
  • 16:43 - 16:47
    for a little bit of rough
    take off on this still.
  • 16:48 - 16:51
    Another thing is testing
    AJAX can feel a little
  • 16:51 - 16:52
    intimidating when you're
    trying to test Javascript
  • 16:52 - 16:53
    but it's actually pretty simple.
  • 16:53 - 16:55
    There are multiple libraries
    to do this kind of thing
  • 16:55 - 16:57
    I like ic-ajax.
  • 17:00 - 17:04
    It intercepts AJAX calls and
    allows you to inject fixtures in.
  • 17:05 - 17:09
    Here we're going to test each
    path through the experience.
  • 17:09 - 17:11
    In this one we're testing that clicking
  • 17:11 - 17:13
    submit shows a success message.
  • 17:13 - 17:15
    We just want to go through
    and verify that all the
  • 17:15 - 17:18
    things that the code says
    it does it's actually doing.
  • 17:19 - 17:21
    We're not changing any code,
  • 17:21 - 17:23
    we're just wrapping it in test existing.
  • 17:25 - 17:26
    And that passes.
  • 17:26 - 17:29
    Okay. At this point we
    repeat for each path
  • 17:29 - 17:31
    to create an integration
    test for the entire
  • 17:31 - 17:34
    application stubbed at the API level.
  • 17:34 - 17:37
    This took several hours
    but it's really important.
  • 17:37 - 17:39
    As I said if you don't have a test harness
  • 17:39 - 17:40
    I do not know how you can refactor.
  • 17:40 - 17:43
    Maybe if somebody has another
    answer we can discuss it,
  • 17:43 - 17:45
    because testing is not my
    favorite thing in the world.
  • 17:47 - 17:49
    We can now move forward
    with some confidence.
  • 17:49 - 17:51
    Go ahead and take yourself a
    victory lap, you earned it.
  • 17:51 - 17:53
    This is, however, just the start.
  • 17:54 - 17:57
    Step three is to identify models.
  • 17:57 - 18:00
    You have this blob of code,
    how do you find models in here?
  • 18:00 - 18:02
    Your server MVC might give you some hints.
  • 18:03 - 18:06
    I don't believe that your
    models will map one to one,
  • 18:06 - 18:08
    but it's a really great place to start.
  • 18:09 - 18:12
    In this one we actually get to
    start driving with the tests.
  • 18:13 - 18:15
    Sometimes I test drive, sometimes I don't,
  • 18:15 - 18:19
    I'm not an expert at either
    style, but I do think that
  • 18:19 - 18:22
    in this case it was pretty
    good to say, "I know that I
  • 18:22 - 18:24
    "have a model and I know
    part of what a model is
  • 18:24 - 18:27
    "going to parse out an animated gif url
  • 18:27 - 18:29
    "and tell me whether it
    is one or is not one."
  • 18:31 - 18:34
    With no code that thing
    should fail, and it does.
  • 18:35 - 18:37
    Now let's extract it.
  • 18:37 - 18:39
    We can actually extract some
    of that logic to a model.
  • 18:40 - 18:43
    And we can extract the
    animated gif link from
  • 18:43 - 18:46
    the POST body and give it a property here.
  • 18:46 - 18:48
    This is called a computed
    property where you see parsedUrl.
  • 18:48 - 18:50
    It does some functiony stuff
    and then it has a little
  • 18:50 - 18:52
    declaration at the end
    that says property body.
  • 18:52 - 18:55
    It means that we're going
    to depend on the body,
  • 18:55 - 18:58
    which is the blob of data
    that somebody just types in,
  • 18:58 - 19:00
    the text that they type in.
  • 19:01 - 19:02
    At any time a person changes that,
  • 19:02 - 19:04
    any time that changes
    it's going to observe and
  • 19:04 - 19:06
    update this parsedUrl
    property on this object.
  • 19:09 - 19:13
    Now those unit tests will pass
    and we can start turning that
  • 19:13 - 19:18
    static content into the dynamic
    content using handlebars.
  • 19:19 - 19:21
    This lets us kill some
    code, that's pretty awesome.
  • 19:22 - 19:25
    This should get the older
    acceptance test passing again.
  • 19:25 - 19:29
    It is the coolest feeling in
    the world to write some tests,
  • 19:29 - 19:31
    take some code, scrub
    some garbage out of it,
  • 19:31 - 19:34
    do something really dangerous feeling,
  • 19:34 - 19:35
    like jump off the cliff
    and know, when you rerun
  • 19:35 - 19:38
    those tests and they start passing again,
  • 19:38 - 19:39
    and you start getting green
    again after a refactor,
  • 19:39 - 19:41
    it's really fun.
  • 19:41 - 19:43
    In this case we didn't do that much,
  • 19:43 - 19:44
    we didn't have to write
    that much code because
  • 19:44 - 19:46
    we let the framework
    carry our matched luggage
  • 19:46 - 19:48
    for it which we cannot live without.
  • 19:49 - 19:51
    The models hold onto your data,
  • 19:51 - 19:54
    they keep it up to date and
    the changes in the DOM are
  • 19:54 - 19:57
    just going to automatically
    propagate out of that.
  • 19:58 - 20:00
    Now we're going to lean even
    harder into the framework.
  • 20:01 - 20:03
    It actually is sort of the
    fun part, identifying the
  • 20:03 - 20:05
    states is more fun than
    identifying models, I think,
  • 20:05 - 20:07
    because we get to go back through the
  • 20:07 - 20:08
    app and pick out what these states are.
  • 20:09 - 20:11
    In this little widget the first state is
  • 20:11 - 20:13
    a blank state, a initial state where the
  • 20:13 - 20:15
    button is just visible
    and nothing else is.
  • 20:16 - 20:17
    When we click it the button goes away and
  • 20:17 - 20:19
    the thing is in a ready-to-save state.
  • 20:20 - 20:22
    While data is in flight
    we're going to disable
  • 20:22 - 20:24
    the post button, leave
    everything else the same.
  • 20:25 - 20:26
    On an error state we're going to leave
  • 20:26 - 20:29
    the text intact but display a message.
  • 20:31 - 20:33
    On success we're going to display a
  • 20:33 - 20:34
    success message and hide the form.
  • 20:35 - 20:37
    After five seconds we want it
    to reset to that initial state.
  • 20:37 - 20:39
    That's kind of the business
    logic that we wanted
  • 20:39 - 20:42
    in the first place but we
    incrementally built it.
  • 20:42 - 20:45
    That's an okay way to
    find out what you want but
  • 20:45 - 20:47
    not a great way to ship to
    production, as we found.
  • 20:48 - 20:50
    The component starts
    in this initial state.
  • 20:50 - 20:52
    We bind that state to a
    class on the component's DOM,
  • 20:53 - 20:56
    and then we'll use that later to let CSS
  • 20:56 - 20:58
    manage what is shown and what is hidden.
  • 20:58 - 21:01
    We want the DOM to just
    be a representation of the
  • 21:01 - 21:03
    state of the app. The DOM
    is just there to represent
  • 21:03 - 21:05
    the app's state at any given time.
  • 21:05 - 21:08
    It's kind of almost read-only.
  • 21:08 - 21:10
    Now instead of managing
    the DOM with jQuery
  • 21:10 - 21:11
    we're going to have buttons fire off
  • 21:11 - 21:13
    actions that just push the state around.
  • 21:13 - 21:15
    "You go here, you go here,"
  • 21:15 - 21:19
    they're like the train conductors
    in a Japanese train station.
  • 21:19 - 21:21
    It's kind of a lazy developer's state
  • 21:21 - 21:23
    machine but it's going to do for now.
  • 21:24 - 21:25
    Step four, that's done.
  • 21:25 - 21:27
    That was all the code we needed for state.
  • 21:27 - 21:30
    Step four is to break up the
    remaining code left in code jail.
  • 21:30 - 21:32
    The states and model are
    in place and are tested,
  • 21:32 - 21:34
    but there's a couple of ugly things left.
  • 21:34 - 21:37
    Let's look at it. Code jail is not empty.
  • 21:37 - 21:39
    The legacy code still reaches outside the
  • 21:39 - 21:42
    component to delete things in a wonky way.
  • 21:43 - 21:46
    And, heh heh, hi, how are you.
  • 21:47 - 21:49
    I want to rub your nose in this code,
  • 21:49 - 21:50
    even though I'm the one that wrote it.
  • 21:52 - 21:53
    What could possibly go wrong here, right?
  • 21:55 - 21:59
    This POST is pretty scary.
    It's painful to modify,
  • 21:59 - 22:02
    it invites pain for the
    user but listing POST
  • 22:02 - 22:04
    is outside the responsibility
    of this component
  • 22:04 - 22:06
    we've created so what can we do about it?
  • 22:08 - 22:09
    Actually we have a pattern
    that we've already laid out.
  • 22:09 - 22:10
    Let's create another component and
  • 22:10 - 22:12
    sprinkle it in for listing those POSTs.
  • 22:13 - 22:15
    Another quick detour in to Ember Data.
  • 22:15 - 22:17
    At this point I have a choice to make.
  • 22:17 - 22:20
    Do I want to make sharing
    this information with you more
  • 22:20 - 22:23
    complicated by talking about
    Ember Data and I think I do,
  • 22:23 - 22:25
    it actually made the
    next steps much easier,
  • 22:25 - 22:28
    and this detour actually
    took me about 20 minutes to
  • 22:28 - 22:30
    replace the model with
    an Ember Data model.
  • 22:30 - 22:33
    Ember data is basically a
    wrapper that talks to AJAX
  • 22:33 - 22:37
    for you and converts to
    an Ember model for you.
  • 22:38 - 22:40
    It buys us lots of good things.
  • 22:40 - 22:42
    Basically took just a few minutes to do.
  • 22:42 - 22:46
    That's it, we just declare
    it as a model on Ember Data.
  • 22:48 - 22:51
    I like to wire in an ic-ajax,
    just like we did before,
  • 22:51 - 22:54
    to Ember Data and this is all
    the work that it takes to do.
  • 22:54 - 22:56
    Fixtures will still work as written.
  • 22:56 - 22:59
    This was all it took to get
    the tests passing again.
  • 23:00 - 23:02
    That's pretty much it
    for the list component.
  • 23:02 - 23:04
    As you can see I have a delete function,
  • 23:04 - 23:06
    a place to reference the list, that's it.
  • 23:06 - 23:09
    It has a list of those posts
    and a way to delete one of them.
  • 23:09 - 23:12
    All I'm doing is
    destroying a model record.
  • 23:14 - 23:15
    The second set of tests here is pretty
  • 23:15 - 23:18
    much going to follow the
    first. This test shows
  • 23:18 - 23:21
    that the animated gifs
    show up as expected,
  • 23:21 - 23:23
    and from here we can drive
    out the delete functionality.
  • 23:24 - 23:27
    We have a second template to
    replace the server-side markup
  • 23:28 - 23:31
    and then we sprinkle it in
    just like the first one.
  • 23:31 - 23:33
    We say, "Hey, jQuery, take this
    component and stuff it in to
  • 23:33 - 23:35
    "the DOM for me where that
    list of posts used to be,"
  • 23:36 - 23:37
    and Ember is going to
    show that for us now.
  • 23:38 - 23:39
    That's interesting, we
    have two components.
  • 23:39 - 23:41
    How are they talking to each other?
  • 23:41 - 23:43
    Well they both react to
    changes to the underlying data.
  • 23:43 - 23:46
    There's a pool underneath that is the
  • 23:46 - 23:48
    same shared data set but the components
  • 23:48 - 23:50
    are completely isolated from one another.
  • 23:50 - 23:52
    They can only communicate by altering
  • 23:52 - 23:53
    that pool of underlying data.
  • 23:55 - 23:57
    Changes in one place can affect the other.
  • 23:58 - 24:00
    There's a lot of boilerplate
    code we did not write here.
  • 24:00 - 24:01
    We just trust that the
    data layer is going to do
  • 24:01 - 24:04
    its job and the DOM will
    represent it properly.
  • 24:05 - 24:08
    One thing that happened though is because
  • 24:08 - 24:11
    we're not doing stuff
    with jQuery UI animation
  • 24:11 - 24:13
    stuff any more we lost
    show hide functionality,
  • 24:13 - 24:15
    so let's put that back.
  • 24:15 - 24:17
    We're going to use CSS transitions
  • 24:17 - 24:18
    which buys a lot of benefits,
  • 24:18 - 24:21
    including hardware acceleration
    on more modern browsers.
  • 24:22 - 24:25
    Remember how we bound class
    name to form state earlier?
  • 24:26 - 24:28
    We said there was a thing
    there that says form
  • 24:28 - 24:31
    state is bound to the class
    name for this component.
  • 24:31 - 24:34
    Now we get these classes
    for free automatically,
  • 24:34 - 24:35
    Ember is going to stuff that in to our
  • 24:35 - 24:37
    component every time the state changes.
  • 24:37 - 24:40
    It pushes the state, it
    changes the name of the class.
  • 24:40 - 24:42
    I like to start by creating placeholders
  • 24:42 - 24:46
    for the various states
    in a given component,
  • 24:47 - 24:50
    and then put different
    behaviors under those states.
  • 24:50 - 24:52
    In this you can see it
    almost tells a story.
  • 24:52 - 24:54
    We start an initial state with a height of
  • 24:54 - 24:56
    zero px and an opacity of zero.
  • 25:03 - 25:06
    Then once it's in another
    state it actually expands.
  • 25:06 - 25:09
    Everything except initial it
    will transition to that state.
  • 25:10 - 25:11
    We transition open to visible
  • 25:11 - 25:15
    with a 200 millisecond delay and a ...
  • 25:16 - 25:19
    You know what, I'm just
    going to show it to you.
  • 25:19 - 25:21
    It's not great to try to
    explain how CSS animations work.
  • 25:22 - 25:23
    Let's do that.
  • 25:31 - 25:33
    I think I need to make
    that window smaller.
  • 25:36 - 25:38
    That's great. Thanks Obama.
  • 25:42 - 25:45
    We're going to submit and now it expands.
  • 25:45 - 25:48
    Here we're in a validation error state.
  • 25:51 - 25:53
    We have the gif preview.
  • 25:53 - 25:54
    We have zero characters
    because that smart preview is
  • 25:54 - 25:57
    telling us that we're not
    using up any characters.
  • 26:01 - 26:03
    And we'll post it.
  • 26:04 - 26:06
    Oh, I just got trolled by chrome caching.
  • 26:09 - 26:14
    This one is just great.
    Julie Andrews is so awesome.
  • 26:18 - 26:20
    I have many of these that
    I really love very much.
  • 26:22 - 26:24
    Instead of doing that all day maybe
  • 26:24 - 26:25
    we should go back to the talk.
  • 26:27 - 26:28
    What we're not doing is we're not
  • 26:28 - 26:30
    manipulating the DOM directly.
  • 26:30 - 26:32
    If we want our tests can
    actually relax about the DOM
  • 26:32 - 26:35
    a little bit, we don't need to
    necessarily test the framework.
  • 26:36 - 26:38
    What we can focus on is application logic.
  • 26:39 - 26:41
    We can still integration test if we want
  • 26:42 - 26:44
    but let's look back and
    see what we've done so far.
  • 26:45 - 26:49
    There's some old code right here.
  • 26:49 - 26:51
    Let's see if you can locate
    the business logic in here.
  • 26:53 - 26:54
    Right? You can't.
  • 26:54 - 26:56
    That's why I'm introducing a powerful
  • 26:56 - 26:59
    encryption algorithm called jQCS, 512-bit.
  • 27:00 - 27:01
    It scatters your business logic across
  • 27:01 - 27:03
    hundreds of lines of jQuery code.
  • 27:05 - 27:06
    You can stop worrying
    about whether hackers
  • 27:06 - 27:08
    are going to access your
    business logic in your
  • 27:08 - 27:11
    front end because even
    your programmers can't.
  • 27:11 - 27:12
    (laughter)
  • 27:12 - 27:14
    That's cloudgineering folks.
  • 27:15 - 27:16
    Also a trademark.
  • 27:17 - 27:19
    That turns out not to be
    such a super hot idea.
  • 27:21 - 27:23
    We've now refactored
    this into a place where
  • 27:23 - 27:25
    we've moved that encrypted
    logic and exposed
  • 27:25 - 27:28
    it via computed properties,
    states and models.
  • 27:28 - 27:30
    The business logic is
    actually front and center now.
  • 27:30 - 27:32
    We've got from this
    sack of hot garbage to a
  • 27:32 - 27:35
    tested and documented
    reliable implementation.
  • 27:35 - 27:38
    It's not perfect but now it
    begs to be extended and reused.
  • 27:40 - 27:42
    From here what happens
    next is really up to you.
  • 27:43 - 27:46
    From here, most of the rendering that's
  • 27:46 - 27:48
    happening on the page
    is being done by Ember.
  • 27:48 - 27:50
    If you want to replace it
    and get all the benefits of
  • 27:50 - 27:52
    having a router underneath
    your app, great, go nuts.
  • 27:52 - 27:56
    You can actually now take
    application handlebars and
  • 27:56 - 27:59
    have it render those to components
    for you, and you're maybe
  • 27:59 - 28:01
    a few hours from having a
    full single page application.
  • 28:01 - 28:04
    Or you can continue to
    sprinkle in more components
  • 28:04 - 28:06
    and let your Rails app do
    all the driving and let your
  • 28:06 - 28:08
    components do the more dynamic
    pieces of your application
  • 28:08 - 28:11
    for you with that pool of
    shared data underneath it.
  • 28:13 - 28:14
    Now my brain is tired.
  • 28:15 - 28:17
    Why did we do all this
    stuff, what even is my life.
  • 28:18 - 28:22
    We had one job to do, a job
    that we were just about to quit,
  • 28:24 - 28:27
    but right before you became
    millionaires in the IPO.
  • 28:27 - 28:28
    I found out a couple years ago I quit
  • 28:28 - 28:34
    a job that just recently IPO'd.
    I would be on some yacht.
  • 28:35 - 28:38
    But we didn't quit,
    because we love our users,
  • 28:38 - 28:41
    we love our coworkers, and
    we want to love our job.
  • 28:42 - 28:44
    Software development, it really is fun.
  • 28:44 - 28:47
    It can be frustrating but it
    shouldn't give you night sweats.
  • 28:48 - 28:50
    Let's try this one more time against
  • 28:50 - 28:52
    our new and improved code base.
  • 28:52 - 28:54
    Once we know the API
    it's a small test to just
  • 28:54 - 28:56
    verify that this thing does what we want.
  • 28:56 - 28:58
    We can add a little
    favorite or like feature.
  • 28:59 - 29:02
    We stub out the data, test that
    a favorite makes it favorite
  • 29:02 - 29:04
    and an unfavorite makes it unfavorite.
  • 29:04 - 29:06
    Build a little favorite
    model that talks to
  • 29:06 - 29:09
    the server and it has
    many relationship here.
  • 29:09 - 29:11
    You can see DS belongs to gifPost
  • 29:11 - 29:13
    and it has many on the other side.
  • 29:13 - 29:15
    And add some dynamic content
  • 29:15 - 29:17
    to the handlebars template.
  • 29:18 - 29:20
    Then we write a toggle action to create or
  • 29:20 - 29:23
    destroy the favorite and
    that's pretty much it.
  • 29:24 - 29:27
    If chrome caching will smile upon me
  • 29:27 - 29:30
    We'll demo that as well, I'm
    going to switch my branch.
  • 29:47 - 29:49
    Everybody knows this trick, right?
  • 29:51 - 29:53
    Also everybody knows the
    trick of typing rails s.
  • 29:56 - 29:59
    It's a little known thing,
    most people don't know.
  • 29:59 - 30:02
    It's how you load a Rails server up.
  • 30:02 - 30:04
    (laughter)
  • 30:07 - 30:09
    You can see my responsive
    design is so badass.
  • 30:09 - 30:12
    Woah, star just flies all around.
  • 30:13 - 30:16
    Now we can favorite this thing.
  • 30:16 - 30:19
    It's actually talking to the
    server on the back end but
  • 30:19 - 30:21
    it was so easy to do this
    that we actually were like,
  • 30:21 - 30:23
    Well, do you want me to filter
    these favorites for you?
  • 30:23 - 30:26
    I can do that and just
    show you my favorite ones.
  • 30:26 - 30:29
    This one, this is legendary.
  • 30:33 - 30:35
    (laughter)
  • 30:36 - 30:38
    (laughter)
  • 30:43 - 30:46
    (laughter)
  • 30:47 - 30:50
    Now we have favorites.
    If I unfavorite something
  • 30:50 - 30:52
    it will automatically pop out of the list.
  • 30:52 - 30:54
    I'm not managing any of
    this stuff. I just built a
  • 30:54 - 30:57
    little tiny filter that took
    like five minutes to do.
  • 30:57 - 31:00
    This stuff buys you so much and extending
  • 31:00 - 31:02
    this actually becomes very fun.
  • 31:07 - 31:10
    We've changed our relationship
    now to this code base,
  • 31:10 - 31:12
    where we actually like working on it.
  • 31:12 - 31:13
    We wake up in the morning
    instead of feeling
  • 31:13 - 31:16
    sick about what's going
    to be in our inbox we're
  • 31:16 - 31:18
    actually really excited
    about what we get to do next.
  • 31:20 - 31:23
    I just want to tell you as
    an addendum to this that my
  • 31:23 - 31:26
    personal story about, my
    first conference was about
  • 31:26 - 31:31
    four years ago and I think
    a lot of people, can I get a
  • 31:31 - 31:35
    show of hands of who's hear
    that's their first conference?
  • 31:37 - 31:39
    That's a really great portion of the room.
  • 31:39 - 31:41
    My first conference,
  • 31:41 - 31:43
    I went to a hack night the
    night after the conference.
  • 31:43 - 31:45
    It was put on by some really great people
  • 31:45 - 31:48
    but I walked in, I looked around
    and I didn't know anybody.
  • 31:49 - 31:52
    I listened to some people talk.
  • 31:52 - 31:54
    I was just learning to program.
  • 31:54 - 31:56
    I was listening to people
    talk and they were so smart
  • 31:56 - 31:58
    and they were people that
    were so well known in the
  • 31:58 - 32:01
    community and I was so
    nobody that I immediately
  • 32:01 - 32:03
    turned around, left, ran
    out of the room as fast
  • 32:03 - 32:06
    as I could, got in my car
    and cried and drove home.
  • 32:06 - 32:08
    Which is pretty awesome,
    I'm like super cool guy.
  • 32:08 - 32:10
    (laughter)
  • 32:10 - 32:13
    After that point the
    community picked me up and
  • 32:13 - 32:15
    dusted me off and said,
    "Get back in there kiddo."
  • 32:16 - 32:18
    Many people in that community
    that I didn't know in the
  • 32:18 - 32:20
    room at the time became
    some of my closest friends.
  • 32:21 - 32:24
    These people in this room, if
    you'll look around, are some
  • 32:24 - 32:27
    of your future closest friends
    and colleagues and mentors.
  • 32:28 - 32:31
    The community is the reason that
  • 32:31 - 32:33
    I get to do this for a living,
  • 32:33 - 32:35
    when before I was doing
    just horrifying things.
  • 32:35 - 32:37
    If you can imagine what
    it would be like to do
  • 32:37 - 32:39
    marketing for a multi-level
    marketing corporation.
  • 32:40 - 32:43
    Just imagine the existential
    hell and imagine programming.
  • 32:43 - 32:45
    We're pretty lucky to
    get to do this and I want
  • 32:45 - 32:47
    everybody to have as good
    a time writing software
  • 32:47 - 32:50
    as I get to have when I'm
    doing stuff like this.
  • 32:52 - 32:54
    The other thing I want
    to say, the last note
  • 32:54 - 32:58
    I want to say on community
    is we have a tendency
  • 32:58 - 32:59
    to do this tent pole
    thing where we raise some
  • 32:59 - 33:02
    people up and then gather
    around those people.
  • 33:02 - 33:04
    That's not really what
    a community is about,
  • 33:04 - 33:06
    a community is a mesh, it's
    not like hub and spoke.
  • 33:07 - 33:08
    Every person in here has something to
  • 33:08 - 33:10
    contribute and something amazing to do
  • 33:10 - 33:11
    and I can't wait to go
    to your talks later.
  • 33:11 - 33:14
    I'm told I'm pretty good at hugs ...
  • 33:14 - 33:18
    (applause)
  • 33:28 - 33:30
    I'm told I'm pretty good at hugs so come
  • 33:30 - 33:34
    say hi to me and thank
    you so much. (applause)
  • 33:39 - 33:43
    (energetic big band music)
Title:
RailsConf 2014 - Bring Fun Back to JS: Step-by-Step Refactoring Toward Ember by Brandon Hays
Description:

more » « less
Duration:
33:59

English subtitles

Revisions