CUPIDo mató a los principios SOLIDos (II)

Todos nos hemos encontrado trabajando sobre código con el que era una delicia trabajar. Era un código fácilmente navegable, legible y sobre el que se podía razonar. Un código que te animaba a profundizar en él. Era un código escrito por alguien que se preocupó por la persona (quizás él mismo) que vendría después.

“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”

 —Refactoring, Martin Fowler with Kent Beck, 1996

De la cita anterior queda claro que escribimos (o deberíamos escribir) código para que los humanos lo entiendan. Pero, ¿podemos escribir un mejor código no solamente con el objetivo de que un humano lo pueda entender?

CUPIDo mató a los principios SOLIDos

“Habitability is the characteristic of source code that enables [people] to understand its construction and intentions and to change it comfortably and confidently.

 “Habitability makes a place liveable, like home.”

 —Habitability and Piecemeal Growth1, Patterns of Software pp. 7-16, Richard P. Gabriel

Marcos Antonio González Gómez-Caro
Marcos Antonio González Gómez-CaroSenior Software Developer en VIEWNEXT

¿Qué tal el concepto de habitabilidad relativo al código?

Como programadores vivimos en el código. Por lo tanto, si el lugar en el que vivimos está minado, lo que menos nos apetecerá será recorrerlo a menudo.

¿Y qué tal un código alegre? Un código que te haga feliz. Un código que te alegre el trabajar con él. Pero, ¿qué hace que un código sea alegre? ¿Cuáles son sus propiedades?

Propiedades vs Principios

 Cuando Dan North estaba planteando la alternativa sobre los principios SOLID, (Ver «CUPIDo mató a los principios SOLIDos I» para más detalle) una de las cosas que tuvo en consideración fue el empleo de la palabra principios.

Consideraba que los principios son reglas que terminan generando fronteras (restricciones) de un modo que sólo cabía estar dentro o fuera. Lo que se traduce en que o cumples el principio o no lo cumples (y si no lo cumples es que tu código es erróneo).

Es por eso que prefiere el uso de propiedades, ya que las considera cualidades o características que permiten definir un objetivo al que encaminarse. Nuestro código simplemente estará más cerca o más lejos del objetivo, pero no sin tener la consideración de erróneo.

Con esta distinción (y elección), se centra en las cualidades que debería tener el código a generar más que en las reglas a seguir para generarlo.

Y centrándonos ya en el uso de propiedades, ¿cuáles son las características de dichas propiedades? Es decir, ¿cuáles serían sus meta-propiedades? Pues deben ser:

  • Prácticas: fáciles de articular/expresar, fáciles de comprobar y fáciles de adoptar.
  • Humanas: expresadas desde la perspectiva de la gente, no del código. Desde el sentimiento que produce trabajar con ese código.
  • Estratificadas: en el sentido de que ejercen de guía para los principiantes, y como matices para los más experimentados que quieren profundizar en la naturaleza del software.

CUPIDo mató a los principios SOLIDos

Pero, ¿qué tiene esto que ver con CUPID? Pues, precisamente que no se trata de una colección de principios, sino de propiedades.

Y lo del acrónimo CUPID ¿de dónde sale? Pues del hecho de que, tras las críticas que lanzó Dan North a los principios SOLID, le preguntaron si tenía una alternativa más elaborada que su receta de escribir código sencillo. Y el resultado fueron las propiedades CUPID, que es un retroacrónimo (seleccionó el acrónimo antes de darle definición), al hacer uso de Cupid (Cupido en inglés) para generarlo, ya que el post que lo dio a conocer vio la luz sobre el día de San Valentín de 2022. Pasemos a revisarlas.

¿Cuáles son las propiedades CUPID?

Composable (Componible): casa bien con otros.

Unix philosophy (filosofía Unix): hace una sola cosa bien.

Predictable (Predecible): hace lo que se espera que hagas.

Idiomatic (Idiomático): se siente natural (aunque no sea de la mejor forma de hacerlo).

Domain-based (basado en el Dominio): tanto en el lenguaje como en la estructura.

Composable (Componible).

 Un código componible es aquel que, por ser fácil de usar, es usado una y otra vez. Un código que su uso te obliga a aprender poco de él para usarlo, que su uso puede conducir a pocas equivocaciones, o con el que las posibilidades de entrar en conflicto son mínimas.

Es un código donde los nombres elegidos revelan la intención del mismo, provocando que sea fácil de descubrir y de evaluar.

También será un código con dependencias mínimas, reduciendo las preocupaciones derivadas de las mismas, así como de posibles incompatibilidades.

