Un fenómeno que me he encontrado numerosas veces a lo largo de mi carrera es la situación en la que la cantidad de beneficio que reporta una cantidad fija de trabajo disminuye a lo largo del tiempo. Al principio, poco trabajo es capaz de generar grandes beneficios. Conforme pasa el tiempo, la misma cantidad de trabajo cada vez da menos beneficios. Hacia el final, hace falta hacer muchísimo trabajo para conseguir incrementos pequeños. Estoy siendo abstracto con la definición de "beneficio" aposta para poder aplicar el fenómeno a muchas situaciones. Al principio me sorprendía que el mismo patrón se repitiera en tantos lugares. Con el tiempo me he dado cuenta de que esto es simplemente una consecuencia natural de cómo trabajamos.
A los humanos nos encantan las correlaciones lineales. Si una unidad de trabajo nos da X beneficios, esperamos que dos unidades de trabajo nos den 2X beneficios y que 10 unidades de trabajo nos den 10X beneficios. El cerebro está preparado para entender la mayoría de fenómenos de manera lineal y de hecho se nos da especialmente mal entender de manera intuitiva fenómenos con formas muy distintas a la lineal, como el crecimiento exponencial por ejemplo. O los rendimientos decrecientes. Por eso, desarrollar una intuición en torno a este fenómeno puede no ser obvio.
Por lo general imaginamos el trabajo como algo incontable, como el agua o el arroz. Lo medimos en horas, por ejemplo. Sin embargo, podemos pensar en el trabajo en forma de tareas discretas. Pasos concretos que podemos hacer que nos llevan un tiempo finito y generan algún beneficio concreto. Ahora podemos ver que no todos estos pasos tardan lo mismo en hacerse ni nos benefician de la misma manera. Algunos son más fáciles que otros. Algunos son más eficaces que otros. Esto nos permite ordenar todas estas tareas que podemos hacer en orden de utilidad, porque queremos hacer primero aquellas que podamos tardar muy poco en hacer o que vayan a tener un impacto muy grande. De hecho, la métrica por la que ordenamos es beneficio dividido por coste. Sí, esto es literalmente
el problema de la mochila (
)
. Esta estrategia de priorización no es necesariamente algo hecho de manera consciente y sistemática. Todos hacemos de manera natural primero aquello que vaya a tener un impacto mayor por menos coste. Es un comportamiento natural.
Ahora bien, ¿qué va a pasar cuando afrontemos nuestro problema de esta manera? Comenzaremos haciendo las tareas que más beneficio nos dan por el menor coste (en este caso pensaremos en el coste como horas de trabajo). Entonces, al principio el proyecto avanzará muy rápido porque estamos haciendo primero las cosas que cuestan menos y aportan más. Pero claro, las tareas fáciles y/o de gran impacto se acaban. Si seguimos trabajando toca hacer tareas que cuestan más o que aportan menos. ¿Por qué? Porque las fáciles y buenas ya están hechas. Así que el progreso se ralentiza porque se está dedicando el tiempo a tareas más difíciles o menos valiosas. Si se sigue trabajando más y más en algún momento se acabará llegando a rascar el socarrat de los quehaceres, las tareas más ingratas por difíciles o por poco relevantes. No hay otras que hacer porque las otras ya están hechas.
Imaginemos una mina. Puede ser de carbón, de hierro, de oro o de tu cosa favorita que se saque de debajo de la tierra. El momento de mayor productividad de una mina siempre es al principio, cuando hay vetas grandes y fácilmente accesibles de mineral. Obviamente, la extracción empieza por ellas, produciendo pingües beneficios en poco tiempo. Con el tiempo esas vetas se acaban y toca buscar otras que a lo mejor están más recónditas o tienen un porcentaje menor de mineral y requieren de un proceso mayor para extraer y refinar. Como siempre se está extrayendo la cosa que en ese momento es más fácil, por definición la tarea se vuelve cada vez más difícil. Ninguna mina se excava del todo. Siempre se llega antes a un punto en el que no es rentable seguir sacando más porque el coste de hacerlo (en sueldos de mineros y coste de operar la maquinaria) es mayor que el dinero que se obtendría de vender lo extraído.
Otro ejemplo. A principios del siglo XX la rentabilidad energética de extraer un barril de petróleo era de 100 a 1. Es decir, por cada unidad de energía (en joules, por ejemplo) que se invertía en extraer petróleo, se obtenían 100. A principios del siglo XXI, esa proporción se había vuelto de 10 a 1. Es decir, 10 veces menos eficiente. Sería ingenuo pensar que a lo largo de esos 100 años el conocimiento de la humanidad sobre la extracción de petróleo se ha ido perdiendo y que ahora lo estemos haciendo peor que antes. Al revés, tanto el conocimiento como la tecnología han progresado muchísimo. Lo que pasa es que a principios del siglo XX uno podía cavar una pala en cualquier secarral de Texas y que saliera un enorme chorro negro hacia el cielo, como en la película
(Paul Thomas Anderson, 2007). Hoy en día, hace ya muchos años que ese petróleo fácil se acabó. El petróleo que se extrae hoy se saca del fondo del mar con grandes plataformas petrolíferas como la Deepwater Horizon, de debajo del hielo de la tundra, de las arenas bituminosas de Alberta en Canadá y de otroz pozos difíciles de acceder. Nos encantaría poder seguir sacando petróleo fácil como hacía Rockefeller pero es que ya no queda.
En muchos aspectos del desarrollo de software sucede algo similar. Dos muy claros son la optimización y arreglar bugs. Un programa en el que nunca se ha prestado atención al rendimiento tiene por lo general grandes pesimizaciones esperando a ser quitadas. Estos suelen ser cambios pequeños, como cambiar una estructura de datos o un algoritmo concreto, que hacen que de repente el programa vaya varias veces más rápido. Conforme este tipo de pesimizaciones van desapareciendo, el gráfico de rendimiento cada vez se vuelve más plano. No hay ninguna parte del programa que sea obviamente el problema y cualquier cosa en la que se trabaje supondrá solamente una mejora marginal ya que afectará a una parte relativamente pequeña del programa. Los cambios grandes, como cambiar las estructuras de datos centrales para optimizar accesos a memoria, suponen mucho trabajo porque requieren cambios por todo el programa y a menudo puden dar mejoras de un pequeño porcentaje pero rara vez van a suponer una diferencia de orden de magnitud. Paralelizar también es una cosa que sólo se puede hacer una vez. Que un programa pase de ejecutarse en serie a hacerlo en paralelo puede hacer que vaya 8, 16 o 32 veces más rápido, según las prestaciones de la máquina en la que se ejecuta, pero es una carta que sólo se puede jugar una vez. Después, cuando el programa ya se ejecuta en paralelo, no hay otro cambio similar que vaya a conseguir un nivel parecido de optimización.
Al arreglar bugs sucede lo mismo. Se empieza arreglando los que son más fáciles o los que tienen un impacto mayor porque afectan a mucha gente o molestan mucho. Conforme esos van desapareciendo, cada vez quedan más bugs raros que o no salen mucho o suponen una molestia menor, o ambas. Si los videojuegos AAA cada vez salen con más bugs en parte es por esto. Por supuesto, son muchos más los bugs que los jugadores no ven porque se han arreglado antes de salir, pero por lo general suele llegar un punto en el que la empresa considera que lo que ganará el programa al librarse de los bugs que quedan no vale el sueldo que van a cobrar los programadores encargados de hacer el trabajo.
En general, los retornos decrecientes no son más que una consecuencia natural de la forma en la que trabajamos. Hacemos primero las tareas que nos reportan mayor beneficio por el menor coste hasta que se acaban. Cuando se acaban, las tareas que quedan por hacer van a costar más y aportar menos porque las otras, las que eran más fáciles y mejores, ya están hechas. Cuando uno se fija, resulta que este patrón está en todas partes.