Tuesday, March 15, 2016

POODR Notes - Chapter 2: Designing Classes with a Single Responsibility

These days, I've been thinking a lot about architecture and design, and I'm revisiting "Practical Object Oriented Design in Ruby." I've read POODR before, many times, but always in bits and pieces, often on the subway. I'd look for insight on a particular point (for example, dependency injection), without reading more about the bigger picture (say, the whole chapter about managing dependencies). So I decided to study smarter by reading whole chapters at a time, underlining and taking margin notes, then going back through to write out (using actual paper!!!) a summary of the main points and what I've learned.

Code needs to be TRUE

This is what I'll be sharing with you, starting with Chapter 2: Designing Classes with a Single Responsibility. This chapter is all about how to organize your code so that it does what you need it to do at the moment and is easy to change and reorganize as you get more information about what the app needs to do. A mnemonic for this idea is that code needs to be TRUE: Transparent about the cost of change, which should be Reasonable relative to the benefit that change would produce, Usable now and in the case of future changes, and Exemplary so that the style and patterns you lay out are worthy of replication as the app grows.

To be the most TRUE, classes should follow the Single Responsibility Principle (SRP), which means it should have one and only one responsibility.  When describing an app, the nouns you use represent classes, as long as they have both data and behavior. As an example, let's say we have a fully automated library that runs on Ruby. A patron comes to the circulation kiosk to identify a book they want to rent and the librarian robot retrieves it from its location in the shelves. Since this is a library, let's start with our Book class.

What is the responsibility of our Book class? As it is now, a book's responsibility is to manage its own properties, like author and title, and to manage its own storage. There are two things in that last sentence that stand out right away. First, if we describe a class's responsibility as "doing this thing" and "doing this other thing," as we just did, there is more than one responsibility. Additionally, a book "storing itself somewhere" doesn't really make sense; a book shouldn't be concerned with its own storage because that is the job of another object, which in our case is Shelf.

Is my class abiding by the SRP?

Now we have two classes: Shelf and Book, each of them abiding by the single responsibility principle. Our code is TRUE: our program does what we need it to do now, and is also organized in a way that will make it easy to change in the future. I'll leave you here with some questions that will help to assess whether a class has one and only one responsibility are:

  • What is the responsibility of this class? If the description includes the word "and" or "or" between two different types of concerns, isolate the different responsibilities in separate classes.
  • Should this domain object be its own class? The answer is yes if it has both data and behavior.
In the next post, we'll look at Chapter 3: Managing Dependencies and how that will help us to write TRUE code. In the comments, share your strategies for making sure your code follows the SRP and how you make it as TRUE as can be.

2 comments:

  1. Good stuff. Makes me want to read POODR again. There is so much richness here, and it's good to be reminded of it. Thanks!

    ReplyDelete
    Replies
    1. Thanks for your comment, Bethanne! Let's have a bookclub - my next book, which I think you would also be interested in, is Confident Ruby: http://www.confidentruby.com/. It's about "smaller" design patterns - how to write nice, concise, clean, and beautiful methods. Let me know if you want to be part of the book club!

      Delete