3:11 0 0
Principios SOLID Single Responsabilitiy Principle

Principios SOLID Single Responsabilitiy Principle

  DrUalcman |  diciembre 262021

Single Responsabilitie Principle [SRP]


Definicion: Una clase debe tener una, y solo una, razon para cambiar.

Pero, ¿y esto que quiere decir exactamente? Bueno, pues todo es un poco abstracto, como toda recomendación, dependerá de la interpretación de cada individuo, o de cada caso de como se vea cual es la responabilidad de la clase. Robert C. Martin lo definió en su libro Agile Software Development, Principles, Patterns and Practices que luego lo reviso en otra publicación más específica sobre C# Agile Principles, Patterns and Practices in C#.

Como empecé a comentar, ¿que quiere decir exaáctamente esta definición? Mi interpretación, tras haber estudiado y escuchado a personas con más experiencia que yo, es que cuando pensamos en una clase, debemos de "intentar" ver dónde puede cambiar, y con esto me refiero, que una clase solo realice un trabajo, no mezclar varias cosas dentro de la misma clase. Y es en este momento cuando se peude decir que es muy abstracto, ya que dependiendo del punto de vista la responsabilidad puede ser una, pero para otros puedes estar mezclando cosas. Vamos a poner un ejemplo.

Tenemos una clase que su función es la de administrar usuarios. Bien pues yo puedo decir que mi clase necesita una serie de métodos para realizar su función, como puede ser, agregar, editar, borrar, listar, pero además necesito llevar el control de que usuario hace las cosas y pongo metodos para realizar este log. Ya que mi responsabilidad es la de administrar usuarios y para ello necesito llevar el control de quien lo hace.

Bueno, pues en este ejemplo, más o menos claro, ya se ven DOS responsabilidades, la de administrar usuarios y llevar el log de quien hace el mobimiento. Pero los muy puristas irían aún más arriba, y te dirían, casi, casi, que cada acción es una responsabilidad y por lor lo tanto hay muchas. Desde mi punto de vista yo veo más bien TRES responsabilidades:

1. Llevar el registro de quien hace la acción
2. Escribir en la fuente de datos (agregar, editar, borrar)
3. Leer de la fuente de datos (listar)

Pero dejémonos de teoría, que como ya he dicho, toda recomendación en la programación, es muy abstracta y depende mucho de las necesidades en cada momento, de la interpretación del problema a resolver y, lo más importante, la experiencia que tenemos para afrontar dicho reto. Veamos unos cuantos ejemplos.

Ejemplo que no cumple con SRP

Seguimos con el ejemplo de administrar usuario y creamos una clase para UserService con un método CreateUser el cual debe de insertar en una base de datos al usuario creado y enviar un correo electrónico para notificar que el usuario ha sido creado. Se vería algo como esto:

public class UserService
{
public void CreateUser(string username)
{
SqlConnection con = new SqlConnection();
con.Open();
SqlCommand command = con.CreateCommand("INSERT INTO [...]"); //insert into a DB

SmtpClient client = new SmtpClient("smtp.myhost.com");
client.Send(new MailMessage()); //send notification mail
}
}

Esta clase no sigue el principiuo de SRP ya que está escribiendo en la base de datos y además está enviando el correo electrónico. Por lo que la clase UserService si necesitamos, por ejemplo, cambiar el servicio de correo electrónico, deberiamos de cambiar el método CreateUser y/o si cambiamos de proveedor de base de datos, también, debenmos de actualizar el método CreateUser para adaptarlo a las nuevas condiciones.

Y como decía, ¿a qué extremos tenemos que llegar para cumplir con SRP? De la forma que lo he descrito, deberíamos mober tanto la escritura en la base de datos, como el envío del correo electrónico, a otras clases más especializadas. O sólo mober uno de los dos, principalmente el de envío de correo, a una clase más especializada. Ya que sólo uno de los dos es el que puede camgiar, por lo que mi responsabilidad (es decir el de la clase) es crear el usuario en la base de datos, y si cambio de base de datos, si o si, debeo de actualizar el método para adaptarme a la nueva base de datos.

Pero, si pensamos un poco más allá, y en un posible futuro, lo mejor y más recomendable, es mover, como ya comenté antes, los dos posibles cambios hacia clases más especializadas, para que mi clase, UserService y en concreto su método CreateUser no tenga que estar siendo actualizado, ya que, solo si necesito agregar el apellido, debo de cambiar esta clase, obviamente también se vería afectados los otros dos, crear el usuario en la base de datos y enviar el correo de confirmación, para que recibieran el apellido. Pero, sólo y solo, si realmente lo necesitan. Puede que necesite recibir el apellido, pero porque hago otra llamada a otra clase a la que le voy a enviar el apellido para realizado otra función.

Veamos como quedaría esta clase respetando el SRP:

public class UserService
{
public void CreateUser(string username)
{
UserRepository.Insert(username);
EmailService.Send(username);
}

Fíjate que bonita ha quedado la clase, y que comprensible es ahora. Primero, apenas son 4 líneas de código. Y hace llamadas a clases que identifican claramente que es lo que van a hacer. Obviamente dentro de estas clases tendremos un poco más de código, para que hagan su trabajo.

Conclusiones

Como ya comenté en el blog de Clean Architecture para torpes. Intentar hacer las cosas siguiendo las recomendaciones de un código limpio, siemrpe nos va a hacer crear más archivos para segregar y separar más el código en cada vez más pequeños y manejables fragmentos de código.

Y hasta aquí la breve explicación del principio SOLID Single Responsability Principle.

Open/Close Principle [OCP]

Liskov Substitutio Principle [LSP]

Interface Segregation Principle [ISP]

Dependency Inversion Principle [DIP]


0 Comentarios

 
 
 

Archivo