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?
相关问题
- how to define constructor for Python's new Nam
- Generic Generics in Managed C++
- Keeping track of variable instances
- How to Debug/Register a Permanent WMI Event Which
- Object.create() bug?
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.
No. It does not break SRP.
Assume that
Event though
ReportPrinter relies on DataAccess and ReportFormatter
, any change in contract ofIDataAccess or IReportFormatter
should be implemented byDataAccess and ReportFormatter
respectively.ReportPrinter
does not worry about the responsibility changes in those classes.You can have
Composition
or implement Mediator pattern to provide loose coupling between these three classes and get job done. Keepcoupling
part away fromresponsibility
.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.
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.