viernes, 20 de abril de 2018

Diseño emergente - Clean code

Esta publicación se centra en el capítulo de Diseño emergente de Clean Code (Robert C. Martin).

Kent Beck establece cuatro reglas para crear un Diseño simple (Simple Design) que son fundamentales a la hora de crear un software bien diseñado. Un diseño es simple sigue las siguiente reglas:

  • Pasa todos los test.
  • No contiene código duplicado.
  • Expresa la intención del programador.
  • Minimiza el número de clases y métodos.

Diseño Simple Regla 1: Pasa todo los test


Un sistema debe tener el comportamiento para el cual fue diseñado. Este debe poder ser verificable para poder asegurar que se está comportando de manera adecuada. Para saber si un sistema es verificable, debería ser probado. Los sistemas que no se pueden probar no deberían ser desplegados ya que no hay garantías en lo referente a su su comportamiento. Un sistema que ha sido probado exhaustivamente y pasa todos los test es un sistema verificable.

Lo sistemas verificables permiten un diseño donde las clases son pequeñas y tienen un único propósito. Esto facilita que las clases cumplan el Single Responsibility Principle (SRP). Cuanto más pruebas se escriban más módulos se irán añadiendo que sean más fáciles de probar. Así que si un sistema está plenamente probado ayuda a crear mejores diseños.

Un mayor acoplamiento hace más difícil escribir test por lo que cuantos más test se escriben más sencillo será usar el principio de Dependency Inverse Principle (DIP) y otras herramientas como la inyección de dependencias, las interfaces y la abstracción para minimizar el acoplamiento.

Diseño simple Regla 2: no duplicar


La duplicación es el enemigo principal de un sistema bien diseñado. Este representa trabajo y riesgo adicional, además de añadir complejidad.

La duplicación se puede manifestar de diversas formas ya sea a través de un código que sea idéntico, muy parecido o incluso que tenga una implementación duplicada.

Por ejemplo, si hay dos métodos en una colección de objetos:


El método «isEmpty» podría devolver un valor binario mientras que «size» devolvería un número entero. La duplicación se puede evitar haciendo que «isEmpty» esté relacionada con la definición de «size».

Crear un sistema limpio requiere eliminar la duplicación incluso si son pocas líneas de código. Observemos el siguiente ejemplo.

Para mantener el sistema limpio hay que eliminar la pequeña duplicación.

Al extraer funcionalidad en estos pequeños niveles se empiezan a reconocer las vulneraciones del Single Resposibility Principle (SRP). Así que este nuevo método extraído se podría mover a otra clase de manera que se eleve su visibilidad. También se puede abstraer el método y se puede reusar en un contexto diferente. Este tipo de reutilización consiste en hacer que la complejidad de un sistem se reduzca sustancialmente. Entender cómo lograr la reutilización del código en pequeño es en esencia reutilizar el código en partes más grandes.

El Template Method pattern es una técnica para eliminar la duplicación a un nivel superior. Observemos el siguiente ejemplo.


Los dos métodos tienen el mismo código a excepción del cálculo de la puntuación por la imagen o el vídeo. El algoritmo cambia dependiendo del tipo de post que sea.

Se puede eliminar la duplicación aplicando el Template method pattern.

Las subclases sobreescriben el método de manera que implementan la lógica específica para cada tipo de post.

Expresividad


Cuando un programador escribe un código lo hace en base a su comprensión del problema que está resolviendo. Una vez pasado un tiempo y si ese mismo programador tiene que volver a tocar esa parte de código es muy posible que no entienda su propio código hasta que no vuelva a adquirir ese conocimiento más profundo del problema.

La mayor parte del coste de un proyecto de software a la larga es el del mantenimiento. Cuanto más grande es el sistema más complejo será entender qué hace cada una de sus partes. Por lo tanto el código debería comunicar la intención tan claramente como sea posible para que otros tengan que invertir menos tiempo en su comprensión. Esto reduce las equivocaciones y el coste de mantenimiento.

Los siguientes puntos son fundamentales:

  • Elegir buenos nombres que comuniquen la responsabilidad de cada clase y método.
  • Que estos sean lo más pequeños posibles.
  • Usar nomenclatura estándar del ámbito de la programación como patrones de diseño que describen la intención del diseño a otros programadores.
  • Baterías de pruebas unitarias que estén bien escritas y expresen lo que se está probando.
  • Aunque lo más importante es intentarlo. Ya que en demasiadas ocasiones una vez que el problema está resuelto se pasa al siguiente problema sin mejorar el código para la siguiente persona que lo tenga que leer.

Clases y método mínimos


En un esfuerzo por cumplir las reglas anteriores se puede llegar a crear clases y métodos que no son necesarios.

Se podría dar el caso de que hubiera un estándar de codificación que establezca crear una interface por cada clase. En este caso habría que ser más pragmático y no tener tantas clases e interfaces.

La meta final es mantener el sistema con las clases y métodos mínimos. Esta regla es la que menos prioridad tiene de las cuatro.

Conclusión


No hay unas simples prácticas que puedan reemplazar la experiencia, pero aplicando estas reglas se puede incrementar el aprendizaje que de otra manera se hubiera tardado más tiempo en adquirir.

No hay comentarios:

Publicar un comentario