The single responsibility principle states that every object should have a single responsibility and that responsibility should be entirely encapsulated by the class. You should think of a responsibility as axis of change. The greater the responsibilities of a class the higher the risk of introducing errors. This is because a class with multiple responsibilities couples together these responsibilities. The goal of this principle is to reduce coupling and increase cohesion where cohesion is how strongly related and focused the responsibilities of a class are and coupling is the degree to which each module relies on each other.
A Shopping System is a good example of this. Take the following class as an example.
Consider a system used in a retail business that has the requirements of being able to process an order either online or in the store. The class does this by calling the Checkout method which then determines the method that the order was received and the appropriate action to take. The problem with this class is that their are multiple responsibilities that are tied together, if any of these responsibilities change there is a high risk that it will affect the other responsibilities in this class. As an example if the method to process a credit card was modified to allow printing of the credit card receipt for a point of sale transaction then this would impact online orders as well.
The first step is to identify the responsibilities that are most likely to change and separate them from the class. There are 4 main areas
- Processing Credit Card Payments
- Processing Cash Payments
- Notification the the order was processed
- Reserving stock
A better approach would look like this
Here the responsibilities have been declared as interfaces and which are then utilised by the sub classes that represent all the different order types. Each order inherits the base class Order which as a list of items and a checkout method and only implements the responsibilities needed for that order type. For example in a Pos Cash order there is no need to notify or reserve items as the order and payment is process in the store. Now that the responsibilities have been separated we now limit the risk that a change to a responsibility will affect any of the other orders. Now if we were to add printing of a credit card receipts we could add a new responsibility like IEftposPrintingService in which only the PosCreditCardOder class would implement and we can safely say that no other order type would be affected.