< Return to Video

Ruby Conf 2013 - API design for gem authors (and users)

  • 0:17 - 0:18
    EMILY SOLFO: My name is Emily Solfo.
  • 0:18 - 0:22
    I work for MongoDB, where I co-maintain the
    Ruby driver to the database.
  • 0:22 - 0:27
    It's the Mongo in JSON gem, if you've used
    the Ruby driver at all.
  • 0:27 - 0:32
    And I'm gonna talk about gem API design for
    gem authors and users.
  • 0:32 - 0:35
    Even if you're not a gem author, this will
  • 0:35 - 0:37
    cover a bunch of concepts that are relevant
    to
  • 0:37 - 0:40
    software engineering in general as well.
  • 0:40 - 0:42
    So why am I talking about this? Well, I
  • 0:42 - 0:46
    do co-maintain these, this Ruby driver at
    MongoDB. But
  • 0:46 - 0:48
    I also realize that many of us have become
  • 0:48 - 0:52
    gem authors through one of two ways: one way
  • 0:52 - 0:55
    we could have become a gem author is by
  • 0:55 - 0:59
    working on a Rails application at our company
    and
  • 0:59 - 1:02
    realizing, over the course of time, that our
    application
  • 1:02 - 1:06
    has become unwieldy, really complex, trying
    to do too
  • 1:06 - 1:09
    many things, and we've decided as a team to
  • 1:09 - 1:12
    break up our application into multiple services
    and tie
  • 1:12 - 1:14
    everything together with a gem.
  • 1:14 - 1:17
    Put all of the business logic in one place,
  • 1:17 - 1:19
    centralize all of our data models, and maintain
    this
  • 1:19 - 1:23
    gem internally at our company along with our
    colleagues.
  • 1:23 - 1:24
    That's one way.
  • 1:24 - 1:27
    The other way is by adopting a gem and
  • 1:27 - 1:31
    becoming a gem maintainer, or by building
    a gem,
  • 1:31 - 1:34
    opensourcing it, and becoming a gem author
    or opensource
  • 1:34 - 1:35
    gem maintainer.
  • 1:35 - 1:39
    So the point of this, though, is that there
  • 1:39 - 1:42
    was a transition at some point. You are, were
  • 1:42 - 1:46
    a web-developer before, and then you transitioned
    into becoming
  • 1:46 - 1:48
    a gem maintainer, a gem author.
  • 1:48 - 1:52
    And before your code was serving people who
    were
  • 1:52 - 1:54
    using a browser and a mouse. So it was
  • 1:54 - 1:57
    good enough that your code worked. Didn't
    really matter
  • 1:57 - 1:59
    what you called your variables. If you wanted
    to
  • 1:59 - 2:01
    use curse words, that was fine as well. It
  • 2:01 - 2:04
    was sort of funny. But now it's not the
  • 2:04 - 2:08
    same thing. Your code, now, serves other developers.
    It
  • 2:08 - 2:12
    serves other people who are looking to your
    gem
  • 2:12 - 2:14
    to provide some kind of functionality in their
    own
  • 2:14 - 2:16
    applications.
  • 2:16 - 2:19
    And these other developers are your future
    self, your
  • 2:19 - 2:24
    future colleagues, your current colleagues,
    opensource users. Regardless of
  • 2:24 - 2:27
    whether you're gem author inside a company,
    and the
  • 2:27 - 2:29
    gem you're working on is proprietary, or it's
    an
  • 2:29 - 2:32
    opensource gem, the things you need to think
    about
  • 2:32 - 2:35
    are the same. And they're not quite the same
  • 2:35 - 2:37
    things you need to think about as a web
  • 2:37 - 2:37
    developer.
  • 2:37 - 2:40
    So my personal story is that, I was a
  • 2:40 - 2:43
    Rails developer about two years ago, and we
    had
  • 2:43 - 2:46
    this, this web application that was serving
    up pages
  • 2:46 - 2:50
    to customers, they were buying things on our
    site.
  • 2:50 - 2:54
    But this Rails application was also serving
    us internally.
  • 2:54 - 2:58
    It was helping our third party vendors print
    things
  • 2:58 - 3:00
    and move them around. It was helping us to
  • 3:00 - 3:04
    run analytics on user behavior. It was helping
    us
  • 3:04 - 3:08
    run analytics on financial data. It was helping
    us
  • 3:08 - 3:11
    manage inventory. It was doing all of these
    things,
  • 3:11 - 3:13
    all in one application.
  • 3:13 - 3:16
    And it was super complex and just really horrible
  • 3:16 - 3:19
    to maintain. So, as I said, like along with
  • 3:19 - 3:21
    a lot of you, I'm sure, we split it
  • 3:21 - 3:24
    up into two different applications, and we
    created a
  • 3:24 - 3:26
    gem that had all of the business logic, all
  • 3:26 - 3:28
    of the data models in one place. And then
  • 3:28 - 3:31
    we maintained it amongst ourselves and managed
    dependencies and
  • 3:31 - 3:33
    versioning and all of that.
  • 3:33 - 3:36
    And the other transition that I went through
    was
  • 3:36 - 3:38
    that as I moved on from being a Rails
  • 3:38 - 3:41
    developer to working at MongoDB where I now
    co-maintain
  • 3:41 - 3:45
    these, this Mongo in JSON gem, I realized
    that
  • 3:45 - 3:47
    it's not quite the same thing, in the same
  • 3:47 - 3:49
    way that it wasn't quite the same thing maintaining
  • 3:49 - 3:52
    this gem at the, at my past company.
  • 3:52 - 3:54
    I need to think about users. I need to
  • 3:54 - 3:58
    think about other developers, like myself,
    using my code.
  • 3:58 - 4:02
    This is a gem, a quote from someone commenting
  • 4:02 - 4:04
    on a gem, that a lot of people use.
  • 4:04 - 4:06
    It's really popular. I didn't want to put
    the
  • 4:06 - 4:08
    gem on the spot and say it sucks, but
  • 4:08 - 4:11
    the point here is that this gem is used
  • 4:11 - 4:13
    by, I'm sure, the majority of people in this
  • 4:13 - 4:17
    room, and someone said, I love the contribution
    to
  • 4:17 - 4:20
    opensource. But it's not very obvious what's
    going on
  • 4:20 - 4:22
    when I look at the code. It's an example
  • 4:22 - 4:27
    of poor OOP design, poor documentation. It's
    sort of
  • 4:27 - 4:28
    a black box. It seems like there's a lot
  • 4:28 - 4:31
    of magic. I don't really know what's going
    on.
  • 4:31 - 4:34
    But as I said, I appreciate the contribution
    to
  • 4:34 - 4:38
    opensource. So people will appreciate your
    contribution. But if
  • 4:38 - 4:39
    you want your gem to be used, if you
  • 4:39 - 4:42
    want people to contribute to your gem, if
    you
  • 4:42 - 4:44
    want it to be this living, breathing thing
    that,
  • 4:44 - 4:46
    that people like and use, you need to think
  • 4:46 - 4:49
    about something beyond just, does my code
    work, do
  • 4:49 - 4:51
    my tests pass.
  • 4:51 - 4:54
    So gem API design is UX design. Is user
  • 4:54 - 4:57
    experience design - it's about users. And
    that's the
  • 4:57 - 5:02
    fundamental difference between writing a web
    application and maintaining
  • 5:02 - 5:05
    a library that other people use.
  • 5:05 - 5:07
    So why is it important to think about things
  • 5:07 - 5:12
    as user experience tasks? Or why is user experience
  • 5:12 - 5:12
    important?
  • 5:12 - 5:15
    So there was something called a UX Fund experiment
  • 5:15 - 5:20
    that was run in 2006 to 2007 by a
  • 5:20 - 5:24
    design firm in Toronto. And what they did
    was
  • 5:24 - 5:26
    they decided, they made up a list of ten
  • 5:26 - 5:29
    companies that they deemed to have superior
    user experiences.
  • 5:29 - 5:33
    These are companies like Google, Apple, JetFlew
    - all
  • 5:33 - 5:35
    of the, the companies that you probably think
    of
  • 5:35 - 5:37
    when you think of a great user experience.
  • 5:37 - 5:40
    And what they did was, they wanted to prove
  • 5:40 - 5:43
    a theory that they had, that great user experience
  • 5:43 - 5:47
    is directly reflected in stock prices, or
    directly reflected
  • 5:47 - 5:48
    in revenue and profit.
  • 5:48 - 5:50
    So what they did was, was they invested fifty
  • 5:50 - 5:53
    thousand dollars in each one of these, or,
    not
  • 5:53 - 5:55
    each one, but, in all of these companies.
    And
  • 5:55 - 5:58
    watched over a year each one of those companies
  • 5:58 - 6:00
    stock price go up.
  • 6:00 - 6:03
    And they concluded that great user experience
    is directly
  • 6:03 - 6:06
    reflected in stock price. So they proved their
    theory.
  • 6:06 - 6:09
    Now, we as Rubyists don't have a stock market.
  • 6:09 - 6:11
    We're not talking about money. But we do have
  • 6:11 - 6:16
    the community and we do have RubyGems. We
    have
  • 6:16 - 6:18
    different libraries that we can choose from
    when we
  • 6:18 - 6:20
    want to do certain things. We have numbers
    and
  • 6:20 - 6:24
    metrics. We have people maintaining these
    projects. We have
  • 6:24 - 6:27
    a number of ways that we can determine whether
  • 6:27 - 6:29
    or not a gem is successful or not.
  • 6:29 - 6:32
    So one example is RSpec. RSpec became really
    popular
  • 6:32 - 6:36
    because it had a great UI. Another example
    is,
  • 6:36 - 6:41
    I can never say this, HTTParty. Was a, is
  • 6:41 - 6:43
    another example of a gem that was doing something
  • 6:43 - 6:46
    similar to what some other gems did, but it
  • 6:46 - 6:49
    sort of became popular because the UI, the
    user
  • 6:49 - 6:51
    experience was superior to some of the others.
  • 6:51 - 6:54
    So user experience is extremely important
    as you're building
  • 6:54 - 6:55
    a gem.
  • 6:55 - 7:01
    And even beyond that, at MongoDB, arguably,
    MongoDB became
  • 7:01 - 7:05
    really popular really quickly, because we
    really focused on
  • 7:05 - 7:08
    the, the developer experience. And it's known
    for this
  • 7:08 - 7:11
    great user experience. We still focus on this,
    even
  • 7:11 - 7:14
    as we grow.
  • 7:14 - 7:16
    I'm on a team called the Driver's Team. We're
  • 7:16 - 7:20
    about twenty-two people, and we support, officially,
    twelve different
  • 7:20 - 7:22
    languages. And on this Driver's Team, I'm
    on a
  • 7:22 - 7:25
    bigger team called the Developer Experience
    team that consists
  • 7:25 - 7:29
    of docs, tools, and some other things.
  • 7:29 - 7:32
    And it is our focus, on this team, to
  • 7:32 - 7:34
    make sure that no matter what product you're
    using
  • 7:34 - 7:37
    or what interface, entry point you have to
    using
  • 7:37 - 7:42
    MongoDB, it's consistent across each one of
    those products.
  • 7:42 - 7:46
    And, and we've found that, like, MongoDB,
    like, everybody
  • 7:46 - 7:50
    knows what MongoDB is. And it's been, it's
    become
  • 7:50 - 7:53
    so, like, popular just because we've really
    focused on
  • 7:53 - 7:55
    the community in this way.
  • 7:55 - 7:58
    Another good example of how we focus on developer
  • 7:58 - 8:02
    experience is the shell. So for those of you
  • 8:02 - 8:04
    who have used the MongoDB shell, what language
    do
  • 8:04 - 8:06
    you use in the shell?
  • 8:06 - 8:10
    JavaScript, right? So JavaScript is a great
    entry point,
  • 8:10 - 8:14
    or a great way to allow developers to interact
  • 8:14 - 8:17
    with the database, because many of us are
    familiar
  • 8:17 - 8:19
    with JavaScript. And so this is one way that
  • 8:19 - 8:21
    we are able to get so many users so
  • 8:21 - 8:22
    quickly.
  • 8:22 - 8:26
    So more specifically, gem API design is UX
    design.
  • 8:26 - 8:28
    So how is it UX design? Let's talk about
  • 8:28 - 8:30
    some UX design concepts. User experience concepts.
  • 8:30 - 8:34
    Well, first of all, obviously, you have users,
    right.
  • 8:34 - 8:35
    So what do you do with your users? You're
  • 8:35 - 8:38
    not coding in a vacuum. You have users who
  • 8:38 - 8:40
    are consuming your code. How do you think
    about
  • 8:40 - 8:41
    your users?
  • 8:41 - 8:44
    Well, one thing is that you should really
    know
  • 8:44 - 8:46
    your users. Who are these users? As I said,
  • 8:46 - 8:49
    they could be opensource users. They could
    be your
  • 8:49 - 8:52
    future colleagues, your future self, your
    current colleagues. Who
  • 8:52 - 8:54
    are these users and how are they going to
  • 8:54 - 8:55
    use their gem - your gem?
  • 8:55 - 8:59
    How do you want them to use your gem?
  • 8:59 - 9:01
    You need to listen in. So how do you
  • 9:01 - 9:03
    listen in? There's so many channels through
    which you
  • 9:03 - 9:06
    can find out how people are using the Ruby
  • 9:06 - 9:08
    language, and what projects people are building
    - what
  • 9:08 - 9:11
    needs they have and how your gem can fulfill
  • 9:11 - 9:12
    those needs.
  • 9:12 - 9:17
    Read blogs. Use Twitter. Talk to users. Give
    presentations.
  • 9:17 - 9:19
    I come to a lot of conferences. I do
  • 9:19 - 9:22
    really enjoy giving presentations. But I also
    really like
  • 9:22 - 9:26
    just listening to conversations. And watching
    other presentations, listening
  • 9:26 - 9:28
    to what you guys don't like, what you do
  • 9:28 - 9:31
    like. How are you using the language, what,
    what's
  • 9:31 - 9:33
    the future of Ruby and what do people see
  • 9:33 - 9:36
    themselves doing with the language in the
    future?
  • 9:36 - 9:40
    This is extremely important input, as you
    maintain a
  • 9:40 - 9:43
    gem. Get to know your users. They're people.
  • 9:43 - 9:46
    And, as you get to know your users and
  • 9:46 - 9:48
    you build this gem, you want to establish
    trust
  • 9:48 - 9:50
    with them. So what does that mean?
  • 9:50 - 9:53
    If they're relying on your gem in their application,
  • 9:53 - 9:56
    you want to make sure that changes you make
  • 9:56 - 9:58
    to the software they depend on is not going
  • 9:58 - 10:00
    to break their code. That seems sort of obvious,
  • 10:00 - 10:03
    right. But we have this set of principles
    called
  • 10:03 - 10:07
    semantic versioning that we all preach, and
    we say
  • 10:07 - 10:10
    that we stick by, but I can't emphasize enough
  • 10:10 - 10:11
    how important this is.
  • 10:11 - 10:14
    So we had an experience once where we were
  • 10:14 - 10:18
    exposing something, and we didn't mean to
    expose. And
  • 10:18 - 10:19
    someone had sort of started to use it. It
  • 10:19 - 10:21
    was supposed to be private but it wasn't marked
  • 10:21 - 10:24
    as private. And then we had changed it in
  • 10:24 - 10:26
    a patched version and it broke in their code.
  • 10:26 - 10:28
    And it didn't go over so well. We didn't
  • 10:28 - 10:32
    intentionally do that, but the user was disappointed
    in
  • 10:32 - 10:36
    the gem, disappointed in us, because the,
    we had
  • 10:36 - 10:38
    broken this contract and this trust we had
    with
  • 10:38 - 10:39
    the user.
  • 10:39 - 10:41
    Extremely important.
  • 10:41 - 10:43
    The other way that you can get to know
  • 10:43 - 10:45
    your users, and have this sort of open communication
  • 10:45 - 10:48
    with your users, is identifying star users,
    or super
  • 10:48 - 10:52
    users, and maintain an open communication
    channel with them.
  • 10:52 - 10:57
    So for example, a couple weeks ago, well,
    so,
  • 10:57 - 10:59
    at MongoDB, the Ruby team is building a new
  • 10:59 - 11:01
    driver. We call it Ruby 2 point 0. And
  • 11:01 - 11:03
    we're trying, so the driver is like pretty
    old.
  • 11:03 - 11:06
    It's a couple years old. And we want to
  • 11:06 - 11:08
    rebuild it and use an architecture that's
    more consistent
  • 11:08 - 11:11
    across some of the other drivers at MongoDB.
  • 11:11 - 11:15
    And we have some customers who are very active
  • 11:15 - 11:17
    and like to give us a lot of feedback,
  • 11:17 - 11:21
    either positive or negative. And so we were,
    this
  • 11:21 - 11:24
    one customer, a couple weeks ago, had asked
    for
  • 11:24 - 11:28
    a specific time mount on a socket. And we
  • 11:28 - 11:30
    didn't provide this specific timeout. And
    so we were
  • 11:30 - 11:32
    talking about this, we were trying to decide
    whether
  • 11:32 - 11:34
    or not this was something we should support.
    But
  • 11:34 - 11:38
    after this whole conversation was concluded,
    I said, actually,
  • 11:38 - 11:41
    you know what, like, in Ruby Driver 2 point
  • 11:41 - 11:43
    0, what do you want? What kind of timeouts
  • 11:43 - 11:44
    do you want to see in the driver?
  • 11:44 - 11:46
    And then we just had this discussion about
    what
  • 11:46 - 11:48
    he would want. So you don't have to pull
  • 11:48 - 11:52
    like twenty thousand people or, like, you
    know, hundreds
  • 11:52 - 11:55
    of users, but if you just ask a couple,
  • 11:55 - 11:58
    you'll find that even with three user feedback,
    or
  • 11:58 - 12:01
    like, five users even, you'll have a pretty
    good
  • 12:01 - 12:03
    idea of what users want.
  • 12:03 - 12:05
    So make sure you, like, really keep- maybe,
    like,
  • 12:05 - 12:08
    identify, like, three particular people who
    are willing to
  • 12:08 - 12:12
    test out your gem in a test environment, or
  • 12:12 - 12:15
    your RCs, and just give you feedback as you
  • 12:15 - 12:17
    develop and as you release.
  • 12:17 - 12:21
    Which I, I skipped this, but releases also.
    Like,
  • 12:21 - 12:23
    make sure you stick to that in your semantic
  • 12:23 - 12:26
    versioning. Like, if you're going to add features
    and
  • 12:26 - 12:28
    you, you've released an RC one, don't continue
    adding
  • 12:28 - 12:31
    features in RC two. Like, stick to that really
  • 12:31 - 12:33
    well as well. It doesn't just go for breaking
  • 12:33 - 12:34
    peoples' code.
  • 12:34 - 12:38
    OK, so that's users. So obviously user experience
    involves
  • 12:38 - 12:43
    users. Get to know your users. Identify star
    users.
  • 12:43 - 12:46
    The second thing is concepts. So we have a
  • 12:46 - 12:50
    number of user experience concepts that, I'm
    not a
  • 12:50 - 12:52
    user experience expert, but there are a couple
    of
  • 12:52 - 12:55
    them that do apply to gem API design and
  • 12:55 - 12:58
    development. So we're gonna focus on three
    of them
  • 12:58 - 13:02
    - consistency, simplicity, and mapping.
  • 13:02 - 13:06
    Consistency is what you might think of as
    maybe,
  • 13:06 - 13:09
    like, a symbol in your system or an interface
  • 13:09 - 13:13
    element that a user interacts with that has
    a
  • 13:13 - 13:16
    specific effect on the system. And every time
    you
  • 13:16 - 13:19
    show that symbol, or provide that thing, that
    interface
  • 13:19 - 13:21
    component, to a user, you want to make sure
  • 13:21 - 13:24
    it has a similar or parallel effect, if not
  • 13:24 - 13:26
    the same effect on the system.
  • 13:26 - 13:28
    So a great example of this is button colors.
  • 13:28 - 13:31
    So we all know that red buttons mean danger
  • 13:31 - 13:36
    or cancel. Blue buttons mean information.
    Greyed out buttons
  • 13:36 - 13:39
    mean something not important or defaults.
    And green buttons
  • 13:39 - 13:42
    mean success. And every time you see these
    buttons
  • 13:42 - 13:44
    everywhere, you probably don't even read them.
    You just
  • 13:44 - 13:47
    look at the color. And that's because these
    interfaces
  • 13:47 - 13:48
    are consistent.
  • 13:48 - 13:50
    We recognize these symbols and we know what's
    go-
  • 13:50 - 13:53
    what they mean.
  • 13:53 - 13:58
    Another interface component, or user experience
    concept, is simplicity.
  • 13:58 - 14:03
    Simplicity is not exposing implementation
    details or too much
  • 14:03 - 14:08
    information to a user. You, as the gem designer,
  • 14:08 - 14:10
    and the gem developer, know way more than
    the
  • 14:10 - 14:13
    user. And the user doesn't need to know everything
  • 14:13 - 14:16
    you know. You only want to expose the user
  • 14:16 - 14:18
    what concerns them and what concerns their
    code.
  • 14:18 - 14:22
    So this, this is, especially relevant at MongoDB,
    as
  • 14:22 - 14:25
    we developer the driver. There are so many
    little
  • 14:25 - 14:27
    things that we know about the server that
    the
  • 14:27 - 14:29
    user doesn't need to know about. The user-
    we
  • 14:29 - 14:31
    need to focus on the, the little things, the
  • 14:31 - 14:34
    little knobs that the user can actually play
    with,
  • 14:34 - 14:37
    and that would have an effect on their own
  • 14:37 - 14:39
    code or their own understanding what's going
    on.
  • 14:39 - 14:42
    That's, it's actually really difficult to
    divine- to design
  • 14:42 - 14:46
    something super simple to someone who only
    needs to
  • 14:46 - 14:50
    know a certain amount of what you know.
  • 14:50 - 14:53
    And mapping. So mapping is the, the last concept
  • 14:53 - 14:58
    that I'm going to show through user, user
    experience
  • 14:58 - 15:02
    design for gem APIs. This example, I think,
    is
  • 15:02 - 15:06
    really great. Mapping is where you have interface
    components
  • 15:06 - 15:09
    that have effects on the system, and it's
    obvious
  • 15:09 - 15:12
    what effect it has based on how you interact
  • 15:12 - 15:13
    with the interface.
  • 15:13 - 15:16
    And the state of the system is really obvious
  • 15:16 - 15:18
    to the user after the user makes them change.
  • 15:18 - 15:22
    So a great example here is a stove. So
  • 15:22 - 15:25
    there's both a bad example and a good example.
  • 15:25 - 15:28
    The top example shows a number of burners
    on
  • 15:28 - 15:30
    a stove and they're arranged in some fashion,
    and
  • 15:30 - 15:32
    then you have all these knobs that manipulate
    these
  • 15:32 - 15:35
    burners, but the knows are in a row. So
  • 15:35 - 15:38
    it's not obvious to a user which knob goes
  • 15:38 - 15:41
    to which burner. And then the stove on the
  • 15:41 - 15:46
    bottom shows a layout of burners and then
    knobs
  • 15:46 - 15:47
    that are in the same exact layout.
  • 15:47 - 15:50
    So there's a really good mapping here. This
    knob
  • 15:50 - 15:52
    has an effect on this burner, because I can
  • 15:52 - 15:55
    make an association between where it's placed
    in the
  • 15:55 - 15:59
    mini mapping and the greater mapping. And
    then it's
  • 15:59 - 16:01
    really obvious to me when a burner turns on
  • 16:01 - 16:03
    that this state has changed and what effect
    that
  • 16:03 - 16:05
    knob has had on the system.
  • 16:05 - 16:09
    OK. So consistency, simplicity, and mapping.
    How does this
  • 16:09 - 16:11
    relate to gem API design? What do you need
  • 16:11 - 16:15
    to consider as you maintain or develop a new
  • 16:15 - 16:16
    gem?
  • 16:16 - 16:19
    We're going to talk about three consistency
    considerations, four
  • 16:19 - 16:23
    simplicity suggestions, and five mapping mantras,
    and look at
  • 16:23 - 16:29
    examples using the MongoDB Ruby driver to
    see how,
  • 16:29 - 16:31
    over the course of the last year and a
  • 16:31 - 16:34
    half, we've changed some features and developed
    the API
  • 16:34 - 16:38
    to adhere to some of these user experience
    concepts.
  • 16:38 - 16:40
    Three consistency considerations.
  • 16:40 - 16:45
    Consider consistent naming. This might seem
    super obvious, but
  • 16:45 - 16:48
    as I said before, variables are really important.
    People
  • 16:48 - 16:50
    are going to look at your code and want
  • 16:50 - 16:52
    to understand just by looking at it what's
    going
  • 16:52 - 16:53
    on.
  • 16:53 - 16:58
    Use consistent variable names across classes.
    Use consistent module
  • 16:58 - 17:03
    names. Use consistent method names. Use consistent
    ops names,
  • 17:03 - 17:06
    like option names. If you have a class that's
  • 17:06 - 17:09
    called something, and then you create an instance
    of
  • 17:09 - 17:11
    it in some other class and refer to it,
  • 17:11 - 17:13
    refer to it by the same name, or refer
  • 17:13 - 17:15
    to it as some name that evokes what that
  • 17:15 - 17:19
    thing is. Don't, don't get too creative with
    your
  • 17:19 - 17:21
    variable names. You want your code to be as
  • 17:21 - 17:24
    clear as possible, and consistent.
  • 17:24 - 17:29
    Consider consistent style. So there are a
    number of
  • 17:29 - 17:32
    things - someone gave a talk this morning
    about
  • 17:32 - 17:34
    winters and ways that you can run your code
  • 17:34 - 17:39
    through some sanitization cross-use to figure
    out if your
  • 17:39 - 17:42
    code is consistent in style. We, on the Ruby
  • 17:42 - 17:43
    driver 2 point 0, have chosen to Rubucop.
    There
  • 17:43 - 17:46
    are a number of other ones out there.
  • 17:46 - 17:49
    This goes for spacing in hashes. This goes
    for
  • 17:49 - 17:53
    method length. This goes for how you're doing
    argument
  • 17:53 - 17:57
    chaining. There are a number of configurations
    you can
  • 17:57 - 18:00
    do with RubuCop. But the reason we do this
  • 18:00 - 18:02
    is so that amongst our team, which is fairly
  • 18:02 - 18:05
    small in number, but amongst our team we have
  • 18:05 - 18:08
    a consistent style, as well as when people
    want
  • 18:08 - 18:10
    to make a contribution to our gem, they have
  • 18:10 - 18:12
    the same style as us.
  • 18:12 - 18:13
    And we want to make sure that over the
  • 18:13 - 18:17
    course of time, this style stays in tact,
    and
  • 18:17 - 18:20
    consistent, so you don't have these, these
    sort of,
  • 18:20 - 18:23
    like, bits of your code that, like, really
    exude
  • 18:23 - 18:25
    one personality over another. You want to
    keep it
  • 18:25 - 18:29
    as consistent and smooth as possible across
    all elements
  • 18:29 - 18:30
    of your code base.
  • 18:30 - 18:36
    The third thing with consistency is consider
    consistent behavior.
  • 18:36 - 18:38
    I think a good example of this is how
  • 18:38 - 18:40
    you raise warnings and exceptions, or how
    you alert
  • 18:40 - 18:42
    the user about something. So there are a number
  • 18:42 - 18:45
    of behaviors that you can think about to keep
  • 18:45 - 18:47
    consistent, but in this case, I can think
    of
  • 18:47 - 18:50
    a particular example a couple weeks ago, where
    we
  • 18:50 - 18:54
    have, you can do a map produce in your
  • 18:54 - 18:56
    replica set in MongoDB. And you can choose
    a
  • 18:56 - 18:58
    particular node in that replica set to do
    that
  • 18:58 - 19:00
    map reduce on.
  • 19:00 - 19:02
    You can't do, under some conditions, you can't
    do
  • 19:02 - 19:04
    your map produce on the secondary, but if
    you
  • 19:04 - 19:07
    say to do it on the secondary, in the
  • 19:07 - 19:10
    past, we would just raise an exception, say
    hey,
  • 19:10 - 19:13
    you can't do it on a secondary, choose, a
  • 19:13 - 19:15
    - we call it re-preference - choose a re-preference
  • 19:15 - 19:16
    of primary.
  • 19:16 - 19:18
    And then we were doing something else, an
    aggregation
  • 19:18 - 19:20
    framework, which is similar to map reduce,
    and then
  • 19:20 - 19:23
    you can choose a secondary there. And it had
  • 19:23 - 19:25
    a similar problem to map reduce. And then
    we
  • 19:25 - 19:28
    realized, according to spec, that we needed
    to actually,
  • 19:28 - 19:32
    behind the scenes, reroute the query to the
    primary.
  • 19:32 - 19:32
    And then we were like, wait a minute, this
  • 19:32 - 19:35
    is not consistent style. We can't raise an
    exception
  • 19:35 - 19:38
    for one case, and then something very similar
    just
  • 19:38 - 19:40
    raises a warning, or do something sort of
    behind
  • 19:40 - 19:41
    the scenes that the user's not aware of and
  • 19:41 - 19:43
    may be surprised later on when they find this
  • 19:43 - 19:46
    job's running on a node they didn't expect.
  • 19:46 - 19:49
    But the point here is not that, whether or
  • 19:49 - 19:51
    not you're warning the user or raised an exception,
  • 19:51 - 19:53
    it's just that you need to be consistent with
  • 19:53 - 19:55
    the behavior of your gem and how the user
  • 19:55 - 19:57
    interacts with it.
  • 19:57 - 20:01
    So those are consistency considerations.
  • 20:01 - 20:04
    Simplicity suggestions. So as I said, simplicity,
    remember, it's
  • 20:04 - 20:08
    not giving the user over-exposing implementation
    details to the
  • 20:08 - 20:12
    user. It's giving the user access to certain
    interface
  • 20:12 - 20:14
    components that are relevant to the user and
    the
  • 20:14 - 20:15
    user's code.
  • 20:15 - 20:19
    So first - give classes a single responsibility.
    We
  • 20:19 - 20:22
    hear this all the time. I think it pretty
  • 20:22 - 20:24
    much speaks for itself, but to give you a
  • 20:24 - 20:27
    concrete example in Ruby driver 2 point 0,
    I
  • 20:27 - 20:30
    don't know about you but client, cluster,
    collection, cursor,
  • 20:30 - 20:33
    database, errors, node - it's super clear
    to me
  • 20:33 - 20:35
    what each one of those classes does, what
    their
  • 20:35 - 20:39
    functions are, and how they interact with
    each other.
  • 20:39 - 20:42
    You want to stick to this, cause when people
  • 20:42 - 20:43
    open up your gem, they start looking at the
  • 20:43 - 20:45
    source code, you want them to be able to
  • 20:45 - 20:47
    know where to go to lear- to look for
  • 20:47 - 20:50
    certain functions, and they want to know how
    things
  • 20:50 - 20:52
    sort of work together. And it gives them an
  • 20:52 - 20:53
    idea of the architecture as well.
  • 20:53 - 20:56
    It's, it's really clear, and there's a lot
    of
  • 20:56 - 21:00
    transparency, when you keep classes having
    a single responsibility.
  • 21:00 - 21:04
    Another example is, I was refactoring some
    code recently,
  • 21:04 - 21:06
    and, along the lines of read preferences,
    which I
  • 21:06 - 21:08
    mentioned before, which is where you choose
    a particular
  • 21:08 - 21:11
    node to do a certain operation in your replica
  • 21:11 - 21:14
    set, I realized that, actually, I was refactoring
    the
  • 21:14 - 21:17
    code having to do with the, the map reduce
  • 21:17 - 21:19
    problem, and I was looking for the code that
  • 21:19 - 21:21
    could determine if you could do something
    on a
  • 21:21 - 21:23
    secondary, and I found some code - we had
  • 21:23 - 21:26
    this re-preferences module where if, but I
    found some
  • 21:26 - 21:30
    relevant code in a utils module as well.
  • 21:30 - 21:33
    So, single responsibility doesn't just go
    for classes. It
  • 21:33 - 21:36
    goes for modules, also. People are going to
    look
  • 21:36 - 21:38
    for specific functions in specific modules,
    and you need
  • 21:38 - 21:41
    to make sure that that's centralized and clear
    as
  • 21:41 - 21:41
    possible.
  • 21:41 - 21:44
    This wasn't necessarily bad design, it was
    just a,
  • 21:44 - 21:47
    just a, an oversight when we were refactoring
    at
  • 21:47 - 21:50
    some point and extracting some code out into
    a
  • 21:50 - 21:52
    read-preferences module. So it made more sense
    to put
  • 21:52 - 21:55
    this code all in one place called read_preferences,
    because
  • 21:55 - 21:57
    as a user, when I look at the code
  • 21:57 - 21:59
    base, I will look at a read_preferences module
    for
  • 21:59 - 22:02
    all the logic having to do with read_preferences.
  • 22:02 - 22:07
    Second thing - hide implementation details.
    This goes along
  • 22:07 - 22:10
    the same lines. Don't expose all of your knowledge
  • 22:10 - 22:13
    to the user. The user doesn't need to know
  • 22:13 - 22:15
    all of the knowledge. Only give them access
    to
  • 22:15 - 22:19
    certain things that are relevant to them.
  • 22:19 - 22:23
    So use the protected keyword private. Only
    expose things
  • 22:23 - 22:25
    to your user that they should be interacting
    with.
  • 22:25 - 22:27
    I realize, though, that there is going to
    be
  • 22:27 - 22:31
    a public API within your gem itself, and sometimes
  • 22:31 - 22:35
    you may unintentionally expose something that
    the user could
  • 22:35 - 22:37
    use, but the user shouldn't be using.
  • 22:37 - 22:39
    And this is actually a case in which you
  • 22:39 - 22:42
    need to be really careful with your documentation,
    and
  • 22:42 - 22:45
    make sure you say never use this method as
  • 22:45 - 22:49
    directly to the user. And only allow your,
    and
  • 22:49 - 22:54
    emphasize that it's an internal public API.
  • 22:54 - 22:57
    Be frugal with helpers. You may feel like,
    in
  • 22:57 - 23:00
    the beginning, that an API is really great
    if
  • 23:00 - 23:03
    you abstract everything, and you provide all
    of these
  • 23:03 - 23:06
    different methods to the user that are, that
    are
  • 23:06 - 23:10
    wrapping all these underlying concepts. What
    you want to
  • 23:10 - 23:13
    do, instead, is really think about how the
    user
  • 23:13 - 23:15
    is going to be using your gem, and only
  • 23:15 - 23:17
    provide helpers for the things that they will
    be
  • 23:17 - 23:18
    doing.
  • 23:18 - 23:19
    So an example of this in the Ruby driver
  • 23:19 - 23:23
    is, we have lots of different types of indexes
  • 23:23 - 23:27
    in MongoDB. We have geospacial indexes, we
    have text
  • 23:27 - 23:31
    indexes, we have ascending, descending, unique,
    goes on.
  • 23:31 - 23:35
    Instead of providing a helper for each one
    of
  • 23:35 - 23:39
    these different types of indexes in MongoDB,
    we've chosen
  • 23:39 - 23:41
    to keep it simple and say, create_index, and
    then
  • 23:41 - 23:44
    we have a constant corresponding to the string
    that
  • 23:44 - 23:47
    determines which index is which type, and
    then you
  • 23:47 - 23:49
    can just use it as the user.
  • 23:49 - 23:51
    Why did we choose to do it this way,
  • 23:51 - 23:53
    and not provide a helper for each one?
  • 23:53 - 23:57
    Well, I don't think the number of indexes,
    or
  • 23:57 - 23:59
    the types of indexes we have, is going to
  • 23:59 - 24:02
    remain the same forever and ever. They are
    going
  • 24:02 - 24:05
    to be indexes added over the course of time.
  • 24:05 - 24:08
    We might need to update indexes for backwards
    compatibility.
  • 24:08 - 24:10
    We're just going to have the number of methods
  • 24:10 - 24:12
    growing and growing. If we change the name
    of
  • 24:12 - 24:15
    the, the, the string constant of one of the
  • 24:15 - 24:15
    indexes.
  • 24:15 - 24:18
    This is where something really simple, like
    create_index, and
  • 24:18 - 24:20
    then you just do something like that, that's
    simple
  • 24:20 - 24:22
    enough for a user. You don't need to over
  • 24:22 - 24:27
    abstract everything and provide helpers where
    it's not necessary.
  • 24:27 - 24:29
    And the other thing is, this is a great
  • 24:29 - 24:33
    exercise. Design your API first. Pretend you're
    the user.
  • 24:33 - 24:36
    Build a little app. And actually write some
    lines
  • 24:36 - 24:39
    where you're using the gem that you're building.
    And
  • 24:39 - 24:41
    then do the implementation later on.
  • 24:41 - 24:43
    So at MongoDB, we as at the Driver's Team,
  • 24:43 - 24:46
    as I said, we're twelve different languages,
    and we,
  • 24:46 - 24:49
    we talk amongst ourselves all the time, regardless
    of
  • 24:49 - 24:52
    whether it's Java or Scala or Python, Ruby,
    Perl,
  • 24:52 - 24:54
    or PHP, we couldn't be any different in terms
  • 24:54 - 24:58
    of what languages we use on a daily basis,
  • 24:58 - 25:01
    but we all talk amongst ourselves and try
    to
  • 25:01 - 25:04
    make sure that this user experience at MongoDB
    is
  • 25:04 - 25:08
    consistent and that the API between all these
    drivers
  • 25:08 - 25:09
    is as consistent as possible.
  • 25:09 - 25:12
    So we have this initiative to try to take
  • 25:12 - 25:15
    some of the, the commands that you can run
  • 25:15 - 25:18
    in MongoDB that are potentially really confusing
    or overly
  • 25:18 - 25:22
    complex and not super transparent to a user,
    and
  • 25:22 - 25:25
    try to build these helpers around them that,
    in
  • 25:25 - 25:27
    one, in reading, just even the name of this
  • 25:27 - 25:31
    helper, it is immediately apparent to the
    user what
  • 25:31 - 25:32
    that thing does.
  • 25:32 - 25:37
    So for example, we have a command called find_and_modify.
  • 25:37 - 25:39
    I only put three parameters here, or options
    here,
  • 25:39 - 25:44
    and there are actually seven, and so, for
    example,
  • 25:44 - 25:47
    new => true, what does that mean? That means
  • 25:47 - 25:49
    that when you, when you do a find_and_modify,
    it
  • 25:49 - 25:51
    will do a find and get a certain number
  • 25:51 - 25:54
    of results, choose one of those results to
    either
  • 25:54 - 25:57
    remove, manipulate, or do an upstart - there
    are
  • 25:57 - 25:58
    a bunch of things that you can do. New
  • 25:58 - 26:01
    => true means return the document after it
    has
  • 26:01 - 26:04
    been modified or created or removed.
  • 26:04 - 26:06
    You can do new => false, which obviously will
  • 26:06 - 26:10
    return the document before it has been modified,
    removed,
  • 26:10 - 26:13
    or upstarted.
  • 26:13 - 26:15
    And so in this case, like, as I said,
  • 26:15 - 26:17
    there are seven options you can pass to find_and_modify.
  • 26:17 - 26:19
    So it's not, it doesn't really make a lot
  • 26:19 - 26:22
    of sense to force the user to use this
  • 26:22 - 26:24
    command, and then go consult the documentation,
    maybe on
  • 26:24 - 26:27
    MongoDB's site where it lists out all the
    intricacies
  • 26:27 - 26:30
    of each one of these parameters. It's much
    easier
  • 26:30 - 26:33
    and much better experience for the user to
    provide
  • 26:33 - 26:34
    something like update_one_then_get.
  • 26:34 - 26:37
    It's, like, really simple, and it says just
    in
  • 26:37 - 26:41
    one reading what that does. So think about,
    like,
  • 26:41 - 26:44
    it's sort of this nice balance between, like,
    when
  • 26:44 - 26:46
    you want to expose implementation details
    or allow the
  • 26:46 - 26:50
    user to do things as, as hands-on or directly
  • 26:50 - 26:52
    as possible, and where you want to add helpers,
  • 26:52 - 26:55
    where there might be some, some convolution
    or some
  • 26:55 - 26:59
    complexity that's just not even worth exposing
    to the
  • 26:59 - 27:00
    user.
  • 27:00 - 27:03
    So those were simplicity suggestions.
  • 27:03 - 27:05
    Mapping mantras. So again, mapping is where
    you have
  • 27:05 - 27:10
    an interface component that is very obviously
    related, or
  • 27:10 - 27:13
    direct, has a direct effect on some element
    of
  • 27:13 - 27:15
    the system. And you want to make sure that
  • 27:15 - 27:17
    whenever there's a change in the system, the
    user
  • 27:17 - 27:21
    gets some feedback and knows what effect that
    interface
  • 27:21 - 27:23
    component has had on the system.
  • 27:23 - 27:26
    So first of all, monkey-patching is mean.
  • 27:26 - 27:29
    Monkey-patching is a bad idea. I don't think
    there's
  • 27:29 - 27:33
    ever a good case for monkey-patching. I don't
    want
  • 27:33 - 27:35
    to embarrass a past colleague, but I think
    this
  • 27:35 - 27:39
    example is too good not to share. We found,
  • 27:39 - 27:40
    in our code, at some point, I'm gonna breeze
  • 27:40 - 27:44
    past this really quickly, we found a method
    called
  • 27:44 - 27:47
    lock_with_hack, that was - that was really
    quick -
  • 27:47 - 27:51
    lock_with_hack that was aliased on lock in
    a mutex.
  • 27:51 - 27:52
    Not a good idea.
  • 27:52 - 27:55
    So use refinements instead. We've just support
    back to
  • 27:55 - 27:57
    1.8.7, so we can't actually use refinements.
    So it
  • 27:57 - 27:59
    might not, it might not be an option for
  • 27:59 - 28:03
    you. People sometimes say use inheritance,
    if you find
  • 28:03 - 28:05
    that you need to monkey-patch something, maybe
    you're design's
  • 28:05 - 28:08
    a little off and you need to re-evaluate your
  • 28:08 - 28:11
    design, there's no quick fix or, like, quick
    answer
  • 28:11 - 28:14
    to getting around monkey-patching but, in
    general, if you
  • 28:14 - 28:16
    can avoid it, avoid it like the plague.
  • 28:16 - 28:21
    Two. Side effects are surprising. That sort
    of speaks
  • 28:21 - 28:24
    for itself. But, to give you a concrete example,
  • 28:24 - 28:28
    if someone is passing in ops to a method
  • 28:28 - 28:30
    that they potentially could be using over
    and over
  • 28:30 - 28:36
    again, don't mutate their op. So, for example,
    here,
  • 28:36 - 28:38
    if I pass in ops to a map reduce,
  • 28:38 - 28:40
    it could, as going back to read_preferences,
    it could
  • 28:40 - 28:43
    say use a secondary node for this map_reduce,
    and
  • 28:43 - 28:46
    if you, if you extract or you delete one
  • 28:46 - 28:49
    key from that hash, the reference is going
    to
  • 28:49 - 28:51
    be used over and over again and future map_reduces
  • 28:51 - 28:55
    in their own code and potentially be su- have
  • 28:55 - 28:56
    surprising effects to the user.
  • 28:56 - 28:59
    So make sure you do something here, like,
    do
  • 28:59 - 29:01
    the opts that you're working with a local
    copy.
  • 29:01 - 29:04
    So avoid side-effects that, that's breaking
    the trust that
  • 29:04 - 29:07
    you have with your user.
  • 29:07 - 29:11
    Requiring method chaining is impolite. Why
    is it impolite?
  • 29:11 - 29:14
    Because you make your user's code look ugly.
    Make
  • 29:14 - 29:18
    sure that, this is, this is a train-wreck
    violating
  • 29:18 - 29:19
    the law of demand (?? - 00:29:19) or whatever
  • 29:19 - 29:22
    you want to call it. If you are, if
  • 29:22 - 29:25
    you are not giving your users access to the
  • 29:25 - 29:28
    right things, their code might end up looking
    super
  • 29:28 - 29:30
    ugly and you want to avoid this. You want
  • 29:30 - 29:33
    to make sure that the API you're providing
    to
  • 29:33 - 29:35
    the users allows them to work with your code
  • 29:35 - 29:39
    in the cleanest, most elegant way possible.
  • 29:39 - 29:45
    Information error messages are imperative.
    I know, I love
  • 29:45 - 29:48
    MongoDB, blah, blah, blah, but I think Mongoid
    is
  • 29:48 - 29:52
    one of the best examples of great error messages.
  • 29:52 - 29:54
    This is an error message, not a blog post.
  • 29:54 - 29:58
    So, user dot find, with a certain ID, you
  • 29:58 - 30:01
    get the, the like basic error. It says error:
  • 30:01 - 30:04
    document not find. Then you have problem:
    document not
  • 30:04 - 30:07
    found for class user with IDs 123. Summary:
    When
  • 30:07 - 30:10
    calling user dot find with ID blah, blah,
    blah
  • 30:10 - 30:11
    - so you have this nice summary, even, of
  • 30:11 - 30:12
    what happened.
  • 30:12 - 30:15
    And then, what's even better, it tells you
    resolution.
  • 30:15 - 30:17
    It tells you what to do. It gives you
  • 30:17 - 30:19
    two options of what you can do. This is
  • 30:19 - 30:20
    the best error message ever.
  • 30:20 - 30:23
    So think about your users, like what - they're
  • 30:23 - 30:25
    gonna be frustrated when they get an error.
    You
  • 30:25 - 30:27
    want to give them as many, as much information
  • 30:27 - 30:29
    as possible, so they can solve the problem
    on
  • 30:29 - 30:32
    their own. Because, otherwise you're going
    to get issues
  • 30:32 - 30:33
    logged against your gem that you're gonna
    have to
  • 30:33 - 30:35
    go through and write out an answer and tell
  • 30:35 - 30:36
    them what to do.
  • 30:36 - 30:39
    So save yourself the time. Save your users
    the
  • 30:39 - 30:41
    frustration and write nice error messages.
  • 30:41 - 30:46
    And the last thing is documentation. So I
    went
  • 30:46 - 30:50
    to a presentation recently, and someone said
    inline comments
  • 30:50 - 30:53
    are a code smell. I totally disagree. I think
  • 30:53 - 30:57
    inline comments are extremely important, in
    particular if you're
  • 30:57 - 31:01
    writing a gem against something like a database,
    for
  • 31:01 - 31:04
    example, that might have some obscure, obscurities,
    or like
  • 31:04 - 31:06
    some weird things about it that you need to
  • 31:06 - 31:09
    write some fancy code around, or some, something
    that
  • 31:09 - 31:12
    might not be totally obvious to a user looking
  • 31:12 - 31:13
    at the code.
  • 31:13 - 31:16
    If you find yourself writing lines of code
    that
  • 31:16 - 31:17
    seem sort of confusing to you, you have to
  • 31:17 - 31:19
    stop and think about it really hard before
    you
  • 31:19 - 31:22
    write it, write an inline comment for anybody
    looking
  • 31:22 - 31:24
    at their code. It might even be you in
  • 31:24 - 31:25
    a couple of weeks when you forget what you
  • 31:25 - 31:26
    did.
  • 31:26 - 31:30
    So, for example, the, the server, the MongoDB
    server,
  • 31:30 - 31:32
    a couple weeks ago decided to create this
    option
  • 31:32 - 31:37
    called digest_password. And what digest_password
    is, in the context
  • 31:37 - 31:41
    of authentication, is tells the server that
    you need
  • 31:41 - 31:43
    to digest the password because I haven't on
    my
  • 31:43 - 31:44
    end.
  • 31:44 - 31:46
    So the, the driver has to, we digest the
  • 31:46 - 31:51
    password driver-side, but then we set this,
    this field
  • 31:51 - 31:53
    saying digest_password false, because when
    it's sent to the
  • 31:53 - 31:55
    server, it's telling the server that you shouldn't
    digest
  • 31:55 - 31:58
    the password. But a user looking at this code
  • 31:58 - 32:03
    is gonna see, OK, digest_password, digest_password
    equals false. That
  • 32:03 - 32:05
    doesn't seem to make any sense at all.
  • 32:05 - 32:07
    So, my colleagues who did a code review, kindly
  • 32:07 - 32:08
    told me, why don't you just put an inline
  • 32:08 - 32:10
    comment here so that someone looking at it
    is
  • 32:10 - 32:12
    not like, why are you digesting the password
    and
  • 32:12 - 32:14
    then setting digest_password to false?
  • 32:14 - 32:17
    So inline comments are great. Not, you know,
    not
  • 32:17 - 32:22
    like paragraphs, like the Mongoid exception
    or the Mongoing
  • 32:22 - 32:25
    exception summary, but make sure that inline
    comments are
  • 32:25 - 32:28
    just little notes for yourself that are super
    clear.
  • 32:28 - 32:30
    Think about them actually as notes to yourself.
    Make
  • 32:30 - 32:32
    them super clear because other users will
    find them
  • 32:32 - 32:35
    really useful.
  • 32:35 - 32:37
    Documentation tools - we use Yard. It's really
    great.
  • 32:37 - 32:40
    I think the documentation looks great. It's
    really easy
  • 32:40 - 32:44
    to use. All the tags are wonderful. Readme
    -
  • 32:44 - 32:47
    Readmes should be short and sweet. They should
    not
  • 32:47 - 32:51
    be guides. They should not be tutorials. They
    should
  • 32:51 - 32:53
    be sort of like an abstract for your gem.
  • 32:53 - 32:56
    So someone who is looking to evaluate your
    gem,
  • 32:56 - 32:58
    just quickly decide if it fulfills a need
    that
  • 32:58 - 33:00
    they have, if it's something that they want
    to
  • 33:00 - 33:03
    use, if they like the API, make sure you
  • 33:03 - 33:05
    put these things in your, in your readme,
    because
  • 33:05 - 33:07
    this is what people are gonna look at quickly
  • 33:07 - 33:09
    when they want to decide whether or not to
  • 33:09 - 33:10
    use your gem.
  • 33:10 - 33:14
    So those were mapping mantras. We talked about
    consistency.
  • 33:14 - 33:17
    We talked about simplicity. And we talked
    about mapping.
  • 33:17 - 33:21
    These are user experience concepts that are
    super relevant
  • 33:21 - 33:24
    to gem API design as well as software design,
  • 33:24 - 33:27
    whether you're a gem author or user.
  • 33:27 - 33:30
    And if you're looking, you haven't authored
    a gem
  • 33:30 - 33:33
    or maintained, had the opportunity to maintain
    a gem,
  • 33:33 - 33:35
    and you just want to try it out, there's
  • 33:35 - 33:38
    a blog post by Daniel Doubrovkine, where he
    -
  • 33:38 - 33:41
    it's called Your First Ruby Gem. And it's
    really
  • 33:41 - 33:43
    excellent. He goes through sort of this checklist
    of
  • 33:43 - 33:45
    things that you have to do as you're building
  • 33:45 - 33:47
    a gem. Like check the name, create a readme,
  • 33:47 - 33:51
    add a license, a gem file. It's really useful
  • 33:51 - 33:53
    for if you just want to even try it
  • 33:53 - 33:55
    out personally on your own, you know, on your
  • 33:55 - 33:58
    own time, and not even share it with anybody.
  • 33:58 - 34:02
    It's a great resource for getting started.
    So think
  • 34:02 - 34:04
    like a UX designer. It's not just about writing
  • 34:04 - 34:07
    code in a vaccuum. And I want to end
  • 34:07 - 34:11
    on a quote from Golden Gate Ruby Conference.
    James
  • 34:11 - 34:15
    Edward Gray the second gave a phenomenal presentation
    about
  • 34:15 - 34:17
    what it's like being a programmer, and his
    own
  • 34:17 - 34:19
    personal experience being a programmer.
  • 34:19 - 34:23
    And he said, Programming is easy. Anybody
    can program.
  • 34:23 - 34:25
    But to be a programmer, that's what gets you
  • 34:25 - 34:28
    to the next level. So get social. Get to
  • 34:28 - 34:30
    know your users and talk to me about the
  • 34:30 - 34:31
    Ruby driver.
Title:
Ruby Conf 2013 - API design for gem authors (and users)
Description:

more » « less
Duration:
35:03

English subtitles

Revisions