2 min read

Single Responsibility Principle

The Single Responsibility Principle (SRP) is a principle in object-oriented programming that suggests that a class should have only one reason to change. This means that a class should have a single responsibility or purpose, and should not be responsible for multiple unrelated tasks.

By following the SRP,

1. classes become more focused, smaller, and easier to understand, which in turn makes them more maintainable and less prone to introducing bugs.

2. we can reduce merge conflicts when different teams are working on the same file, conflicts can arise if the file has multiple responsibilities. However, if each class has a single responsibility, conflicts are less likely to occur, and if they do, they are easier to resolve.

A practical way to assess whether a class adheres to the SRP is to write down the purpose of the module or class. If the description requires the use of AND or OR to describe the responsibilities of the class, it may be an indication that the class is doing more than one thing and could potentially benefit from being refactored into smaller, more focused classes.

In summary, the Single Responsibility Principle promotes the practice of having classes with a single responsibility or reason to change, leading to smaller, more focused classes that are easier to understand and maintain.

Example:

class Order
  def initialize(items)
    @items = items
  end

  def calculate_total
    # Code to calculate the total cost of the items in the order
    total = 0
    @items.each do |item|
      total += item.price
    end
    puts "Calculating total cost of items: #{total}"
    total
  end

  def generate_invoice
    # Code to generate an invoice for the order
    puts "Generating invoice for the order"
    # Code to generate invoice
  end

  def send_confirmation_email
    # Code to send confirmation email to the customer
    puts "Sending confirmation email to the customer"
    # Code to send email
  end
end

In this example, we have an Order class that represents an order in an e-commerce system. It has three methods: calculate_total, generate_invoice, and send_confirmation_email. However, these methods are responsible for multiple tasks, including calculating the total cost of items, generating an invoice, and sending a confirmation email. This violates the Single Responsibility Principle, as the Order class has multiple reasons to change - one for calculating total, one for invoice generation, and one for email sending.

To adhere to the Single Responsibility Principle, we can refactor the Order class into separate classes, each with its own single responsibility:

class Order
  def initialize(items)
    @items = items
  end

  def calculate_total
    # Code to calculate the total cost of the items in the order
    total = 0
    @items.each do |item|
      total += item.price
    end
    puts "Calculating total cost of items: #{total}"
    total
  end
end

class InvoiceGenerator
  def generate_invoice(order)
    # Code to generate an invoice for the order
    puts "Generating invoice for the order"
    # Code to generate invoice
  end
end

class EmailSender
  def send_confirmation_email(order)
    # Code to send confirmation email to the customer
    puts "Sending confirmation email to the customer"
    # Code to send email
  end
end