DEV Community

Omar Faruque Shamim
Omar Faruque Shamim

Posted on

Single Responsibility Principle (SRP)

Each class should have only one responsibility or reason to change.

This means each class should focus on a single functionality or responsibility and not combine unrelated tasks.

Why is SRP Important?

  • Simplifies Maintenance : Changes to a specific responsibility are isolated, reducing the risk of impacting unrelated code.

  • Improves Code Readability : Classes are smaller and easier to understand.

  • Enhances Reusability : Class can be reused in different contexts without carrying unnecessary responsibilities.

  • Eases Testing : Testing a single responsibility is straightforward, as the class has fewer dependencies.

  • Reduces Coupling : Avoids tightly coupling unrelated functionalities, making the codebase more flexible.

How to Apply SRP

Hereโ€™s an example of implementing SRP for a ticket booking scenario. The solution demonstrates how to handle booking logic, database persistence, email notifications, and error logging using separate classes.

Classes Overview
BookingService: Core business logic for booking tickets.
DatabaseService: Handles database interactions.
EmailService: Sends email notifications.
LoggerService: Logs errors or other information.

Code Implementation

  • LoggerService Handles logging operations.
public class LoggerService
{
    public void LogError(string message)
    {
        // Log error to a file or monitoring system
        Console.WriteLine($"Error: {message}");
    }

    public void LogInfo(string message)
    {
        // Log general information
        Console.WriteLine($"Info: {message}");
    }
}
Enter fullscreen mode Exit fullscreen mode
  • EmailService Handles sending emails.
public class EmailService
{
    public void SendEmail(string to, string subject, string body)
    {
        // Simulated email sending logic
        Console.WriteLine($"Email sent to {to} with subject: {subject}");
    }
}
Enter fullscreen mode Exit fullscreen mode
  • DatabaseService Handles database operations.
public class DatabaseService
{
    public void SaveBooking(string bookingDetails)
    {
        // Simulated database save logic
        Console.WriteLine($"Booking saved: {bookingDetails}");
    }
}
Enter fullscreen mode Exit fullscreen mode
  • BookingService Core business logic for ticket booking. It orchestrates the other services.
public class BookingService
{
    private readonly DatabaseService _databaseService;
    private readonly EmailService _emailService;
    private readonly LoggerService _loggerService;

    public BookingService(DatabaseService databaseService, EmailService emailService, LoggerService loggerService)
    {
        _databaseService = databaseService;
        _emailService = emailService;
        _loggerService = loggerService;
    }

    public void BookTicket(string userEmail, string bookingDetails)
    {
        try
        {
            // Step 1: Business logic for booking (e.g., validation, seat availability)
            _loggerService.LogInfo("Booking process started.");

            // Step 2: Save booking to the database
            _databaseService.SaveBooking(bookingDetails);

            // Step 3: Send confirmation email
            _emailService.SendEmail(userEmail, "Booking Confirmation", "Your booking is confirmed!");

            _loggerService.LogInfo("Booking process completed successfully.");
        }
        catch (Exception ex)
        {
            // Step 4: Log any errors
            _loggerService.LogError($"Error during booking: {ex.Message}");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Program Execution Tie everything together and simulate the booking process.
public class Program
{
    public static void Main(string[] args)
    {
        // Dependency setup
        var databaseService = new DatabaseService();
        var emailService = new EmailService();
        var loggerService = new LoggerService();

        var bookingService = new BookingService(databaseService, emailService, loggerService);

        // Simulated booking details
        string userEmail = "user@example.com";
        string bookingDetails = "Flight: XYZ123, Date: 2024-12-01, Seat: 12A";

        // Book the ticket
        bookingService.BookTicket(userEmail, bookingDetails);
    }
}
Enter fullscreen mode Exit fullscreen mode

Execution Flow

  • Business Logic Execution: Booking process begins with validation and checks.
  • Database Save: The booking details are stored using DatabaseService.
  • Email Notification: A confirmation email is sent using - EmailService.
  • Error Handling: Any exceptions during the process are logged by LoggerService.

This approach ensures a clean, modular design while adhering to SOLID principles.

Top comments (0)