Search code examples
oopsingle-responsibility-principledesign-principlestell-dont-ask

Single Responsibility(SRP) vs Tell Don't Ask(TDA)?


I understand that many design principles conflict with each other in some cases . So, we have to weigh them and see which one is more beneficial. Till now I was aware of SRP principle and did my lot of designs solely based on that but internally I was feeling sometimes wrong while following this principle. Now I came to know about TDA , My feeling got more support with that :)

SRP :- Object should be worried about its own concern not anyone else

TDA :- Behavior (which is dependent only on its object state) should be kept inside the object itself

Example :- I have different Shapes like Rectangle, Square, Circle etc. Now i have to calculate area.

My design till now :- I was following SRP where I had AreaCalculatorService class which will ask state of shape and calculate the area. The reasoning behind this design was shape should not be worried about area calculation as it's not shape responsibility. But ideally i used to think area calc code should reside under each shape as if down the line if new shape comes up I have to modify AreaCalculatorService class(which violates the Open for extension and closed for modification principle(OECM)). But always gave preference to SRP. That seems to be wrong

Myth is broken(At least mine) :- With TDA, looks like my feeling was correct where I should not ask about the state of the object but tell the shape to calculate it's area. Though it will violate the SRP principle but will support OECM principle. As I said design principles conflict with each other some times, but I believe where behavior is completely dependent on its object state, behavior and state should be together.

Another Example :- say I have to calculate the salary of all departments of all Employees in an organization, then we should follow the SRP where SalaryCalculatorService will depend on department and employees.

It will ask the salary of each employee and then do summation on all salaries. So here I am asking for state of employee but still not violating TDA calcSalary is not dependent only on salary of each employee.

Let me know if my interpretation of both these principle is correct or not where I should follow TDA in first case but SRP in second ?


Solution

  • I think your TDA understanding is correct. The problem is with SRP, in my experience it is the SOLID principle most misunderstood. SRP says that one class should have only one reason to change. The "reason to change" part is often confused with "it should have only one responsibility" so "it must do only one thing". No, it's not like that.
    The "reason to change" depends completely from the context of the application where the class resides. Particularly it depends on the actors that interact with the software and that in the future could be able to ask for changes.
    The actors could be: the customer who pays for the software, the normal users and some super-users. The DBAs that will manage the database of the application or the IT department that handles the hardware where the application runs. Once you have enumerated all the actors around your software, in order to follow what SRP says, you have to write your class in a way that it has only one single responsibility, therefore only the requests from one actor could require some changes on your class.
    So, I think you should follow TDA putting data and behaviors that use those data inside the same object. In this way you can manage the relations among the objects telling them what to do instead of asking data, reducing coupling and reaching a better encapsulation.
    SRP as explained above will guide you to decide which behaviors put in one object rather than another one.