SOLID Principles in Ruby on Rails: Part 2.

Welcome back, Ruby enthusiasts! Ready to dive deeper into the magical world of SOLID principles? Grab your coffee (or tea, no judgment here), and let’s make these principles as fun as a weekend hackathon.

Single Responsibility Principle (SRP)

Example: Separating User Notifications

Ever tried to do too many things at once? Your User model feels the same way. Let’s give it a break and let it focus on what it does best: being a User.

Before:

class User < ApplicationRecord
  def send_welcome_email
    # Code to send welcome email
  end

  def send_password_reset
    # Code to send password reset email
  end
end

After:

class User < ApplicationRecord
end

class UserNotifier
  def initialize(user)
    @user = user
  end

  def send_welcome_email
    # Code to send welcome email
  end

  def send_password_reset
    # Code to send password reset email
  end
end

See? Now the User can chill while the UserNotifier handles the communication. It’s like hiring an assistant for your overworked self.

Open/Closed Principle (OCP)

Example: Extending Payment Methods

Imagine you’re a chef and every time someone orders a new dish, you have to rewrite the entire menu. Sounds exhausting, right? Let’s keep our code open for new dishes but closed for rewriting.

Before:

class Payment
  def process(type)
    if type == 'credit_card'
      # Process credit card payment
    elsif type == 'paypal'
      # Process PayPal payment
    end
  end
end

After:

class Payment
  def process(payment_method)
    payment_method.process
  end
end

class CreditCardPayment
  def process
    # Process credit card payment
  end
end

class PayPalPayment
  def process
    # Process PayPal payment
  end
end

class BitcoinPayment
  def process
    # Process Bitcoin payment
  end
end

Now you can add new payment methods without touching the Payment class. It’s like adding new recipes to your cookbook without rewriting the whole thing. Bon appétit!

Liskov Substitution Principle (LSP)

Example: User Roles

Remember that time you tried substituting baking soda for baking powder? Let’s avoid that kind of disaster in our code.

Before:

class User
  def permissions
    raise NotImplementedError, 'This method should be overridden by subclasses'
  end
end

class Admin < User
  def permissions
    'all'
  end
end

class Guest < User
  def permissions
    'read'
  end
end

After:

class User
  def permissions
    raise NotImplementedError, 'You must implement the permissions method'
  end
end

class Admin < User
  def permissions
    'all'
  end
end

class Guest < User
  def permissions
    'read'
  end
end

Now Admin and Guest can be swapped without any explosions. It’s like using the right ingredients in your favorite recipe.

Interface Segregation Principle (ISP)

Example: Different Types of Reports

Ever been forced to buy a whole album when you only like one song? Let’s not do that to our clients. Give them only what they need.

Before:

class Report
  def generate_pdf
    # Generate PDF report
  end

  def generate_csv
    # Generate CSV report
  end

  def generate_html
    # Generate HTML report
  end
end

After:

class Report
end

class PdfReport < Report
  def generate
    # Generate PDF report
  end
end

class CsvReport < Report
  def generate
    # Generate CSV report
  end
end

class HtmlReport < Report
  def generate
    # Generate HTML report
  end
end

Now, each report type is a solo act. It’s like creating a custom playlist instead of buying the whole album.

Dependency Inversion Principle (DIP)

Example: Notifications System

Think of this as choosing the right tool for the job. You wouldn’t use a hammer to fix your laptop, right?

Before:

class Notification
  def send_email(message)
    # Send email notification
  end

  def send_sms(message)
    # Send SMS notification
  end
end

After:

class Notification
  def initialize(sender)
    @sender = sender
  end

  def send(message)
    @sender.send(message)
  end
end

class EmailSender
  def send(message)
    # Send email notification
  end
end

class SmsSender
  def send(message)
    # Send SMS notification
  end
end

class PushNotificationSender
  def send(message)
    # Send push notification
  end
end

Now you can easily switch between email, SMS, and push notifications. It’s like having a multi-tool in your coding toolbox.

Conclusion

Implementing SOLID principles in your Rails applications doesn’t have to be a chore. By following these guidelines with a bit of creativity and humor, you can make your code more maintainable and enjoyable to work with.

Stay tuned for more tips on writing clean, efficient, and fun Ruby on Rails code.

Thôi Lo Code Đi Kẻo Sếp nạt!