Low Level Design 105 | Single Responsibility Principle in SOLID | 2022 | System Design

sudoCODE
6 Mar 202210:28

Summary

TLDRThis video delves into the Single Responsibility Principle (SRP), a key concept in SOLID design principles. Contrary to common misconceptions, SRP doesn't imply a class should have only one method or reason to change. Instead, it emphasizes that a class should have one reason to change, driven by a single 'actor' or stakeholder. The video uses Uncle Bob's 'Clean Code' to illustrate this with examples like an 'Employee' class and a 'Bill' class, showing how changes in one part of a class can affect other functionalities if not properly separated. The solution? Decomposing classes to ensure each handles a single responsibility, thus adhering to SRP and making software easier to maintain and less prone to unintended side effects from changes.

Takeaways

  • πŸ“š The Single Responsibility Principle (SRP) suggests that a module or class should have one reason to change, meaning it should address the needs of one actor or stakeholder.
  • 🚫 Contrary to common misconceptions, SRP does not imply that a class should have only one public method; rather, it emphasizes that changes to the class should be driven by a single business requirement.
  • πŸ‘¨β€πŸ« Uncle Bob's book 'Clean Code' provides a detailed explanation of SRP, using examples to illustrate how a class can serve multiple methods corresponding to different stakeholders without violating the principle.
  • πŸ” The term 'actor' in SRP refers to different stakeholders or departments within a system that might require changes to the functionality provided by a class or module.
  • πŸ’‘ SRP is about ensuring that the impact of changes is isolated to the part of the system that is directly related to the stakeholder requesting the change, thereby minimizing unintended side effects.
  • πŸ› οΈ When a class is changed to meet the needs of one stakeholder but inadvertently affects the functionality used by another, it indicates a violation of SRP.
  • πŸ”„ To adhere to SRP, it may be necessary to refactor a class into multiple classes, each with a distinct responsibility, allowing for independent changes without cross-functional impacts.
  • πŸ“ˆ The example of an 'Employee' class with methods for calculating salary, hours, and saving data illustrates how a single class can serve multiple actors, but changes in one area can ripple through to others if not properly designed.
  • 🏒 The script uses a restaurant app scenario to further explain how SRP can be applied in practice, suggesting that classes like 'Bill', 'BillPrinter', and 'BillStore' should be separate to handle different responsibilities like calculating, printing, and storing bills.
  • πŸ€” SRP is subjective and requires judgment; it's about balancing the number of classes with the need to make the software easy to change and maintain without breaking existing functionality.

