Question

SRP principal say:

a class or module should have one, and only one, reason to change

I have some Facade class as my service layer classes. e.g SaleService, that it provide some methods e.g SaveOrder(), CancelOrder(), CreateOrder(), GetAllOrders(), GetAllPlannedOrders(), ...

I only put them together because of their conceptual relations.
Does using such classes with this methods, that may have more than one reasons to change(), violate SRP? if yes, how can i handle this problem?

Was it helpful?

Solution

The facade pattern does not violate SRP per se. Often the facade pattern hides a complex interaction between underlying objects. In this case the 'single responsibility' for the facade is managing these interactions. As long as these interactions do not change, there should be no reason for your facade to change. If the interactions get really complex, it may be worthwhile to split the implementation of your facade in multiple objects again.

If I look at your examples, I do not get the impression that you are really trying to hide complexity, so it might be interesting to reconsider the use of the facade pattern here.

OTHER TIPS

I see the purpose of SRP being to identify cases where a class is doing too much, where a better design would be to have multiple classes. A classic example: a ReportProducer class, which does some work to assemble the data and some more work to format the output, probably there should be two classes: one for gathering, one for formatting. Amongst the benefits of that approach is flexibility: we can use a single gather class and multiple different formatter classes.

Now your example seems quite reasonable, you have a coherent class, all the methods are related, a user of the class knows that this is the class to go to for Orders. This looks like a single responsibility to me.

What are reasons for change? In the report example we have two completely different kinds of change: perhaps where the data comes from changes, or perhaps the desired format changes. In your example, one could argue that there are also multiple possible reasons: the "shape" of an Order could change, the desired interface could change (eg. add a queryCancelledOrders() method) the back-end that you are a Facade to might change. However I don't believe that these are indications that you violate SRP: they all relate to the task of presenting an interface for manipulating orders.

If we were to take "single reason for change" completely literally then I don't believe we could ever write any class. We always have interface and implementation, and usually also some dependent classes. Any one of those might change, so we always have at least two and probably three reasons for change.

Instead think of "what is this classes responsibility?" can you express it in a sentance without using words such as "AND". Bad: Collect data AND format report.

SRP is about changes in the implementation details of one responsibility that could cause a class to be modified even if that responsibility is only a small part of the class.

A Facade can't violate SRP in that precise, more serious way because it's only a superficial reflection - it won't change each time the internals of one of the operations change. It might change when the name of one of the operations changes, which does cause some brittleness but nothing terrible, or when an operation we want to reflect through the Facade is removed or added - but this has more to do with what the Facade chooses to expose, which is in fact its actual responsibility.

I most often use a Facade when I want a third-party component to be consumed through a single entry point by my code. An example of this is the Anti-Corruption Layer pattern. I usually think twice about creating Facades to my own code however, because you can easily be won over by its convenience and that can prevent you from really thinking about the dependencies between objects.

I'm not sure if SaleService is really a Facade in your example though, since Services often do more than just redirecting to some business behavior (they can do logging, authorization, transaction management, coordinate multiple calls to the business, etc.)

Yes, but the main purpose of facade pattern is to switch responsibility categorization dimension.

A facade wraps all objects in a subsystem into an single object, and offer multiple public methods as interface.

The objects in the subsystem are categorized according to Business Entity. But the facade's methods are categorized according to Use Case.

If a component which involves only one use case imports the facade, the facade's methods for other use cases are also visible to the component. That's to say, in the component's view, the facade has multiple responsibilities.

Therefore, facade pattern is often used along with Interface Segregation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top