# Chapter 2 - Designing Classes with a Single Responsibility

[Practical Object-Oriented Design in Ruby](https://www.poodr.com) is a book by [Sandi Metz](https://twitter.com/sandimetz)

# Chapter Summary

The goal of this chapter is to talk about ways to model your application using classes, such that **it does what it is supposed to do right now and is also easy to change**. There are a few techniques to achieve the above, but this chapter will be focusing on **designing classes with a single responsibility**. This post will briefly talk about the *reasons and benefits of having classes with a single responsibility*, followed by some tips and examples on *writing code that embraces change*.

## Classes with a single responsibility

The most obvious reason for having classes that have a single responsibility is that it makes the code easier to change. Not only that, having classes that **do only one thing** highly decreases the chance of your app breaking unexpectedly. Code is easy to change when

- Changes have no unexpected side effects
- Small changes in requirements require correspondingly small changes in code
- Existing code is easy to reuse
- The easiest way to make a change is to add code that in itself is easy to change

With the definition above, to write code that is easy to change, it should have the following qualities. Code should be

- **Transparent** &mdash; The consequences of change should be obvious in the code that is changing and in distant code relies upon it
- **Reasonable** &mdash; The cost of any change should be proportional to the benefits the change achieves
- **Usable** &mdash; Existing code should be usable in new and unexpected contexts
- **Exemplary** &mdash; The code itself should encourage those who change it to perpetuate these qualities

### Why Single Responsibility Matters

It matters because classes that have single responsibility are much easier to reuse and maintain. Imagine having classes that have more than one responsibility and all of them are so coupled that you cannot use just the behavior you need, which will lead to duplication of the code of interest. Duplicated code then leads to additional maintenance and increases bugs. Of course, one could argue that the non-single responsibility class could be reuse by structuring it in a way that you can access only the behavior you need. However, this just substitutes one problem for another. Because the class you are reusing is confused about what it does and contains several tangled-up responsibilities, it has many reasons to change. It may change for a reason that is not even related to your use of it, and each time it changes there are possibilities of breaking every class that depends on it.

### Case Study
Let's use this example of writing a Ruby application to **calculate gear ratios and the effect of the difference in wheels**. Here is the initial code which will be refactored later.

```ruby
class Gear
  attr_reader :chainring, :cog, :rim, :tire
  def initialize(chainring, cog, rim, tire)
    @chainring = chainring
    @cog = cog
    @rim = rim
    @tire = tire
  end

  def ratio
    chainring / cog.to_f
  end

  def gear_inches
    # tire goes around rim twice for diameter
    ratio * (rim + (tire * 2))
  end
end
```

### Determining If a Class Has a Single Responsibility

Does the `Gear` class has a single responsibility? One way to determine is by *interrogating* it. We can rephrase every one of its methods as a question. For example, *"Mr. Gear, what is your ratio?"* seems perfectly reasonable, while *"Mr. Gear, what are your gear_inches?"* is on shaky ground, and *"Mr. Gear, what is your tire (size)?"* is just downright ridiculous.

Another way is to describe it in one sentence. If the simplest description you can devise uses the word "and", the class likely has more than one responsibility. If it uses the word "or," then the class has more than one responsibility and they aren't even very related. If you describe the responsibility of the Gear class as *"Calculate the ratio between two toothed sprockets"?*, then the current code does too much. What about *"Calculate the effect that a gear has on a bicycle"?* Put this way, *gear_inches* is back on solid ground, but tire size is still quite shaky.

### Determining When To Make Design Decisions

Bear in mind that applications are never perfectly designed and there are usually two approaches to making them better. The *"improve it now"* versus *"improve it later"*. 

**Improve it later** &mdash; You might prefer this approach if the *future cost of doing nothing is the same as the current cost*. Taking the example above, we know that something is not right with the `Gear` class, but it is still `transparent` and `reasonable` because it does not have any dependencies. Conveniently, when new dependencies arrive, they will supply the exact information you need to make good design decisions.

**Improve it now** &mdash; From another perspective, defensible arguments like 

> The structure of every class is a message to future maintainers of the application. It reveals your design intentions. For better or for worse, the patterns you establish today will be replicated forever.

suggests that one should improve it now so that the *"lie"* about the intentions of the `Gear` class does not propagate. Using the example above, the `Gear` class is neither `usable` or `exemplary`. It has multiple responsibilities and so should not be reused.

There is no right approach, a good designer understands the tensions between "improve it now" versus "improve it later" and minimizes the costs by making **informed tradeoffs** between the needs of the present and the possibilities of the future.

## Writing Code That Embraces Change

With the use of a few techniques, the code is now refactored to:

```ruby
class Gear
  attr_reader :chainring, :cog, :wheel
  def initialize(chainring, cog, wheel)
    @chainring = chainring
    @cog = cog
    @wheel = wheel
  end

  def ratio
    chainring / cog.to_f
  end

  def gear_inches
    ratio * wheel.diameter
  end
end

class Wheel
  attr_reader :rim, :tire
  def initialize(rim, tire)
    @rim = rim
    @tire = tire
  end

  def diameter
    rim + (tire * 2)
  end
end

```

`Gear` class does look better now, it no longer knows about `tire and rim` but just accepting a `Wheel` object responding to the `diameter` method. This is still a dependency, but we will talk more about managing dependencies in the next chapter. Below are some of the techniques we have used in refactoring the example.

### 1. Depend on Behavior, Not Data
#### (a) Hide Instance Variables

In Ruby, data is often held in an instance variable, and by hiding the instance variable using the accessor method we have implemented the code in a way that only the `cog method` understands what `cog` means. If later `@cog` needs to be adjusted we will just need to modify the `cog` method itself. For example

```ruby
  def cog
    @cog * unanticipated_adjustment_factor
  end
```

However, dealing with data as if it's an object that understands messages introduces two new issues. The first issue involves visibility like wrapping the `@cog` instance variable either in a *public* or *private* method. This will be discussed in a different chapter. The second issue is that it is possible to wrap every instance variable in a method and to therefore treat any variable as if it's just another object. This results in the distinction between *data* and regular *object* begins to disappear. Despite that, the author recommends that most things are still better thought of as plain old objects. Send messages to access variables, even if you think of them as data.

#### (b) Hide Data Structures

If being attached to an instance variable is bad, depending on a complicated data structure is worse. However, if you can control the input, pass in a useful object, but if you are compelled to take a messy structure, hide the mess even from yourself. In the example below, assume that we are compelled to take in a messy structure, and we are trying to make it better by using the Ruby `Struct` class to wrap it. This style of code allows you to protect against changes in externally owned data structures and to make your code more readable and intention revealing.

```ruby
### BEFORE ###
class ObscuringReferences
	attr_reader :data
	def initialize(data)
		# data = [[622, 20], [622, 23]]
		@data = data
	end
	
	def diameters
		# 0 is rim, 1 is tire
		data.collect { |cell| cell[0] + cell[1] * 2 }
	end
end

### AFTER ###
class RevealingReferences
	attr_reader :wheels
	def initialize(data)
		@wheels = wheelify(data)
	end
	
	def diameters
		wheels.collect { |wheel| wheel.rim + (wheel.tire *2) }
	end
	
	Wheel = Struct.new(:rim, :tire)
	def wheelify(data)
		data.collect { |cell| Wheel.new(cell[0], cell[1]) }
	end
end
```


### 2. Enforce Single Responsibility Everywhere
#### (a) Extract Extra Responsibilities from Methods

Methods, like classes, should have a single responsibility with the similar reasons of making them easy to change and easy to reuse.

Let's look at what happened to the `gear_inches` after applying this technique

```ruby
### BEFORE ###
def gear_inches
  # tire goes around rim twice for diameter
  ratio * (rim + (tire * 2))
end

### AFTER ###
def gear_inches
  ratio * diameter
end

def diameter
  rim + (tire * 2)
end
```

This simple refactoring makes the underlying problem obvious. `Gear` is definitely responsible for calculating `gear_inches` but `Gear` **should not** be calculating wheel diameter. The cumulative effects of making sure methods have single responsibility are huge and here are some of the benefits:

- *Exposes previously hidden qualities*
- *Avoids the need for comments*
- *Encourages reuse*
- *Easy to move to another class*


#### (b) Isolate Extra Responsibilities in Classes

Now we know that `Gear` is doing too much. If you are certain that you need a `Wheel` class, go on and create one, which is what we have done in the *refactored version*. But let's assume that you are not sure whether there is a need for the `Wheel` class, and you want to refactor `Gear` so that it has a single responsibility. Ruby allows just that

```ruby
class Gear
  attr_reader :chainring, :cog, :wheel
  def initialize(chainring, cog, rim, tire)
    @chainring = chainring
    @cog = cog
    @wheel = Wheel.new(rim, tire)
  end

  def ratio
    chainring / cog.to_f
  end

  def gear_inches
    ratio * wheel.diameter
  end

  Wheel = Struct.new(:rim, tire) do
    def diameter
      rim + (tire * 2)
    end
  end
end
```

Of course, this isn't a long-term design goal. It does clean up `Gear` but defers the decision about Wheel. Keep in mind that any decision you make in advance of an explicit requirement is just a guess. Don't decide; preserve your ability to make a decision later.

## Conclusion

I have learned a lot from this chapter, new techniques that I am not aware of before this. Now, when I write code I will try my best to keep the classes and methods to serve only a single responsibility. And if I can't do that for any reason, I will try to isolate the dependencies so that it will make refactoring so much easier later.