Q & A

  • What is the Single Responsibility Principle (SRP)?

    -The Single Responsibility Principle (SRP) is a software design principle that states a class or module should have only one reason to change, meaning it should only have one responsibility. It implies that the class should be designed in such a way that it encapsulates the functionality that caters to the needs of one particular stakeholder or group of stakeholders.

  • What does the term 'actor' mean in the context of SRP?

    -In the context of the Single Responsibility Principle, 'actor' refers to a stakeholder or a group of stakeholders who have a specific interest or requirement that could lead to changes in the software. It could be a department within a company, like the CFO, HR, or IT, each of which might require changes to the software for different reasons.

  • Why is it important to adhere to the Single Responsibility Principle?

    -Adhering to the Single Responsibility Principle is important because it helps in creating a modular and maintainable codebase. When a class has only one reason to change, it reduces the risk of unintended side effects when modifications are made. This principle contributes to a design where changes in one part of the system are less likely to affect other parts, thereby enhancing the overall stability and reliability of the software.

  • Can you provide an example from the script that illustrates the violation of SRP?

    -An example from the script that illustrates the violation of SRP is the 'Employee' class with methods like 'calculate salary', 'calculate hours', and 'save employee data'. These methods cater to different stakeholders (CFO, HR, and IT), and changes in one method due to the requirements of one stakeholder can inadvertently affect the functionality used by another stakeholder.

  • How can the violation of SRP be resolved according to the script?

    -The script suggests resolving the violation of SRP by decomposing the class into multiple classes, each with a single responsibility. For instance, creating separate classes like 'SalaryCalculator', 'HoursCalculator', and 'Store' for handling salary calculation, hours calculation, and data storage respectively, ensures that changes in one class do not impact the others.

  • What is theFacade Pattern mentioned in the script, and how does it relate to SRP?

    -TheFacade Pattern is a design pattern that provides a simplified interface to a complex subsystem. In the context of SRP, it can be used to create a unified interface for a set of classes that handle different responsibilities, thereby adhering to the principle by ensuring that changes in one part of the subsystem do not affect others.

  • How does the script explain the concept of a 'module' in relation to SRP?

    -In the script, a 'module' is explained as a collection of classes, functions, or a package that encapsulates a set of functionalities. It should be designed in such a way that it has only one reason to change, driven by the needs of one actor or stakeholder group.

  • What is the significance of decomposing a class into multiple classes as per SRP?

    -Decomposing a class into multiple classes as per SRP ensures that each class has a single responsibility and a single reason to change. This leads to a design where each class is focused on a specific business requirement or functionality, making the system easier to understand, maintain, and extend.

  • How does the script address the misconception that a class should have only one public method according to SRP?

    -The script clarifies that the misconception about SRP being that a class should have only one public method is incorrect. Instead, it emphasizes that as long as the changes in a class are driven by one primary stakeholder or group of stakeholders, the class can have multiple public methods.

  • What are some practical examples given in the script to explain SRP?

    -The script provides practical examples such as the 'Employee' class with multiple responsibilities and the 'Bill' class in a restaurant app that calculates the final amount, prints the bill, and saves the bill. These examples are used to illustrate how violating SRP can lead to issues and how decomposing these classes can resolve these issues.

Outlines

00:00

πŸ“š Understanding the Single Responsibility Principle

The paragraph introduces the concept of the Single Responsibility Principle (SRP), one of the SOLID principles of object-oriented design. It clarifies common misconceptions about SRP, emphasizing that a class should have only one reason to change, not necessarily one method. The speaker references Uncle Bob's 'Clean Code' and explains SRP using the example of an 'Employee' class with multiple methods serving different stakeholders (CFO, HR, and Engineering). The paragraph highlights how changes in one method can inadvertently affect others due to shared functionality, thus violating SRP. The solution proposed is to refactor the class into separate classes, each with a single responsibility, to ensure changes in one part of the system do not impact others.

05:02

πŸ” Deep Dive into SRP with Real-World Examples

This paragraph delves deeper into the Single Responsibility Principle with practical examples. It uses the scenario of a restaurant app with a 'MenuItem' class and a 'Bill' class to illustrate how a class can end up handling multiple responsibilities, such as calculating the bill, printing it, and saving it. The paragraph explains how changes in one aspect, like saving the bill to a database, can affect other functionalities if not properly separated. The speaker suggests decomposing the 'Bill' class into smaller, more focused classes like 'BillPrinter' and 'BillStore' to adhere to SRP. This approach ensures that changes in one area, such as database storage, do not disrupt other functionalities like bill calculation.

10:03

πŸŽ₯ Wrapping Up and Looking Forward to Open/Close Principle

In the concluding paragraph, the speaker summarizes the discussion on the Single Responsibility Principle and invites viewers to engage with any questions or doubts in the comments. The speaker also teases the next video, which will cover the Open/Close Principle, another of the SOLID principles. The paragraph serves as a bridge to upcoming content, encouraging viewers to continue their learning journey with the series.

Mindmap

Keywords

πŸ’‘Single Responsibility Principle

