La complejidad es el enemigo

23 de Abril de 20211

Estoy cerca de cumplir 7 años trabajando en Google. Aprendí muchas cosas aquí, muchas más de las que podría escribir. Y pensé que podría compartir con vos algo que solo vino a mí a través de la experiencia.

La complejidad es mortal para el software. Es difícil medir su costo y tiende a introducirse muy lentamente, así que crece volviéndose peor al punto que es difícil verlo hasta que es muy tarde. Por otro lado, es fácil ver los beneficios de incrementar la complejidad: Una nueva capa intermedia permite la característica X, o dividir un proceso que corría en una computadora para que se ejecute en dos te permitiría superar el obstáculo de escalabilidad. Pero ahora deberías mantener otra capa de indirección en tu cabeza o implementar un nuevo mecanismo de comunicación entre dos computadoras.

Esto que mencioné es evidente tanto para los nuevos programadores como para los veteranos. Lo que logré durante mis años en la industria es un mejor entendimiento sobre cómo balancear estas cosas. Cuándo se justifica la complejidad y cuando no. Recuerdo con frecuencia un comentario de un amigo sobre el compilador de Go creado por Ken Thompson: este compilador es rápido porque no hace demasiado, el código es muy simple.

Resulta que, al igual es que más fácil escribir un artículo largo que escribir uno breve que señale lo mismo de manera concisa, es difícil escribir software que sea sencillo y breve.

Esto se puede ver con facilidad en el diseño de lenguajes de programación, los lenguajes nuevos suelen tener un montón de características, mientras muy pocos logran tener la simpleza y claridad de C.

En los programas de hoy en día, se suele pensar más en la cantidad de objetos que están involucrados que en otra cosa. En los sistemas distribuidos pasa lo mismo, solo que se piensa en cuantas piezas móviles hay.

Otra palabra para este problema es “inteligencia”. Esto se decía otro de los hackers de C: “Depurar un programa es el doble de difícil que escribir el código en primer lugar. Después de todo, si escribes el código lo más “inteligente” que puedas, estás, por definición, condenándote a no poder depurar ese programa, ya que no serás doblemente inteligente al momento de depurarlo.”

¿Qué ayuda?, me pregunto si esto se reduce solamente a la experiencia: haber sido mordido por tantos proyectos donde alguien pensó que la meta-programación era lo mejor y cosas similares.

Encontré que tener objetivos específicos para evaluar el código nuevo es de mucha ayuda. Es más fácil rechazar código nuevo si puedes decir algo cómo “Esto no ayuda a resolver nuestro objetivo inicial del proyecto”.

Dentro de Google usamos una plantilla para describir el diseño de los proyectos nuevos, en esa plantilla tenemos una sección llamada “no-objetivos”, donde se enumeran extensiones o mejoras razonables al proyecto que se intentarán evitar.

Irónicamente, encontré que usar las herramientas menos sofisticadas pueden ayudar con la complejidad. Es difícil escribir un programa complicado en C porque no puede hacer demasiado. Los programas en C suelen tener un montón de arrays porque es todo lo que tienes, y eso está bíen, porque los datos ocupan poco lugar, los accesos a los elementos son directos, la información está alocada en la misma página de memoria, etc. Sin embargo, nunca recomendaría usar una herramienta rudimentaria porque sí, en lugar de eso, mi lección ha sido: “Escribe código python como si fuera C.”