In the context of the SRP, we define a responsibility to be a reason for change. If you can think of more than one motive for changing a class, that class has more than one responsibility. This is sometimes difficult to see. We are accustomed to thinking of responsibility in groups. For example, consider the Modem interface in Listing 8-1. Most of us will agree that this interface looks perfectly reasonable. The four functions it declares are certainly functions belonging to a modem. Listing 8-1. Modem.cs -- SRP violation
However, two responsibilities are being shown here. The first responsibility is connection management. The second is data communication. The dial and hangup functions manage the connection of the modem; the send and recv functions communicate data. Should these two responsibilities be separated? That depends on how the application is changing. If the application changes in ways that affect the signature of the connection functions, the design will smell of rigidity, because the classes that call send and read will have to be recompiled and redeployed more often than we like. In that case, the two responsibilities should be separated, as shown in Figure 8-3. This keeps the client applications from coupling the two responsibilities. Figure 8-3. Separated modem interface
If, on the other hand, the application is not changing in ways that cause the two responsibilities to change at different times, there is no need to separate them. Indeed, separating them would smell of needless complexity. There is a corrolary here. An axis of change is an axis of change only if the changes occur. It is not wise to apply SRPor any other principle, for that matterif there is no symptom. |