2.6 Código Limpio
A lo largo de este tutorial vamos a modificar el código para generar un código más fácil de entender y de probar.
Robert C. Martin escribió un libro (Clean Code) para explicar cómo crear un código limpio para que sea más fácil de entender y entender por otros programadores. Otro libro también muy bueno es el siguiente Clean Architecture: A Craftsman's Guide to Software Structure and Design (Robert C. Martin Series) . Un libro enfocado en C# aunque no esta tan actualizado es: Clean Code in C#: Refactor your legacy C# code base and improve application performance by applying best practices
Algunas de sus sugerencias son:
Escribir nombres de variables y funciones descriptivos.
En lugar de repetir código crear funciones.
Que tus funciones no tengan muchas líneas de código. Alrededor de 10 líneas máximo .
Tus funciones no deben tener más de 3 parámetros.
El código debe ser suficientemente claro para que no necesite comentarios.
Evita utilizar números que signifiquen algo como 0 Cancelado 1 Activo 2 Vendido, es mejor utiilzar Enumeraciones.
Que tus funciones hagan lo que dice de acuerdo al nombre. Por ejemplo una función que se llame enviaEmail y que aparte de email imprima un recibo y guarde en base de datos.
No almacenar passwords en el código.
También explica unos principios llamados SOLID los cuales son:
S - Single responsibility principle (SRP)
Este principio indica que cada clase o función debe realizar solamente una actividad. Por ejemplo. el método insertar de una clase categoría solo debe insertar no debe tener parámetro por ejemplo acción el cual indique que la función debe insertar o modificar una categoría. O una clase que guarde en base de datos una factura y la imprima, se debe tener 2 clases una para comunicarse con la base de datos y otra para imprimir.
O - Open/Closed principle (OCP)
Tú código debe ser abierto a ser extendido por otros programadores para que lo puedan ajustar a sus necesidades y debe ser cerrado para que no necesites cambiar tu código para adecuarlo a las necesidades de los demás programadores.
Por ejemplo puedes tener un clase que calcule los impuestos de acuerdo al tipo de producto. Unos productos tienen un impuesto donde debes pagar el 16% del valor del producto como impuesto, otro impuesto puede ser de forma fija por ejemplo cada que compres el producto debes pagar $4.00 de impuesto. El código podría ser el siguiente
Si luego surge un nuevo tipo de impuesto que sea una combinación de los dos, tendrías que modificar tu clase para agregar el nuevo tipo de impuesto y pasar el cambio a todos los programadores que estén utilizando tu clase. Con el principio abierto cerrado esto no es necesario.
Para esto usa el concepto de interfaces el cual te permite definir las propiedades y métodos comunes a todos los objetos.
Aunque parece que es mucho más código de esta forma se cumple el principio 1, 2 en el cual cada clase solo tiene un objetivo y si luego surgen nuevos tipos de impuestos solo creas una clase que implemente la interfaz producto y no tienes que pedirle a la persona que diseño la clase Impuesto que agregue el cálculo cuando surja un nuevo tipo de impuesto. Si luego surgen muchos tipos de impuestos diferentes tendrías un código muy largo lleno de cases o de ifs
Este es un ejemplo sencillo ya un ejemplo más complicado es un método que borre un registro de acuerdo a su Id, el código siempre es el mismo buscar el registro por su id y luego borrarlo, lo único que cambiamos es el nombre de la tabla.
L - Liskov substitution principle
Este principio indica que cuando una clase hereda de otra clase se pueden sustituir sin que el funcionamiento sea diferente.
Continuando con el ejemplo anterior si creas otra clase que herede de ProductoPorcentaje la función CalculaImpuesto deberéa regresar el impuesto con la misma fórmula Precio * Tasa y no deberia hacer algo diferente como Precio * Tasa + Tasa ya que el funcionamiento seria diferente y se debería crear otra clase nueva que implemente la interfaz IProducto.
En el proyecto utilizaremos este principio para cambiar en enitity framework que en lugar de utilizar una base de datos de mysql utilice una de sql server o una base de datos en memoria.
El funcionamiento del código es el mismo, por lo cual podemos cambiar de base de datos utilizando el paquete nuget correspondiente.
I - Interface segregation principle
Este principio indica que las interfaces solo deben tener los métodos y propiedades que realmente son necesarios. Así los programadores que implementan tu interfaz solo implementan los métodos que son útiles para ellos.
Continuando con nuestro ejemplo nuestra interfaz IProducto si necesitamos tener productos que si manejan control de existencias es decir que no se pueden vender si no tienen existencias y productos sin existencia como por ejemplo la compra de un dominio de internet, sería un error agregar a nuestra interfaz IProducto un campo que diga existencia, lo mejor seria tener 2 interfaces una para productos con existencia otra para productos sin existencia
D - Dependency Inversion Principle
Este principio indica que los módulos de alto nivel no deben depender de módulos de bajo nivel. Ya que si cambias una clase mas sencilla debes cambiar la clase mas complicada.
Veamos un ejemplo, tenemos una clase casa, la cual incluye un objeto de tipo Puerta y Ventana
Esta clase no cumple con este principio ya que si luego necesitamos otro tipo de puerta o de ventana tenemos que modificar la clase casa, para esto lo mejor es crear interfaces para la clase Puerta y la clase Ventana y pasar en el constructor un objeto puerta y un objeto ventana para personalizar la casa. Este principio se utiliza mucho en .NET Core para pruebas unitarias
Nuestro ejemplo del principio 2 también cumple con este principio ya que pasamos la lista de productos como parámetro en lugar de que la clase cree los productos.
En el proyecto utilizamos este principio para pasar un objeto para guardar el log de errores y para poder cambiar la base de datos y para validar los permisos a los servicios.
Last updated