What is the use of single responsibility principle?
What is the use of single responsibility principle?
I am trying to understand the Single Responsibility principle but I have tough time in grasping the concept. I am reading the book "Design Patterns and Best Practices in Java by Lucian-Paul Torje; Adrian Ianculescu; Kamalmeet Singh ."
In this book I am reading Single responsibility principle chapter ,
where they have a car class as shown below:
They said Car has both Car logic and database operations. In future if we want to change database then we need to change database logic and might need to change also car logic. And vice versa...
The solution would be to create two classes as shown below:
My question is even if we create two classes , let’s consider we are adding a new property called ‘price’ to the class CAR [Or changing the property ‘model’ to ‘carModel’ ] then don’t you think we also need to update CarDAO class like changing the SQL or so on.
So What is the use of SRP here?
3 Answers
3
Great question.
First, keep in mind that this is a simplistic example in the book. It's up to the reader to expand on this a little and imagine more complex scenarios. In all of these scenarios, further imagine that you are not the only developer on the team; instead, you are working in a large team, and communication between developers often take the form of negotiating class interfaces i.e. APIs, public methods, public attributes, database schemas. In addition, you often will have to worry about rollbacks, backwards compatibility, and synchronizing releases and deploys.
Suppose, for example, that you want to swap out the database, say, from MySQL to PostgreSQL. With SRP, you will reimplement CarDAO
, change whatever dialect-specific SQL was used, and leave the Car
logic intact. However, you may have to make a small change, possibly in configuration, to tell Car to use the new PostgreSQL DAO. A reasonable DI framework would make this simple.
CarDAO
Car
Suppose, in another example, that you want to delegate CarDAO to another developer to integrate with memcached, so that reads, while eventually consistent, are fast. Again, this developer would not need to know anything about the business logic in Car
. Instead, they only need to operate behind the CRUD methods of CarDAO
, and possibly declare a few more methods in the CarDAO
API with different consistency guarantees.
Car
CarDAO
CarDAO
Suppose, in yet another example, your team hires a database engineer specializing in compliance law. In preparation for the upcoming IPO, the database engineer is tasked with keeping an audit log of all changes across all tables in the company's 35 databases. With SRP, our intrepid DBA would not have to worry about any of the business logic using any of our tables; instead, their mutation tracking magic can be deftly injected into DAOs all over, using decorators or other aspect programming techniques. (This could also be done of the other side of the SQL interface, by the way.)
Alright one last one - suppose now that a systems engineer is brought onto the team, and is tasked with sharding this data across multiple regions (data centers) in AWS. This engineer could take SRP even further and add a component whose only role is to tell us, for each ID, the home region of each entity. Each time we do a cross-region read, the new component bumps a counter; each week, an automated tool migrates data frequently read across regions into a new home region to reduce latency.
Now, let's take our imagination even further, and assume that business is booming - suddenly, you are working for a Fortune 500 company with multiple departments spanning multiple countries. Business Analysts from the Finance Department want to use your table to plot quarterly growth in auto sales in their post-IPO investor reports. Instead of giving them access to Car
(because the logic used for reporting might be different from the logic used to prepare data for rendering on a web UI), you could, potentially, create a read-only interface for CarDAO
with a short list of carefully curated public attributes that you now have to maintain across department boundaries. God forbid you have to rename one of these attributes: be prepared for a 3-month sunset plan and many many sad dashboards and late-night escalations. (And please don't give them direct access to the actual SQL table, because the implicit assumption will be that the entire table is the public interface.) Oops, my scars may be showing.
Car
CarDAO
A corollary is that, if you need to change the business logic in Car
(say, add a method that computes the lower sale price of each Tesla after an embarrassing recall), you wouldn't touch the CarDAO
, since if car.brand == 'Tesla; price = price * 0.6
has nothing to do with data access.
Car
CarDAO
if car.brand == 'Tesla; price = price * 0.6
Additional Reading: CQRS
Yes that is correct. A corollary is that, if you need to change the business logic, you wouldn't touch the DAO.
– James Lim
Sep 9 '18 at 18:42
Yeah got it , But what about model? If I do some changes to the model then I have to change DAO also right ?
– vicky
Sep 9 '18 at 18:43
If by
model
you meant Car.model
, then you can rename columns in CarDAO
without changing the interface of Car (and vice versa).– James Lim
Sep 9 '18 at 18:46
model
Car.model
CarDAO
Oh I see. In that case, some changes have to be done on both sides, whereas with SRP there is a chance that some changes only have to be done on one side. For example, you could add a
decade
attribute to Car
that is derived from Car.year
, without changes to CarDAO
.– James Lim
Sep 9 '18 at 18:52
decade
Car
Car.year
CarDAO
For adding new property you need to change both classes only if that property should be saved to database. If it is a property used in business logic then you do not need to change DAO. Also if you change your database from one vendor to another or from SQL to NoSQL you will have to make changes only in DAO class. And if you need to change some business logic then you need to change only Car
class.
Car
So to put it simple , they SRP helps us to REDUCE the impact on the changes . Am I right ?
– vicky
Sep 9 '18 at 18:41
Yes, to reduce impact, to make parallel development by several developers faster and easier (avoid merge conflicts if one developer works on
Car
class and another on CarDAO
class)– Ivan
Sep 9 '18 at 18:44
Car
CarDAO
Single responsibility principle as stated by Robert C. Martin means that
A class should have only one reason to change.
Keeping this principle in mind will generally lead to smaller and highly cohesive classes, which in turn means that less people need to work on these classes simultaneously, and the code becomes more robust.
In your example, keeping data access and business logic (price calculation) logic separate means that you are less likely to break the other when making changes.
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Thanks for your detailed explanation. So to make it simple , so I add property to Car class I need to make Changes in CarDAO also but the impact will be less compared to previous . Is my understanding correct?
– vicky
Sep 9 '18 at 18:39