Número 8
20 de abril de 2022

Do Repeat Yourself

Na programación temos tres siglas moi coñecidas: KISS (“Keep It Simple, Stupid”), YAGNI (“You Ain’t Gonna Need It”) e DRY (“Don’t Repeat Yourself”).

Estas siglas representan consellos para programadores. A primeira exhórtanos a non complicarnos a vida innecesariamente: escribe o código máis sinxelo que solucione o teu problema. A segunda dinos que non caiamos na tentación de facer cousas innecesarias pensando que as imos usar máis tarde, porque iso case nunca ocorre. A terceira recoméndanos que evitemos escribir a mesma cousa dúas veces.

Un home nunha paisaxe escabrosa berra “eco!” e o eco responde “eco…”. Logo o home berra “ola eco!” e o eco responde “iso dixen…”O eco que segue o principio DRY.

KISS e YAGNI son bos consellos: son doados de explicar, doados de entender e doados de aplicar. Queres facer algo complicado podendo facer algo máis simple? KISS: escolle a opción simple. Queres escribir un framework que che permita, no futuro, exportar datos a XML, JSON, Protocol Buffers, Thrift ou calquera outra representación incluso se non existe hoxe en día? YAGNI: segue os teus requirimentos e, se no futuro tés que exportar a Cap’n Proto, xa o farás daquela.

KISS e YAGNI refórzanse mutuamente: se non engades cousas que non precisas agora, o código é máis simple e viceversa. As dúas siglas son coma as dúas caras dunha moeda, ou coma os campos electromagnéticos: non podes ter unha sen a outra.

Por desgracia, non podemos dicir o mesmo de DRY. Se seguimos DRY cegamente, imos ir na contra de KISS e YAGNI.

Por exemplo, imaxinade que tedes tres funcións case idénticas e, como queredes seguir DRY, combinádelas para facer unha soa función que as substitúa. O malo é que esta función ten que cubrir todos os casos que cubrían as tres funcións orixinais, e iso fai que sexa bastante complexa. Se precisamos de engadir máis funcionalidade, isto complica esta función moito máis, que vai na contra de KISS. Se mantiverades as funcións separadas, abondaría con engadir unha cuarta función.

Para outro exemplo, pensade nunha aplicación web que le rexistros dunha base de datos e os amosa ao usuario no navegador. Para que isto funcione, ten que haber unha definición dos rexistros na base de datos, outra na parte da aplicación que se executa no servidor e outra na que se executa no navegador. Moita xente pensa que este é un número de repeticións intolerable, así que, para seguir DRY, escriben e empregan frameworks que lles permiten definir os rexistros nun só sitio. O malo deses frameworks é que teñen que contemplar todos os posibles casos de uso desde o principio, aínda que non se usen, e isto vai contra YAGNI.

Cando eu era un programador novato, non tiña medo de teclear e copiar e pegar e duplicar o que fixera falta: aínda gardo o código fonte dun programa que fixen en 1996 que estaba dividido en varias seccións, no que cada sección estaba feita a base de copiar e pegar e buscar e substituír. Segundo fun aprendendo máis e a tomar máis en serio o de DRY, o meu código fonte comezou a sofisticarse: moito código escribín que non entendía ninguén. Aínda máis, ter que escribir a mesma cousa varias veces dábame tanta preguiza e tanta rabia, que moitas veces gastaba tanto tempo buscando o framework perfecto que non me quedaba nada para programar.

Agora, a miña actitude é diferente: algo de duplicación non lle fai mal a ninguén. Por exemplo, cando quero xeneralizar varios fragmentos de código semellantes, espero a ter polo menos tres exemplos antes de comezar (é imposible xeneralizar nada con un ou dous exemplos). E, se falamos de aplicacións en capas, non teño ningún problema en ter unha definición para os obxectos en cada capa. É unha actitude moito máis saudable e produtiva: escribo máis e mellor código e estou máis contento.

Polo tanto, se me pedides que vos dea os meus consellos, estes son: KISS e YAGNI.

A DRY, botádelle auga.

A ilustración desta folla está baseada nun gravado de Joseph Mallord William Turner e nun gravado de Karel van Mallery.