SOLID #1: Single Responsibility Principle (SRP) con C#

En esta publicación veremos como implementar Single Responsibility Principle usando el lenguaje C#.

Rodríguez Patiño, Eduardo
2020-11-28 | 11,629 lecturas
Actualizado:

Un módulo solo debe tener un motivo para cambiar.

Lo cual quiere decir que una clase debería estar destinada a una única responsabilidad y no mezclar la de otros o las que no le incumben a su dominio.

Ejemplo

El siguiente ejemplo es una clase que permite crear una orden de compra y luego manda una notificación al cliente.

public class OrderService
{
    private readonly SmtpClient _smtpClient;

    public OrderService(SmtpClient smtpClient) 
    {
        _smtpClient = smtpClient;
    }

    public async Task Add(Order order) 
    {
        // 01. Código para crear la orden

        // 02. Notificar al cliente
        var message = new MailMessage ("sales@admin.com", order.ClientEmail)
        {
            Subject = "Se le asignó una compra",
            Body = "Estimado,\n Hemos creado su nueva orden de compra .."
        };

        await this.SendCustomerNotification(message);
    }

    public async Task SendCustomerNotification(MailMessage message) 
    {
        await _smtpClient.SendMailAsync(message);
    }
}

¿Qué anda mal?

El código en general esta bien, pero el problema es que comparte la responsabilidad de mandar el correo, la cual no esta dentro de su dominio.

De esta manera podemos hacer mejoras al BankService sin tener que tocar la clase UserService.

¿Cómo hacemos respetar el principio?

Separemos las responsabilidades en sus clases respectivas.

public class NotificationService 
{
    private readonly SmtpClient _smtpClient;

    public NotificationService(SmtpClient smtpClient)
    {
        _smtpClient = smtpClient;
    }

    public async Task SendEmail(MailMessage message) 
    {
        await _smtpClient.SendMailAsync(message);
    }
}

public class OrderService
{
    private readonly NotificationService _notificationService;

    public OrderService(NotificationService notificationService) 
    {
        _notificationService = notificationService;
    }

    public async Task Add(Order order) 
    {
        // 01. Código para crear la orden

        // 02. Notificar al cliente
        var message = new MailMessage ("sales@admin.com", order.ClientEmail)
        {
            Subject = "Se le asignó una compra",
            Body = "Estimado,\n Hemos creado su nueva orden de compra .."
        };

        await this._notificationService.SendEmail(message);
    }
}

¿Qué ganamos?

Hacemos que el código sea más fácil de mantener al tener las responsabilidades separadas en distintas clases.