Applying SOLID Principles in Ruby: Examples and Best Practices

Single Responsibility Principle (SRP)

This principle states that each class should have a single responsibility. It emphasizes that a class should perform one specific function and not have too many reasons to change.

Example: Managing user information and sending email notifications.

class UserManager
  def create_user(user_data)
    # Logic for creating a user
  end
end

class EmailService
  def send_email(email_data)
    # Logic for sending an email
  end
end

Open/Closed Principle (OCP)

This principle encourages extending functionality by adding new code rather than modifying existing code.

Example: Handling different payment methods in an e-commerce application.

class PaymentProcessor
  def process_payment
    # Common logic for payment processing
  end
end

class CreditCardPaymentProcessor < PaymentProcessor
  def process_payment
    # Logic for processing credit card payment
  end
end

class PayPalPaymentProcessor < PaymentProcessor
  def process_payment
    # Logic for processing PayPal payment
  end
end

Liskov Substitution Principle (LSP)

This principle asserts that objects of a derived class should be substitutable for objects of the base class without affecting the correctness of the program.

Example: Managing geometric shapes.

class Shape
  def area
    # Common logic for calculating area
  end
end

class Rectangle < Shape
  def area
    # Logic for calculating area of rectangle
  end
end

class Square < Shape
  def area
    # Logic for calculating area of square
  end
end

Interface Segregation Principle (ISP)

This principle advises breaking interfaces into smaller ones to avoid forcing classes to implement methods they don't need.

Example: Interfaces for updating and displaying data.

module UpdateableFeature
  def update_feature
    # Logic for updating feature
  end
end

module DisplayableFeature
  def display_feature
    # Logic for displaying feature
  end
end

Dependency Inversion Principle (DIP)

This principle suggests using dependency injection to manage dependencies.

Example: Using dependency injection to manage dependencies.

class OrderProcessor
  def initialize(db_connection, email_service)
    @db_connection = db_connection
    @email_service = email_service
  end
end

Remember that applying SOLID principles in Ruby should be done flexibly based on the specific purpose of your project and your understanding of SOLID and Ruby.