views:

370

answers:

3

In the following video, the author takes an existing class and assigns the Single Responsibility Principle to it. He takes a Print Class that has the job of Accessing Data, Formatting, and Printing the report. He breaks up each method to its own class, so he creates a DataAccess class to handle data access, he creates a ReportFormatter class to handle the formatting of the Report, and he creates a ReportPrinter class to handle the printing of the Report. The original Report class is then left with one method, Print() which calls the ReportPrinter's class method Print. DataAccess and ReportFormatter appear to have responsibility, but ReportPrinter relies on DataAcess and ReportFormatter, so doesn't this break the SRP or am I misunderstanding it?

+1  A: 

SRP doesn't address dependencies. Breaking the class up into the single-responsibility classes will facilitate breaking those dependencies later. SRP addresses one of the two principles oftem mentioned together: Cohesion and Coupling. SRP is about high cohesion, and the dependencies can be indicative of high coupling. Good designs have high cohesion and low coupling. Sometimes these two principles can be at odds.

Robert
I would argue that the single class with the whole implementation has higher coupling than the four separate classes. The single class is coupled to the implementation of the data access, formatting and printing, while the four separate classes are only coupled to the definitions of each class. Just because there are more classes does not mean there is higher coupling.
Stefan Moser
+1  A: 

Without watching the video, it sounds like a reasonable design. SRP is not broken, as methods dealing with data access do not appear in the ReportPrinter class, only the concept that "I can call something to get the data I want."

You could push it a bit further, and have a coordinator class responsible only for coordinating the activities of the data access class, the formatter class, and the printer class. You could also arrange the objects in different ways, like having the coordinator sends data to the formatter, which sends it to the printer, and the coordinator doesn't (directly) know about the printer.

Something has to know about coordinating the efforts of the narrowly-focused objects. That becomes their responsibility. It's okay to know about the idea or concept of what the other objects will do, so long as you don't know or care how they do it. Thinking of interfaces as "seams of responsibility" is a good start.

It can also be helpful if you think of objects as passing data to each other, rather than "doing" things. So the ReportFormatter returns (or forwards) a new object representing a formatted report, rather than (conceptually) performing objects on an existing report.

kyoryu
+1  A: 

The Single Responsibility Principle indicates that a given class should have a single responsibility (or 'reason to change'). It does not, in and of itself, indicate how that responsibility is to be satisfied. Doing so can, and often does, require the cooperation of multiple other classes as collaborators.

Brandon E Taylor