The Single Responsibility Principle (SRP) is a software design principle that states a class should have only one reason to change, meaning it should only have one job or responsibility. In the video, it is explained that SRP does not mean a class should have only one public method, but rather that the changes to a class should be driven by a single business requirement or stakeholder. The video uses the example of an 'Employee' class with methods like 'calculate salary', 'calculate hours', and 'save employee data', each potentially being changed by different stakeholders like CFO, HR, and IT, thus violating SRP.

πŸ’‘Module

In the context of the video, a module refers to a cohesive block of code that encapsulates a specific functionality or set of related functionalities. This could be a class, a package, or a set of functions. The video emphasizes that a module should have only one reason to change, which is driven by a single 'actor' or stakeholder. For instance, the 'Employee' class is a module that should ideally be split into smaller modules to adhere to SRP.

πŸ’‘Actor

An 'actor' in the video refers to a stakeholder or a user of the software system who can potentially cause a change in the system. Actors could be different departments within a company, such as the CFO, HR, or IT, each having distinct requirements that may lead to modifications in the software. The video explains that a module should be designed in such a way that changes are only influenced by one actor, aligning with the SRP.

πŸ’‘Facade Pattern

The Facade Pattern is a design pattern mentioned in the video as a potential solution to adhere to the Single Responsibility Principle. It provides a simplified interface to a more complex subsystem, hiding the complexities from the client. Although the video does not go into detail about the Facade Pattern, it suggests that it could be used to create a unified interface for the 'Employee' class, separating concerns and allowing changes to be made in isolation.

πŸ’‘Decomposition

Decomposition in the video refers to the process of breaking down a complex class into smaller, more manageable classes, each with a single responsibility. This is suggested as a solution to adhere to the SRP. For example, the 'Employee' class could be decomposed into 'SalaryCalculator', 'HoursCalculator', and 'Store' classes, each handling a specific responsibility and minimizing the impact of changes across different parts of the system.

πŸ’‘Stakeholder

A stakeholder in the video is defined as an individual or group with an interest or concern in the software system, such as a department within a company. The video explains that changes to a module should ideally come from one primary stakeholder or group, reflecting a single business requirement. This approach helps maintain the integrity of the software by ensuring that changes in one area do not inadvertently affect others.

πŸ’‘Business Requirement

A business requirement in the video is a need or condition that the software must meet to fulfill its purpose within an organization. The video emphasizes that a class or module should be designed to meet the needs of one specific business requirement, which is typically represented by one stakeholder group. This focus on a single business requirement helps maintain the SRP by ensuring that changes are localized and do not ripple through unrelated parts of the system.

πŸ’‘Design Patterns

Design Patterns are reusable solutions to common software design problems. The video briefly mentions the Facade Pattern as an example of how to apply design patterns to adhere to the Single Responsibility Principle. Design patterns provide a structured approach to solving recurring design issues and can help in creating more maintainable and flexible software architectures.

πŸ’‘Clean Code

Clean Code refers to the book by Robert C. Martin (Uncle Bob) that advocates for simple, well-structured, and readable code. The video uses examples from this book to explain the Single Responsibility Principle. The book is often cited as a foundational text for software developers looking to improve their coding practices and understand principles like SRP.

πŸ’‘Open-Close Principle

The Open-Close Principle is another SOLID principle mentioned at the end of the video. It states that software entities like classes, modules, and functions should be open for extension but closed for modification. This principle complements the SRP by encouraging the design of software components that can be easily extended without needing to alter existing code, thus reducing the risk of introducing bugs.

Highlights

Introduction to the Single Responsibility Principle (SRP) and its common misconceptions.

The true meaning of SRP as explained by Uncle Bob in his book 'Clean Code'.

SRP defined: A module should have one reason to change, influenced by one actor.

Explanation of the term 'actor' in the context of SRP with an example.

Example of an 'Employee' class violating SRP by serving multiple stakeholders.

Illustration of how changes in one part of a class can affect other functionalities due to shared methods.

The concept that a class should encapsulate functionalities that cater to one business functionality.

