Skip to content

Python Code Example Following the Single Responsibility Principle (SRP)

This article explains the Single Responsibility Principle (SRP) and how to apply it in Python. By using this principle, you create classes that are simpler to maintain and test.

If you have any questions or comments, feel free to leave them at the bottom of the page. I will be delighted to respond.

1. What is the Single Responsibility Principle (SRP)?

The Single Responsibility Principle (SRP) is one of the SOLID principles. It involves creating separate classes if they change for different reasons. For example, if a class manages users with different roles, it is better to create a class for each role (admin and customer). This way, if the management rules change for admins, it will not impact the customers.

2. Why Use the Single Responsibility Principle (SRP)?

The SRP is a method of designing classes. It's a basic principle of object-oriented programming and Clean Code.

Here are the advantages of this principle for classes:

  • Easier maintenance. Changing one management rule does not cause side effects or regressions on another management rule.

  • Simpler method testing. By avoiding combining multiple management rules in a single class, you don't have to test all these rules each time.

  • Easier reuse of classes. When you need to employ a management rule in another class, it can be done without needing to duplicate code.

  • Simplified documentation of classes. Documenting a class that focuses on a single functionality is easier. The code becomes simpler to read and understand.

3. Python Code Example Not Following the Single Responsibility Principle (SRP)

Imagine you need to create a user management system. You need to manage updating a user's address and sending a welcome email. Here is an example of code that does not follow the SRP principle:

class UserManager:
    def __init__(self, user_data):
        self.user_data = user_data

    def change_user_address(self, new_address):
        self.user_data['address'] = new_address
        print(f"Address updated to {new_address}")
        self.send_email("Your address has been updated.")

    def send_email(self, email_content):
        # Code to send email
        print(f"Email sent to {self.user_data['email']}: {email_content}")

In this example, the change_user_address method changes the user's address and sends a confirmation email. If you want to send a welcome email, you can directly call the send_email method. This implies adding an email_type parameter to the send_email method to differentiate between welcome emails and confirmation emails. This makes the method more complex and harder to test.

class UserManager:
    def __init__(self, user_data):
        self.user_data = user_data

    def change_user_address(self, new_address):
        self.user_data['address'] = new_address
        # Sending a confirmation email
        self.send_email("Your address has been updated.", "address_change")

    def send_email(self, email_content, email_type=None):
        # Test the type of email
        if email_type == "address_change":
            # Building the email content
            email_content += f"\nNew Address: {self.user_data['address']}"
            # Additional logic for sending confirmation email
            # ... example: updating the user's nickname
        elif email_type == "welcome":
            # Building welcome email content
            # ... example: adding a confirmation link
        # Generic code for sending email
        print(f"Email sent to {self.user_data['email']}: {email_content}")

# Example usage
user_data = {'name': 'John Doe', 'email': 'john@example.com', 'address': '123 Main St'}
manager = UserManager(user_data)
manager.change_user_address('456 Elm St')
manager.send_email("Welcome to our website!", "welcome")

4. Python Code Example Following the Single Responsibility Principle (SRP)

Now, here is an example of code that adheres to the SRP. Still in the case of user management, we have created a UserDataManager class that manages user data and an EmailNotificationManager class that handles sending emails.

The UserDataManager Class (SRP)

class UserDataManager:
    """
    Class to manage user data.
    """
    def __init__(self, user_data):


 self.user_data = user_data

    def change_user_address(self, new_address):
        self.user_data['address'] = new_address
        print(f"Address updated to {new_address}")

The UserEmailManager Class (SRP)

class EmailNotificationManager:
    """
    Class for sending notifications to users
    via email.
    """
    def __init__(self, user_data):
        self.user_data = user_data

    def send_email(self, email_content):
        # Code to send email
        print(f"Email sent to {self.user_data['email']}: {email_content}")

Example of Updating User Address Using SRP Classes

To adhere to the management rules, we must: update the user's address and send a confirmation email.

Therefore, we will create an instance of UserDataManager and an instance of EmailNotificationManager. Then, we will call the change_user_address and send_email methods of each instance.

user_data = {'name': 'John Doe', 'email': 'john@example.com', 'address': '123 Main St'}
user_data_manager = UserDataManager(user_data)
email_manager = EmailNotificationManager(user_data['email'])

# Update address
user_data_manager.change_user_address('456 Elm St')

# Send notification
email_manager.send_email("Your address has been updated.")

Explanation of the SRP Principle in Python in This Example

  • UserDataManager: this class only manages user data. If the user data management rules change, you do not need to modify the EmailNotificationManager class.

  • EmailNotificationManager: this class only manages sending emails. If the email sending management rules change, you do not need to modify the UserDataManager class.

  • Decoupling of Classes: the UserDataManager and EmailNotificationManager classes are independent. You can reuse them easily. For example, if you do not want to notify an administrator about the update of their email address, you can use only the UserDataManager class.

  • Simpler Unit Testing: the classes are simpler to test. You can test the UserDataManager class without having to test the EmailNotificationManager class and vice versa.

The SRP principle has many advantages. Use it in your Python code to design applications that are simpler to maintain and test.