GetNoticed IT#4: Single Responsibility Principle-O-L-I-D

It’s time to continue about SOLID. Last time I started from the last letter in the abbreviation so this time we’re going to go to the opposite end and talk about S.

A class should have only one reason to change.

Sounds simple? But what a responsibility is? Let’s think about database access class which handles extraction of data from DB and saving data to DB. So it can be said that this class has two responsibilities, right? That is why the principle sounds as above, not “A class should have only one responsibility” as the name of the principle suggest. Martin himself explains that very well here:
I like to say that this principle means that there should be only one source of possible changes to a class. This is almost exactly as the formal definition but somehow when I said it this way the principle became clear for me.
The principle is also explained as below:

The single responsibility principle states that every module or class should have responsibility over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility. (Wikipedia)

So, to sum things up: the SRP inclines to create simple and cohesive classes that can only be changed by changing one requirement.

Now, let’s move on to an example. I don’t know how clear it is going to be but I can’t think of anything that is better and a the same time simple enough.
We have an Item class that is described by its name and its value. It also stores information how many items of a type we have available. An item can be sold, we can calculate its value after tax, shipping cost and our sell margin, and we can generate an invoice line for the transaction.

One glance at the code above and it’s obvious that the SRP rule is violated. First of all an item should not hold information of quantity available. It is store responsibility not item itself. Why? For instance, we we may want for certain items to implement auto-replenish feature. That’s definitely storage responsibility not the item. Or even better: we may want to calculate how many items of different type we have in store. How to do that if each item holds its available quantity?
Okay, so let’s remove storage responsibility to separate class. That class should be able to store different items and its available quantities. As we don’t want to create thigh coupling between storage and items we’ll start from creating abstractions of item class and storage class (which we’re going to built in a minute).

What Item can do has already been described above. Storage must make it possible to add and remove items, and check if an item is available. Let’s implement Storage class:

That’s done. So let’s move on to selling an item and calculating its value. Our case is simple and it might seem to be an overkill but I think that there should be separate classes to deal with selling (or maybe it’s better to say ‘processing order’) and calculating item’s value (after tax, with shipping costs added etc). The reason for this separation is in the principle. Why I want to separate selling an item: its requirements may change independently of calculating the value. For instance shop management decides to introduce extra discount. That changes only the way the value is calculated. It has nothing to do with the processing of sale. So, let’s begin with ValueCalculator.

ValueCalculator takes item, tax rate, margin rate and shipping cost in its constructor and makes available properties as follows: NetValue, TaxValue and GrossValue. That’s the responsibility.
Having the above done we can move on to separating GenerateInvoiceLine and creating new class InvoiceGenerator.  Its only responsibility is to return a line that can be pasted into an invoice:

Now it’s finally time for order processing (or SellItem method in initial Item class). It has to ask Storage if there is required quantity of ordered item available, and if affirmative it orders Storage to remove required quantity of item from stock and the asks InvoiceGenerator for a invoice string that is going to be handed to InvoicePrinter.

So, that would be it. Our example now follows the SRP. After all these changes our Item class now in fact has only one responsibility: to describe an item.

You can download final version of the code written above here. I hope that it is for anyone in anyway helpful. I also encourage to check the first post about SOLID here. It is about Dependency Inversion Principle. That’s it for today, thanks for reading and come later for more!