SRP does not mean a class should have only one public method.

The importance of decomposing classes to adhere to SRP for better software design.

Solution to SRP violation using the Facade pattern, although not detailed in the video.

A restaurant app example demonstrating SRP violation and its consequences.

How changes in one method can impact other methods due to shared responsibilities within a class.

The suggestion to separate concerns by creating distinct classes for different functionalities.

The idea that design is subjective and SRP should be applied based on business requirements and ease of change.

Encouragement for viewers to explore more about SRP and leave comments for further discussion.

A preview of the next video, which will cover the Open-Close Principle.

Transcripts

play00:00

hello and welcome to pseudocode in this

play00:02

video we are going to talk about one of

play00:04

the solid principles that starts with s

play00:06

which is single responsibility principle

play00:08

you might have heard definitions like

play00:10

single responsibility principle means

play00:12

one class should have only one and one

play00:14

reason to change one class should have

play00:16

only one public method or if your class

play00:18

description has and in the definition

play00:21

that means you're breaking the single

play00:22

responsibility principle and so on

play00:24

i'm sorry to break the sad news to you

play00:27

this is not what single responsibility

play00:28

principle means

play00:30

let's see actually what uncle bob meant

play00:33

when he

play00:35

coined the term single responsibility

play00:36

principles or how he has explained in

play00:38

his book so let's get started

play00:43

[Music]

play00:49

single responsibility principle from its

play00:51

name sounds very straightforward that

play00:54

one class or one module or one function

play00:56

should have only one responsibility and

play00:58

should have only one reason to change in

play01:00

fact even i also used to think like that

play01:04

but on further digging i found this book

play01:06

by uncle bob it is called clean code and

play01:08

i'm going to use the same example from

play01:10

from his book that explains the single

play01:13

responsibility principle but to start

play01:15

with the definition that principle

play01:17

actually states any module

play01:20

module means a set of functions or a set

play01:22

of functionality a class or a package or

play01:25

it can be a set of functions or it can

play01:26

be a source code itself

play01:29

should

play01:30

have a reason to change by only one

play01:32

actor or the whole functionality should

play01:35

be able to change by only one actor now

play01:38

what does this mean here we can

play01:40

understand what is the module but what

play01:42

is actor here now let's try to

play01:44

understand that using an example

play01:47

there is a class called employee and

play01:49

that class has three different methods

play01:51

calculate salary calculate hours and

play01:54

save employee data now that calculate

play01:56

salary method can be used by actually

play01:59

the financial officer of a company so

play02:02

let let's call that person cfo

play02:04

the hours calculate hours data can be

play02:07

required by the human resources

play02:08

department of the company and saving the

play02:11

employee data might be required from the

play02:13

technical or engineering department so

play02:15

now we can see that there are three

play02:17

different actors or three different

play02:19

stakeholders who actually need

play02:21

this functionality which is all written

play02:23

in one class

play02:24

now let's imagine a scenario where

play02:26

calculate salary and calculate hours are

play02:30

using some same underlying function or a

play02:32

private function in a class

play02:34

which is called get hours or get regular

play02:36

hours now if there is any kind of

play02:39

calculation change in the calculate

play02:40

salary method which is required by the

play02:42

cfo this calculation uh function will

play02:45

change in this class and

play02:47

it might require a change in the regular

play02:50

hours private function also so the

play02:51

person who is making this change uh he

play02:53

or she made a change here also now two

play02:55

methods public and private both have

play02:57

been changed now since calculate hours

play02:59

is also using this regular regular hours

play03:02

method internally this implementation

play03:04

breaks so cfo required a change to be

play03:07

made in certain functionality and the

play03:09

human resources department is getting

play03:11

some wrong data because somebody changed

play03:14

the underlying implementation of a

play03:16

private method which was used by both

play03:19

these public methods so what actually

play03:22

happened here what happened here was one

play03:24

class exposed two or three different

