$30 off During Our Annual Pro Sale. View Details »

Fields & Fences

sarahmei
February 06, 2015

Fields & Fences

Everyone's building services these days, but for many teams it's turning out to be harder than expected. What can we learn from object-oriented design to make this transition easier?

From RubyConfAU in Melbourne, Australia.

sarahmei

February 06, 2015
Tweet

More Decks by sarahmei

Other Decks in Technology

Transcript

  1. F I E L D S & F E N C E S
    S A R A H M E I
    R U B Y C O N F A U 2 0 1 5
    https://www.flickr.com/photos/islespunkfan/2761157346/
    I’m really excited to be here in Melbourne for RubyConfAU, to show you a
    brand new talk. You’re the first ones to see it, and probably the only ones to
    ever see it in a 20-minute format.
    !
    20 minutes is a fascinating time interval for a talk, and by “fascinating” I
    mean really really difficult. In 20 minutes, I can really only say one thing.
    !
    It remains to be seen whether I picked the right one.

    View Slide

  2. https://www.flickr.com/photos/cmichel67/410891354/
    I’m the Chief Consultant at DevMynd Software. I’m based in San Francisco,
    where, you may have heard, the tech industry is killing the soul of the city.
    I’ve been there since 2001, but I’m part of the problem, because I see that
    and go, “FEWER! Fewer hipsters.”
    !
    I do a lot of pair programming & helping people figure out to refactor large
    codebases. I raised my hand un-ironically yesterday when Keith Pitty asked if
    anyone loved legacy code. I actually love working with codebases that have
    been around for a while. You can see all the scars, all the battles fought and
    lost over the years. It’s like a tapestry with hidden stories woven into it.

    View Slide

  3. https://www.flickr.com/photos/cmichel67/410891354/
    I have some side projects - they’re all non-profits. I’m one of the directors of
    RubyCentral, which means I help run RubyConf and RailsConf. I’m the
    program director for RailsConf this year.
    !
    In addition to Ruby Central, I’m also on the board of RailsBridge, which I
    founded back in 2009. We’re working to get more underrepresented folks
    into the Ruby community. I’m also on the board of Bridge Foundry, an
    organization we formed to bring our way of doing things to other
    communities. Now we’ve got ClojureBridge and MobileBridge going, and
    they’re both super cool.

    View Slide

  4. SERVICE-ORIENTED
    ARCHITECTURE
    OBJECT-ORIENTED
    DESIGN
    https://www.flickr.com/photos/foilman/3306277484/
    Despite the slides I’ve shown you so far, this is not a talk about farming. It’s a
    talk about service oriented architecture! Awesome, right? We’ve had so
    many of those already. But this is actually also a talk about object-oriented
    design.
    !
    Those two phrases are programmer jargon that can be pretty intimidating.
    !
    And many people have very different ideas about what these things are. So
    I’m going give you my definition for each, and then we can explore why I
    want to talk about them together. Let’s start with Service-Oriented
    Architecture.

    View Slide

  5. SOA
    MEANS
    BUSINESS
    https://www.flickr.com/photos/pasukaru76/5362499983/
    SOA is quite trendy at the moment, as I’m sure you can tell from all the talks
    that have touched on it.
    !
    I have a friend who’s raising VC money right now. That means she’s going
    around to VCs with a 5-minute pitch presentation. Most of these guys, to be
    perfectly honest, are assholes. She got a meeting with one of the big names
    down on Sandhill Road, and she was in the middle of the slide on
    monetization strategy when the guy interrupted her mid-sentence to ask if
    she planned to do SOA.
    !
    SOA is something non-programmers have on their radar. Sort of like “the
    cloud.”

    View Slide

  6. DevMynd
    An
    App
    That
    Does
    All
    The
    Things
    So let’s talk about what it actually is. Everyone starts with one Rails app in
    one repository. And at first that app does everything. It accesses the
    database and manages the tables, it routes requests, it render views, it talks
    to third-party services, it runs background jobs, maybe it accepts some API
    calls. And for the vast majority of Rails apps, this pattern is totally fine.
    !
    But then there’s the ones that are successful. SOA is always prompted by
    growth, either growth in traffic that requires one component in your app to
    be scaled differently from the others, or growth in team size that makes it
    awkward for all of you to work in the same codebase, and often these
    happen at the same time.

    View Slide

  7. DevMynd
    An
    App
    That
    Does
    All
    The
    Things
    FEWER
    One
    Thing
    One
    Thing
    So SOA, as it’s most commonly practiced, involves identifying separable
    responsibilities in your codebase, and then isolating them in their own
    codebases with their own deployment setups.
    !
    Now remember, this is all driven by growth. So when you start moving
    towards service oriented architecture, you’re separating responsibilities in
    your codebases, not because it’s some kind of moral imperative, or because
    your VCs tell you to, but because you’re actually feeling the pain that SOA is
    meant to address.
    !
    So that’s Service-Oriented Architecture. Let’s talk about OOD.

    View Slide

  8. OOD
    MEANS
    ACADEMIA
    https://www.flickr.com/photos/shutterhacks/4474421855/
    Object-oriented design, often abbreviated as OOD, is a much older idea
    than service-oriented architecture (at least among our generation of
    programmers). Therefore, it’s perceived by some people as rather academic,
    and not super useful in the everyday creation of software.
    !
    And there are some very academic definitions of OOD floating around out
    there. But at its core, it’s really something very simple. Object oriented
    design is how you decide where to put code when you need to write it.
    Does it go in a class you already have? Or a new class? A method you
    already have? Or a new method?
    !
    But people think about object-oriented design as academic, largely because
    they picture it happening like this:

    View Slide

  9. DevMynd
    User Contract Subcontract
    Provision Site
    def lorem
    puts “program”
    end
    def ipsum
    puts “computer”
    end
    def lorem
    puts “program”
    end
    def lorem
    puts “program”
    end
    def lorem
    puts “program”
    end
    def lorem
    puts “program”
    end
    def ipsum
    puts “computer”
    end
    Done!
    You have an app you want to build, so you decide up front what the names
    are of all the classes that you want, then you decide how they talk to each
    other, and then the rest is implementation detail, in which you’re always
    working towards this grand plan that you have in your head, and then
    someday, when the code looks like your design, you get a gold star and
    you’re done.
    !
    That is not what object-oriented design is. Because this never happens. But
    people think it should.
    !
    One of the reasons they think that is because of SOLID.

    View Slide

  10. DevMynd
    S
    O
    L
    I
    D
    ingle Responsibility Principle
    pen/Closed Principle
    iskov Substitution Principle
    nterface Segration Principle
    ependency Inversion Principle
    You may have heard this acronym before. It puts together 5 principles of
    object-oriented design. If you thought the phrase “object-oriented design”
    was jargon, just wait until you see these!
    !
    The principles are useful to know. And I recommend you look at the
    Wikipedia page for SOLID at some point. However, in day-to-day
    development, they have very limited utility. The SOLID principles describe
    what your code should look like when it’s done. They give you no
    guidance at all on how to get it there.
    !
    And so in the absence of such guidance, many people assume that object-
    oriented design means coming up with a design, a priori, that fits all these
    principles.

    View Slide

  11. DevMynd
    Contract
    User
    def lorem
    puts “program”
    end
    def ipsum
    puts “computer”
    end
    def lorem
    puts “program”
    end
    def foobar
    puts “baz”
    end
    But what object-oriented design actually looks like in the wild is quite
    different. At the beginning, you have some rough ideas of concepts you
    want to model, so you make a few classes, like Contract and User, and you fill
    in the functionality you need. At some point you notice Contract is starting
    to get a little large. It’s hard to work with. It’s doing too many things. It has
    many responsibilities.

    View Slide

  12. DevMynd
    ContractGroup
    Contract
    User
    def lorem
    puts “program”
    end
    def ipsum
    puts “computer”
    end
    def lorem
    puts “program”
    end
    def foobar
    puts “baz”
    end
    So you take a careful look at what’s inside of it and you separate one of the
    responsibilities into its own class. You don’t separate it because it’s some
    kind of moral imperative, or because Uncle Bob told you to, but because
    you’re actually feeling the pain that object-oriented design is supposed to
    address.

    View Slide

  13. https://www.flickr.com/photos/hapal/2482557110/
    The design of your application is the dozens of decisions you make every
    day, from small scale to large scale, about where code goes. Design is an
    emergent property of those decisions, not a pre-specified framework that
    makes all those decisions for you.
    !
    Design is bottom up. It is not and cannot be top down. But why not?

    View Slide

  14. DevMynd
    User Contract Subcontract
    Provision Site
    def lorem
    puts “program”
    end
    def ipsum
    puts “computer”
    end
    def lorem
    puts “program”
    end
    def lorem
    puts “program”
    end
    def lorem
    puts “program”
    end
    def lorem
    puts “program”
    end
    def ipsum
    puts “computer”
    end
    Why can’t we do this? Why can’t decide what we want at the beginning and
    then stick to it?
    !
    The answer is simply that we don’t know at the beginning what
    responsibilities our code will have.

    View Slide

  15. DevMynd
    https://www.flickr.com/photos/courtneyrian/5750960959/
    The only way we get that information is by writing the code, putting it
    somewhere, noticing when it seems out of place, and then moving it. Failing
    to do this re-assessment once code is written is how Rails apps get into
    trouble. That’s how you end up with a monolith.
    !
    I want you to think about the largest ActiveRecord model in the app you’re
    working on now.

    View Slide

  16. DevMynd
    User class with
    include UserStateMachine
    include UserScopes
    arrows that point at each sequentially
    1122
    650
    326
    40
    67
    39
    This is the Order model from Spree, an open-source e-commerce Rails app.
    I’m not picking on Spree - many apps have it much worse. Thinking about
    your model, how many lines of code does it have?
    !
    Order itself has 650, but then we have all these modules we include, so we
    have to count those. Total is just over 1100.
    !
    Most apps have at least one of equivalent size to Order. I’ve seen
    ActiveRecord models 5000 lines long. Usually the largest model in your
    codebase is also the one that changes the most often. It’s the one your
    application revolves around.

    View Slide

  17. DevMynd
    https://www.flickr.com/photos/beth19/5258618267/
    It’s the one that has to change with every single story. It’s the core of your
    application. If you’re an e-commerce company, perhaps it’s Order. If you’re a
    social network, perhaps it’s User. That’s the class that needs object-oriented
    design. The rest of your models, if the code fits on one screen, it doesn’t
    really matter.
    !
    There’s a scatterplot in Code Climate where one axis is complexity and the
    other axis is churn. The files that are in the top right of that plot are the ones
    that change frequently and are very complex.
    !
    Those are the classes you need object-oriented design for.

    View Slide

  18. DevMynd
    An
    App
    That
    Does
    All
    The
    Things
    FEWER
    One
    Thing
    One
    Thing
    ContractGroup
    Contract User
    So that’s Service-Oriented Architecture, and Object-Oriented Design. And
    when you’re looking at these boxes and lines diagrams, it all seem so clear,
    doesn’t it. You just find the boundaries of your responsibilities and make
    them formal. But as Rachel covered earlier, delineating the boundaries of a
    single responsibility is surprisingly difficult.
    !
    And OOD is the same way. You read a book about it, and it tells you single
    responsibility per class, and you’re ready to do the right thing, and then you
    sit down in front of your Rails app and you can’t figure out what to do.
    !
    These two problems are hard for exactly the same reason: delineating the
    boundaries of a single responsibility is surprisingly hard. And that’s true
    whether you’re trying to pull out a service or reduce the size of a class.

    View Slide

  19. DevMynd
    SOLID
    https://www.flickr.com/photos/jessiefish/3042962641/
    Because remember, SOLID shows us this amazing place where our code can
    be, but gives us no roadmap for getting there. So what is our roadmap? How
    do we know which things to separate?

    View Slide

  20. https://www.flickr.com/photos/louisa_catlover/4051628871/
    I call this the phone booth in the garden problem.
    !
    Maybe this once was the right place for a phone booth, but then the
    landscape around it changed. We get used to it being there. We don’t notice
    the incongruity anymore.
    !
    We do have some ways of helping ourselves see our phone booths. And
    these generally go under the name of “code smells.”

    View Slide

  21. https://www.flickr.com/photos/zachbonnell/14283693650/
    Code smells! The term comes from Kent Beck, and was made popular by
    Martin Fowler in his book on refactoring. They’re usually described as surface
    indicators in code that often indicate deeper problems within.
    !
    Some people call these icebergs, because only 10% of any iceberg is above
    the water.
    !
    I use code smells for a different and more specific purpose. A code smell is a
    sign that I’m mixing responsibilities. They are the clues that show me what
    objects I need to make. They point out the phone booth in the garden. Let’s
    look at a concrete example.

    View Slide

  22. DevMynd
    Duplicated code! It’s one of the code smells that we’re most attuned to, and
    the most used to dealing with.
    !
    Let’s say you have two ActiveRecord models with these two methods. These
    two methods are mostly doing the same thing, with minor implementation
    differences - the prefix is different, R vs. P, and order numbers include letters.
    !
    Fortunately, each code smell has an associated refactoring that fixes it. When
    you have duplicated logic with minor differences, that’s telling you there’s
    another class trying to get out. The refactoring that fixes this is called
    “extract class.”

    View Slide

  23. DevMynd
    So we make a new class that encapsulates the algorithm for generating a
    user-facing ID of some sort.

    View Slide

  24. DevMynd
    Then we replace the instances of the algorithm with a call to the new class
    we created.
    !
    We’ve talked a lot recently about DRY, “don’t repeat yourself,” which is an
    admonition to avoid repeated ideas in your code. DRY does not apply to
    repeated syntax. Repeated syntax can indicate a repeated idea, but often
    does not. It can be hard to tell the difference between the two situations.
    !
    I have a simple rule for this, though.

    View Slide

  25. DevMynd
    If you can’t DRY it out
    with a new class,
    leave it in.
    https://www.flickr.com/photos/aigle_dore/5952236932/
    If you can’t DRY out your code by creating a new class, then leave the
    duplication in.
    !
    Whether or not you can create (and name) a class that captures the idea is
    what tells you whether the idea is the same, or the syntax just happens to be
    repeated.

    View Slide

  26. DevMynd
    Duplicated Ideas
    Inappropriate Intimacy
    Data Clump
    Complex Conditional
    Code Smells
    Besides Duplicated Ideas, there are lots of other code smells that it’s worth
    your time to get familiar with and locate examples of in your own code. Most
    of them have fantastic names, too.

    View Slide

  27. DevMynd
    Shotgun Surgery
    Inappropriate Intimacy
    Data Clump
    Complex Conditional
    Code Smells
    For example, the official name of duplicated ideas is actually “shotgun
    surgery,” which describes the symptom of having to operate in many places
    at once on the codebase to make one logical change.
    !
    Inappropriate intimacy is when one class knows things about the internal
    workings of another class. The fix for that is to move logic around between
    classes.
    !
    Data clump is when you’re always passing two or more parameters together,
    and the refactoring that fixes that is to turn those two things into a class.
    !
    Complex conditional is one of the only ones that is exactly what it sounds
    like. Any time you have to use else if, ask yourself if you really need it.

    View Slide

  28. DevMynd
    Code Smells
    Shotgun Surgery
    Inappropriate Intimacy
    Data Clump
    Complex Conditional
    Service Smells
    Code smells are the guides we use to help us find the right boundaries. They
    are the missing roadmap that guides us towards SOLID code. They help us
    make decisions about where to put class boundaries.
    !
    Can they also help us make decisions about where to put service
    boundaries?
    !
    I think they can. But they take different forms in the SOA world.

    View Slide

  29. Shared
    Data
    https://www.flickr.com/photos/ryanr/142455033/
    The first is shared data. This could manifest itself in a number of ways. The
    most obvious is multiple services accessing the same database.
    !
    Another more subtle example of shared data is two services with separate
    databases that must synchronize some subset of their data regularly.
    !
    Each piece of data must have one and only one source of truth, and further,
    there must be one and only one way to access it.

    View Slide

  30. DevMynd
    Shotgun Surgery
    Inappropriate Intimacy Shared Data
    Data Clump
    Complex Conditional
    Shotgun Surgery
    Code Smells Service Smells
    Shared Data is the service equivalent of Inappropriate Intimacy. One service
    knows way too much about the interior of another service.

    View Slide

  31. Shared
    Data
    Shared
    Business
    Logic
    https://www.flickr.com/photos/duncanh1/4914379424/
    Second is shared business logic. If you’ve ever been tempted to make a
    gem that has your ActiveRecord models in it so they can be shared between
    services, your services are not independent enough.

    View Slide

  32. DevMynd
    Code Smells Service Smells
    Shotgun Surgery Shared Logic
    Inappropriate Intimacy Shared Data
    Data Clump
    Complex Conditional
    Shotgun Surgery
    Shared Logic is the service equivalent of Shotgun Surgery. It often goes
    along with Shared Data, but not always.

    View Slide

  33. Lockstep
    Deployment
    https://www.flickr.com/photos/alykat/5268223656/
    Next is lockstep deployment. Services that must always be deployed at the
    same time is a smell. Look for ways to decouple them.
    !
    Note that Lockstep Deploy can be caused by either shared data or shared
    business logic, but there are many other ways to achieve it as well. Just like
    code smells, service smells won’t be clear-cut, won’t exist in isolation, and
    may be hard to identify sometimes. But just having a name to put on them
    does a surprising amount of good.

    View Slide

  34. DevMynd
    Code Smells Service Smells
    Shotgun Surgery Shared Logic
    Inappropriate Intimacy Shared Data
    Data Clump
    Complex Conditional
    Shotgun Surgery Lockstep Deployment
    Lockstep Deployment is another service manifestation of Shotgun Surgery.

    View Slide

  35. Query
    Parameters
    https://www.flickr.com/photos/maduixaaaa/2567638237/
    Query parameters are another service smell. If you have to pass in more
    than one or two things for it to figure out what to do, your service is
    probably doing too much.
    !
    Can’t get around this one with nested routes — those are hidden query
    parameters.
    !

    View Slide

  36. DevMynd
    Code Smells Service Smells
    Shotgun Surgery Shared Logic
    Inappropriate Intimacy Shared Data
    Data Clump
    Complex Conditional Query Parameters
    Shotgun Surgery Lockstep Deployment
    Query Parameters is the service equivalent of a complex conditional. Having
    to pass in parameters to specify which of several paths to take usually
    produces a conditional in the underlying code, which is another way to
    identify this one.

    View Slide

  37. Parameter
    Clump
    https://www.flickr.com/photos/44803940@N04/4556141916/
    Lastly - parameter clump. If you’re always passing around two or more
    pieces of data together, there’s probably some behavior there that you
    should pull into its own service.

    View Slide

  38. DevMynd
    Code Smells Service Smells
    Shotgun Surgery Shared Logic
    Inappropriate Intimacy Shared Data
    Data Clump Parameter Clump
    Complex Conditional Query Parameters
    Shotgun Surgery Lockstep Deployment
    Parameter Clump is of course the service equivalent of a Data Clump.
    !
    Each of these smells indicates a problem with your service boundaries. And
    almost always, the problem is that individual units — whether classes, or
    services — are doing too much.

    View Slide

  39. DevMynd
    Code Smells Service Smells
    Shotgun Surgery Shared Logic
    Inappropriate Intimacy Shared Data
    Data Clump Parameter Clump
    Complex Conditional Query Parameters
    Shotgun Surgery Lockstep Deployment
    More
    Smaller
    Classes
    More
    Smaller
    Services
    The answer to code smells - make more and smaller classes. The answer to
    service smells - make more and smaller services.
    !
    Let me leave you with a few thoughts.

    View Slide

  40. • Class boundaries are easier to change
    than service boundaries
    • Get good at OOD first by breaking down
    complex, high-churn classes
    • Use service smells to guide drawing
    service boundaries
    https://www.flickr.com/photos/pixx0ne/2211981698/
    Service-oriented architecture is a new term for a very old skill. It’s all about
    identifying responsibilities. This is skill you can practice & get better at. And
    it’s much cheaper to learn that in your code than it is to learn it in your
    services. Because class boundaries are a hell of a lot easier to change than
    service boundaries.
    !
    Refactoring the main codebase — your “first” service — into smaller objects
    is what makes service-oriented architecture even possible. You can’t identify
    a responsibility to extract to a service if it’s scattered across multiple big
    objects. You must deal with your god objects before you can do services.
    !
    Once you get there, use the smells to guide your architecture toward single-
    responsibility services.

    View Slide

  41. Make
    Smaller
    Things
    https://www.flickr.com/photos/terykats/5650784759/
    !
    Make smaller things. This applies in services as much as it does with objects.

    View Slide

  42. DevMynd
    Sarah Mei
    [email protected]
    @sarahmei
    THANKS!
    That’s all I’ve got today. Thank you!

    View Slide