Pereza II: Generadores de código
Los generadores de código hacen nuestro trabajo duro. Pero no los necesitamos más.
Líneas de código gratis
Hace unos años trabajando en la industria me tocó participar en la demo de un producto de programación en el que se hacía uso de un wizard o generador de código. La persona que presentaba dicha demostración se vanagloriaba de escribir menos código dejando que la máquina escribiera el texto por ella basándose en los templates que iba declarando.
El argumento de seducción consistía en la posibilidad de escribir menos código. Hoy en día sabemos que ese enfoque está completamente equivocado.
Si nosotros le tenemos que indicar a la máquina cuál es el meta-código es porque no estamos siendo suficientemente declarativos.
Existen varias razones:
a) No hemos llegado al nivel de abstracción y tenemos que enseñarle al intérprete a que haga manipulaciones sintácticas de nuestros modelos.
Si existe una cierta redundancia lo natural sería modelar esa redundancia buscando en la realidad hasta descubrir con qué concepto abstracto (que todavía no habíamos modelado) se corresponde.
b) Algunos generadores de código se basan en la excusa (casi siempre incorrecta) de que el código escrito es más rápido que el utilizado al incluir una indirección o abstracción. El argumento de la performance casi siempre pierde sustento ante un benchmark. Como contrapartida podemos argumentar que para leer o debugguear una función en general las indirecciones confunden al programador novato (y le hacen perder tiempo al experimentado)
Actualmente el tiempo del ser humano es mucho más valioso y escaso que el tiempo de la máquina.
c) algunos lenguajes de programación imponen restricciones arbitrarias de tipos que únicamente pueden ser evitadas mediante la generación de código intermedio como los generics de Java o templates en c++.
Este tipo de soluciones parecen diferentes pero son similares.
d) Para resolver estas indirecciones el intérprete utiliza meta-programación aunque esto es desaconsejado entre otros motivos por dejar referencias oscuras, casi imposibles de refactorizar y fácilmente borrables por equivocación.
e) El código generado con Wizards o con meta-programación es mucho más oscuro, mucho más difícil de seguir y viola el principio de fallar rápido porque no suele defenderse ante posibles construcciones inválidas.
Tenemos que tomar la decisión de no utilizarlo si queremos construir buenos modelos de software.
f) El código generador por los wizards, templates y herramientas automáticas de generación de código es de muy baja calidad. No suele estar documentado y genera acoplamiento por ser un copy&paste repetitivo. En caso de encontrar un error en uno de los fragmentos generados, debido a dicho acoplamiento, tendremos que corregirlo en múltiples lugares violando así el principio DRY.
g) El código generado tiene poco valor agregado, y muchas veces fomenta malas prácticas de diseño como la generación automática de getters y setters.
h) Finalmente, si las computadoras pueden hacer inferencias sobre la repetición de nuestros patrones de diseño es porque no estamos aportando la parte creativa (y por ahora no replicable) del diseño y nos quedaremos sin trabajo en el corto plazo.
La solución está en el estante de siempre
Ante el síntoma de encontrar un patrón que se repite en nuestro código el diagnóstico casi siempre es el mismo:
Existe una abstracción o generalización en el dominio del problema que todavía no descubrimos.
La solución trivial es ir, con la ayuda de nuestro experto de dominio favorito, a descubrir cuál es el concepto en el mundo real que engloba la repetición o patrón que el wizard o template no nos permitía descubrir.
Conclusiones
Los generadores de código dinámico fueron una moda pasajera, propia de un momento en que se medía la productividad en base a las líneas de código generadas.
Para superarlos deberemos mantenernos fieles a la regla de la biyección y buscar abstracciones dentro del mundo real en el dominio del problema.
Parte del objetivo de esta serie de artículos es generar espacios de debate y discusión sobre diseño de software.
Esperamos comentarios y sugerencias sobre este artículo.
Este artículo también está disponible en inglés aquí.