play03:27

methods two or three different public

play03:29

methods which were corresponding to

play03:31

different stakeholders of the software

play03:33

or different actors of the software one

play03:36

actor does not have to know anything

play03:38

about the other actor or they might not

play03:40

know anything about the other actor but

play03:41

still change requested from one of them

play03:43

has impacted the other one now this here

play03:46

is the breaking of single responsibility

play03:48

principle because this module is

play03:50

encapsulating the different functions of

play03:53

different functionality which cater to

play03:55

different actors of the system and this

play03:57

is what single responsibility principle

play03:59

means that the code that you are writing

play04:02

if that code request changes from only

play04:05

one actor or one stakeholder or even

play04:07

group of one stakeholder which fulfill

play04:09

one business requirement

play04:11

till that point it is fine so that means

play04:13

your class can have more than one public

play04:15

methods as long as the change in those

play04:17

public methods or change in those

play04:19

business logic is requested by one

play04:21

primary stakeholder or group of

play04:23

stakeholders till then it is fine but if

play04:26

one class has changes being requested

play04:28

from different stakeholders that means

play04:30

you have tried to put toward three

play04:32

different business functionalities

play04:33

together in one module and you have

play04:35

broken the single responsibility

play04:37

principle so this is what the example in

play04:39

the clean code entails now how do we

play04:42

solve this the best way to solve this

play04:44

like in the book it has been explained

play04:46

using facade pattern which i will not go

play04:48

into detail here because it is still out

play04:50

of scope i have not completed the design

play04:52

patterns yet but a better way to do this

play04:54

is to break the classes you make a

play04:58

salary calculator class you make our

play05:00

calculator class and you making a store

play05:02

class and all those classes can be

play05:04

called from different parts of the

play05:06

program and the calculation of

play05:09

salary does not need to know about or

play05:11

does not need to depend on any method

play05:13

that is used in calculate hours

play05:15

similarly saving the employee data to

play05:17

some database does not need to know

play05:18

about calculate salary or calculate

play05:20

hours at all this way while by

play05:23

separating the class or by

play05:25

decomposing one class into multiple

play05:27

classes we can actually other to single

play05:29

responsibility principle where the

play05:31

business function or the business

play05:33

requirement or the business logic sits

play05:34

in particular classes and the request

play05:37

for those requests for changing that

play05:39

business logic can only come from one

play05:41

particular stakeholder since all of this

play05:43

can be a lot to wrap your head around

play05:45

hence we will try to understand one more

play05:47

simpler example let's say there is a

play05:49

small restaurant app

play05:50

where we have a class called menu item

play05:53

now this class has the name of the item

play05:56

the

play05:57

if that item is available for take away

play05:58

or not and the amount of the item and

play06:00

tax and discount etcetera

play06:02

okay now there is another class called

play06:04

bill which can consist a list of these

play06:07

items the

play06:09

customer on whose name the bill has to

play06:11

be generated the timestamp and other

play06:12

properties

play06:14

if you think about it the responsibility

play06:15

of the bill class is to calculate the

play06:18

final amount so what does this function

play06:20

does it goes over all the items of the

play06:22

classes get their prices applies

play06:24

particular discount etc and returns the

play06:26

final amount

play06:28

now once the bill is generated the bill

play06:30

also has to be printed and the same bill

play06:32

file of the same build data also has to

play06:35

be saved to some location it can be a

play06:37

local file or it can be a database or

play06:39

anything so there is a save function it

play06:41

can seem perfectly fine to keep all

play06:44

these methods in the same build class

play06:46

where you are calculating the bill

play06:47

printing the bill and saving the bill

play06:49

now let's see what happens there is a

play06:51

team who want to change the database

play06:53

implementation of how the bill is being

play06:55

saved maybe they want to change the data

play06:57

store all together or maybe they want to

play06:59

modify the columns the way in which the

play07:01

bill is saved they would come and make