Unix philosophy (filosofía Unix).

 ¿Qué es seguir la filosofía Unix? Pues el hacer que cada programa haga una cosa bien (y sólo una cosa). Sí a esta característica le unimos la anterior de ser componible, tendremos la potencialidad de llegar a hacer cualquier cosa.

Pero, ¿qué diferencia esta propiedad del Single Responsibility Principle (SRP)? Pues la perspectiva desde la que se toma. SRP lo hace desde el interior del código mirando al exterior, y la filosofía Unix es desde el exterior mirando al interior. La filosofía Unix es sobre qué hace el código, y no de cómo lo hace o puede llegar a cambiar.

Predictable (Predecible).

 Y es que el código se debe comportar como se espera de él, sin sorpresas, incluso aunque no hubiera existencia de tests. Si los hubiera, se vería como una generalización de la testabilidad, es decir, que pasa todos los tests.

Sería determinístico, pero no solo es desde el punto de vista del comportamiento o la funcionalidad, sino de qué se obtiene en cada ejecución. Hace la misma cosa cada vez y bajo unas características operativas bien entendidas (memoria, CPU, etc). Además,dicho código debería ser:

  • Robusto: cómo se comporta ante multitud de situaciones distintas.
  • Fiable: cómo se comporta ante situaciones bien conocidas.
  • Resiliente: cómo se comporta ante situaciones no esperadas.

Y sería observable en el sentido técnico, en el que el estado interno puede ser inferido de las salidas proporcionadas. Hay que tener en consideración que no se puede hacer algo observable, sino que se diseña algo observable, haciéndola una característica de lo que se construye.

De esta forma, buscaremos crecer en los niveles de instrumentación (instrumentación, telemetría, monitorización, alerta, predicción y adaptación).

Idiomatic (Idiomático).

 El código debería ajustarse a los modismos del lenguaje, lo que implica que hay que profundizar en el estudio del mismo. Los modismos del lenguaje pueden ser la forma de resolver problemas (p.e. patrones de diseño, de refactorizado o de de arquitectura de aplicación). También se pueden considerar modismos las características, constructores, librerías, frameworks y herramientas estándares del contexto en el que nos encontremos.

Además, estará escrito para la gente del ecosistema en el que se desarrolle, de forma que se sienta natural trabajar con él para dichas personas. Es el modo en el que se escribe código habitable, haciendo uso de modismos.

Esto implica el uso de modismos locales, tales como las guías de estilos estándares o de facto. Estarán alineados con los proyectos, las dependencias, las plataformas y la organización, teniendo en cuenta que el nombrado o la estructuración del código son modismos. Se busca que sea familiar en todo momento, lo escriba quien lo escriba. Y solo se puede escribir código idiomático si se aprenden los modismos, por lo que es una inversión a realizar.

Domain-based (basado en el Dominio).

 El código debe transmitir lo que está haciendo en el lenguaje del problema para minimizar la carga cognitiva entre lo que se escribe y lo que hace. Esto implica algo más que usar las palabras correctas, es hacer uso del dominio.

El código se escribirá en el lenguaje del dominio…y siempre recordando que puede hay múltiples dominios. Debemos buscar que el dominio del código modele de manera tan natural el dominio del problema que ambos colapsen en el mismo espacio. Que hablar sobre qué hace el código y hablar de cómo funciona el dominio sean la misma cosa, eliminando la carga cognitiva que implicaría la traducción de un modelo a otro.

Hay que tener en consideración no sólo el lenguaje del dominio, sino la estructura del dominio. Hay que generar código para la solución, no para el framework de turno.

Se deben usar límites de dominio como límites de módulo y unidades de despliegue. Precisamente está relacionado con la cualidad de poder ser desplegado. No necesariamente sobre lo que desplegamos, sino sobre las opciones para el despliegue. El alineamiento entre límites de dominio con límite de unidades de despliegue es lo que permite liberar subsistemas de manera completamente independiente o gestionarlos de manera completamente independiente.

En definitiva, hay que buscar que sea imposible mirar en el código y que no se sepa qué problema está resolviendo.

¿Qué opinas de las propiedades CUPID? ¿Crees que realmente son una alternativa a los principios SOLID? ¿O se pueden considerar como un complemento?

Quizás lo más apropiado es huir de Martillos de Oro, y considerar que toda herramienta tiene su contexto de aplicación, y que lo que más nos aporta es saber reconocer dichos contextos para sacar el mayor partido de ellas.

Webliografía:

CUPID – for joyful coding – Daniel Terhorst-North – NDC London 2022

CUPID—for joyful coding – Dan North & Associates Limited

CUPID – for joyful coding – Speaker Deck

CUPID – for joyful code

Otros artículos relacionados

2024-02-21T09:48:39+01:0021 febrero, 2024|

¡Compártelo en tus redes sociales!

Ir a Arriba