play07:03

changes to this class now if they have

play07:05

to make changes to this class they might

play07:07

end up adding some more properties in

play07:09

the class implementation itself and

play07:12

whoever is using the constructor of this

play07:14

bill class that functionality will break

play07:16

because they have changed the

play07:18

attributes and the basic properties of

play07:20

this class itself and why did they

play07:21

change it because they wanted to change

play07:23

how the bill is saved in database so

play07:26

again

play07:27

saving something to database this

play07:29

responsibility should have been catered

play07:30

by a different class if let's say this

play07:33

function save bill would have been in an

play07:36

another class called store class and

play07:38

that implementation would have been

play07:40

hidden from the bill class whoever was

play07:42

supposed to make that change they would

play07:43

have made this change in the in that

play07:46

store class itself without having to

play07:48

change the any columns of the bill

play07:51

similarly printing the bill that format

play07:54

require that format print format might

play07:56

require some changes and again if though

play07:58

that change is impacting the whole bill

play08:00

class it is again breaking the single

play08:02

responsibility principle because so many

play08:04

things are happening inside one class

play08:05

and change in one method can impact

play08:08

another method so it would be so the

play08:10

best way would be to again decompose

play08:12

these classes there can be a uh bill

play08:14

printer class there can be a bill store

play08:16

class and then there can be a bill class

play08:18

whose sole responsibility is to

play08:19

calculate the final amount of the bill

play08:21

and once the final amount of bill is

play08:23

calculated this bill object can be

play08:25

passed on to the bill printer class and

play08:28

this bill object can be passed on to the

play08:30

storable class now however the store

play08:32

class wants to store the data add or

play08:35

remove columns or keep some data from

play08:36

the bill or not keep some data from the

play08:38

bill they can do it without impacting

play08:40

the actual build class so this comprises

play08:43

of the whole single responsibility

play08:45

principle

play08:46

i hope that i have explained it in a

play08:49

clear manner and uh please note that

play08:51

again and again i am saying that it does

play08:54

not mean that one class should have only

play08:56

one public method that is not the

play08:58

meaning of single responsibility

play08:59

principle the meaning is

play09:01

module collection of classes functions

play09:04

should cater changes to a particular

play09:06

business stakeholder or a group of

play09:08

stakeholders through which the changes

play09:10

come into the picture if one class or

play09:13

one module has changes coming in from

play09:15

different business functions that means

play09:17

something is going wrong

play09:19

and as i always say design is something

play09:21

which is very subjective it is not

play09:23

objective there is no single right or

play09:25

wrong answer to single responsibility

play09:26

principle you might argue that this way

play09:29

if i keep on decomposing my classes i

play09:31

will end up with a lot of classes and

play09:33

where do i stop again it is up to your

play09:35

judgment and the business requirements

play09:37

that how do you organize your classes

play09:39

decompose your classes or put them

play09:41

together

play09:42

as long as it is fulfilling the business

play09:44

requirement and it is rendering the

play09:46

software easy to change as long as the

play09:49

software is easy to change and it is not

play09:51

breaking the existing functionality that

play09:53

itself is a good signal that your design

play09:55

is good i have linked the book from

play09:58

which i have picked this example i have

play10:00

linked other resources as well for you

play10:02

to read more about this concept if you

play10:04

have any doubt please please feel free

play10:06

to leave it in the comments and i will

play10:08

try to address it in the next video we

play10:10

will understand the next solid principle

play10:12

starting from o which is called open

play10:14

close principle till then take care see

play10:16

you in the next video

play10:18

[Music]

Rate This
β˜…
β˜…
β˜…
β˜…
β˜…

5.0 / 5 (0 votes)

Related Tags
Software DesignSingle ResponsibilityClean CodeUncle BobCode PrinciplesClass DecompositionSoftware ArchitectureSOLID PrinciplesProgramming Best PracticesDesign Patterns