Hace años, pero también años después de fundar Lokad, me di cuenta de que ninguna aplicación única podría ofrecer algo cercano a la excelencia en lo que respecta a la optimización de la cadena de suministro. Hicimos todo lo posible, pero no fue suficiente. No importaba cuántas características agregáramos a las primeras versiones de Lokad, cada nuevo cliente parecía desesperadamente diferente a todos los anteriores que habíamos logrado cubrir hasta ahora. Los desafíos de la gestión de la cadena de suministro son simplemente demasiado diversos y caóticos para encajar en una cantidad “sana” de menús, botones y opciones.

Una serpiente de pitón, sin relación con Python, el lenguaje de programación.

De hecho, la mayoría de nuestros competidores reconocen esta situación y optaron por construir productos de software con una cantidad “insana” de menús, botones y opciones, todo esto como un intento desesperado de hacer frente a “todos” los desafíos de la cadena de suministro. Desafortunadamente, este camino conduce a monstruosidades de software que se convierten en fracasos espectaculares cuando se implementan a gran escala. Me refiero a este antipatrón como el Horror No Euclidiano.

Así, enfrentándonos a una clase de problemas, es decir, los desafíos de la cadena de suministro, que simplemente no podían resolverse con una única aplicación, comenzamos, en parte accidentalmente1, a abordar el meta-problema: cómo entregar aplicaciones “hechas a la medida” donde cada aplicación estaría dedicada a la resolución de un solo problema para una situación determinada, por ejemplo, la optimización de reabastecimiento para una empresa específica.

Entregar software hecho a medida para empresas no es algo nuevo. La industria del software comenzó de esa manera en los años 60 y luego evolucionó durante los años 80 hacia el modelo dominante de empaquetado que conocemos hoy en día. Como regla general, el software hecho a medida tiende a tener muchas propiedades indeseables en comparación con el software empaquetado: mayores inversiones iniciales, configuraciones prolongadas, mayores costos de mantenimiento, mayores riesgos, etc.

Sin embargo, la experiencia que había adquirido durante los primeros años de Lokad indicaba que, en lo que respecta a la optimización de la cadena de suministro, el software hecho a medida tenía una ventaja clave: realmente entregaba resultados excelentes. De hecho, mientras que nuestra aplicación original entregaba, en el mejor de los casos, resultados aceptables2, sin importar cuán precisas fueran las previsiones, esos prototipos a menudo lograban resultados excelentes. Además, el único truco involucrado era la especialización extrema de la pieza de software destinada al problema en cuestión.

Después de agotar lo que parecían ser todas las alternativas, llegamos a la conclusión de que entregar aplicaciones hechas a medida era la única opción. Sin embargo, la escalabilidad; cómo entregar muchas aplicaciones, y la mantenibilidad; cómo mantener los costos de mantenimiento bajo control, eran dos preocupaciones fundamentales. En primer lugar, tuvimos que elegir un lenguaje de programación. En ese momento, consideramos muchas opciones: R, Python, JavaScript, Lua, C#, … y desarrollar nuestro propio lenguaje de programación específico del dominio (DSL), que más tarde se conocería como Envision. Discutir los pros y los contras de todas esas opciones sería algo tedioso3, por lo tanto, con el fin de mantener la claridad, la discusión se centró en la elección entre Python y Envision; siendo Python el competidor más fuerte frente al desarrollo de nuestro propio DSL.

Python era atractivo debido a su simplicidad y a todo su rico ecosistema de bibliotecas de terceros, especialmente en el área de aprendizaje automático4. También era una opción de bajo costo para Lokad: como Python, y prácticamente todas sus bibliotecas populares, son de código abierto, simplemente habríamos empaquetado un subconjunto limitado de Python, seleccionando algunas docenas de paquetes específicos, y listo. La mayor parte del trabajo para Lokad se habría centrado en ofrecer una experiencia de PaaS alrededor de Python al estilo de Heroku, pero adaptada lo más posible a los desafíos de la cadena de suministro.

Sin embargo, aquí hay una prueba de fuego que consideramos: ¿era razonable esperar que un analista de negocios, más tarde conocido como un científico de la cadena de suministro, que trabajara 1 día a la semana durante 6 meses, pudiera entregar una aplicación de calidad de producción para resolver un desafío crítico de la cadena de suministro, como el reabastecimiento, para una empresa de $10M? Al analizar la opción de Python, estaba claro que nunca podríamos acercarnos siquiera a ese nivel de eficiencia operativa.

En primer lugar, Python requiere ingenieros de software. De hecho, Python, al igual que cualquier lenguaje de programación completo, expone toneladas de complejidades técnicas a quien escribe código en Python. Si bien el papel del científico de la cadena de suministro se formalizó más adelante, tuvimos la intuición desde el principio de que, incluso considerando personas talentosas y inteligentes, esperar que fueran expertos tanto en ingeniería de la cadena de suministro como en ingeniería de software era demasiado. Necesitábamos capacidades programáticas accesibles a un amplio espectro de personas con mentalidad técnica, no solo a ingenieros de software profesionales.

Por lo tanto, creamos Envision como un lenguaje para eliminar clases enteras de problemas técnicos que son inevitables con Python. Por ejemplo:

  • Los objetos pueden ser nulos, las fechas pueden ser absurdamente antiguas o futuras, NaN puede propagarse felizmente a través de su canal de datos, las cadenas pueden volverse absurdamente grandes… En la cadena de suministro, estas “características” no son más que problemas esperando a ocurrir.
  • Los elementos orientados a objetos (es decir, las clases) están garantizados para ser mal utilizados5, y lo mismo se puede decir acerca de las excepciones personalizadas o las expresiones regulares. La mera presencia de esos elementos es, en el mejor de los casos, una distracción poco saludable.
  • Múltiples operaciones básicas como el análisis de archivos tabulares dispares (incluidas las hojas de cálculo de Excel) no forman parte del lenguaje y requieren lidiar con muchos paquetes dispares, cada uno con sus propias complejidades técnicas.

Ninguna de estas clases de problemas técnicos se puede eliminar de Python sin perjudicar al propio lenguaje. Envision, como lenguaje de programación, es accesible a especialistas en cadena de suministro (en lugar de especialistas en software) solo debido a su enfoque extremadamente preciso en problemas de optimización predictiva de la cadena de suministro.

Piensa en la última vez que tuviste que realizar cálculos con una hoja de cálculo de Excel, y imagínate dictando todos los cambios que hiciste en esta hoja de Excel por teléfono sin poder ver la hoja de Excel por ti mismo. Así es como se ve una iniciativa de optimización de la cadena de suministro impulsada por profesionales, pero implementada por ingenieros de software (no especialistas en cadena de suministro). Las empresas gastan una enorme cantidad de tiempo tratando de transmitir lo que quieren a TI, y TI gasta una enorme cantidad de tiempo tratando de entender lo que la empresa quiere. Después de una década de experiencia en Lokad, observo que confiar en desarrolladores de software que no son especialistas en cadena de suministro para llevar a cabo una iniciativa de optimización de supply chain quantitativa multiplica los costos al menos por un factor de 5, sin importar cuán ágil y talentoso pueda ser el equipo de software.

En segundo lugar, los costos de mantenimiento de los prototipos apresurados de Python se disparan. Fuera de la industria del software, pocas personas se dan cuenta de que la ingeniería de software6 se trata principalmente de mantener los costos de mantenimiento bajo control. Sin embargo, resolver problemas de optimización de la cadena de suministro es un proceso complicado: los datos de muchos sistemas (poco) confiables deben ser canalizados de manera confiable, los procesos imperfectos y en constante cambio deben ser documentados y modelizados, las métricas de optimización reflejan una estrategia empresarial en constante cambio, etc. Como resultado, cualquier pieza de software que se escriba para ofrecer la optimización de la cadena de suministro siempre incorpora una gran dosis de complejidad específica del dominio, simplemente para hacer frente a lo que el mundo nos está presentando.

Sin embargo, el tiempo es esencial. No tiene sentido tener el plan perfecto para el plan de producción del año pasado. Como regla general, es seguro asumir que el día en que el prototipo de software comienza a funcionar, se moverá a producción en cuestión de semanas, sin importar si el prototipo está bien o mal escrito.

Esperar que la alta dirección apruebe un retraso de 6 meses para reescribir el prototipo y hacerlo apto para producción desde una perspectiva de mantenimiento es un pensamiento ilusorio. Sin embargo, poner un prototipo apresurado de Python en producción es la receta para tener costos de mantenimiento épicos, luchando una batalla cuesta arriba con una corriente interminable de errores que necesitarán ser parchados las 24 horas del día, los 7 días de la semana.

Por lo tanto, la única forma práctica de mantener la producción en buen estado es escribir el prototipo con un lenguaje de programación que garantice un alto grado de corrección por diseño. Por ejemplo, a diferencia de Python, Envision ofrece:

  • Tiempo de ejecución finito garantizado en tiempo de compilación: cuando se procesan múltiples terabytes de datos, se vuelve muy tedioso esperar horas antes de darse cuenta de que un cálculo simplemente nunca va a terminar.
  • Consumo de memoria acotado garantizado en tiempo de compilación: lidiar con errores de falta de memoria en el lote de producción nocturno no es divertido y, en la práctica, interrumpe gravemente las operaciones.
  • Lecturas y escrituras atómicas: Envision evita, por diseño, las lecturas y escrituras concurrentes dentro del sistema de archivos, incluso cuando los archivos se están enviando a través de FTP mientras los scripts se están ejecutando. El sistema de archivos que respalda a Envision es prácticamente un Git hecho a la medida para archivos planos gigantescos. Sin una adecuada versión de los datos, muchos errores se convierten en heisenbugs: cuando alguien profundiza en el problema, los datos se han actualizado y el problema ya no se puede replicar.
  • Ejecución escalable en un cloud de recursos informáticos, eliminando todos los obstáculos de paralelización que son inevitables tan pronto como los datos superan algunas decenas de gigabytes.

Los lenguajes de programación genéricos ofrecen poca corrección por diseño; y Python, inclinándose hacia el espectro de enlace tardío, ofrece excesivamente poco en esta área. Incluso al considerar mejores alternativas, desde la perspectiva de la corrección por diseño, como Rust, esas alternativas están lejos de ser satisfactorias para la optimización de la cadena de suministro.

Aquí hay algunas áreas más en las que Envision destaca de formas que simplemente no son accesibles en Python:

Defensa en profundidad: Tan pronto como alguien comienza a escribir código en su organización, a menos que se tomen precauciones muy especiales7, su código se convierte en una responsabilidad inmediata desde una perspectiva de seguridad informática. A través de Python, es posible hacer cualquier cosa en la máquina que ejecuta el script de Python. Aislar adecuadamente Python en la práctica es un problema diabólicamente complicado. En particular, cualquier cadena producida por el script de Python es un vector de inyección potencial. Si bien las inyecciones de SQL son notorias, (demasiado) pocas personas se dan cuenta de que incluso los archivos de texto plano simples como CSV son vulnerables a ataques de inyección. Envision ofrece un grado de seguridad que simplemente no se puede replicar con Python. Las violaciones de datos están en aumento, esparcir fragmentos de Python por todas partes no va a hacer ningún bien a la seguridad informática.

Rendimiento transparente: Si un programa es demasiado lento para ejecutarse, entonces este programa ni siquiera debería compilar en primer lugar8. Si un programa se hace una línea más corta, entonces el programa debería ejecutarse más rápido. Si solo se cambia una línea, solo esta línea debería volver a calcularse9 al volver a ejecutar el programa sobre los mismos datos. Al compilar, el compilador no debería apuntar a ninguna máquina en particular, sino a un conjunto de recursos informáticos en la nube, ofreciendo paralelización automática basada en datos. Envision avanza mucho hacia la entrega de todas estas propiedades de forma predeterminada sin ningún esfuerzo de codificación. En contraste, se requiere un uso masivo de bibliotecas especializadas en Python para comenzar a aproximar tales propiedades.

Actualización transparente: El estado del arte es un objetivo en constante movimiento en lo que respecta al software. En 2010, el mejor conjunto de herramientas de aprendizaje automático era SciPy (arguablemente). En 2013, fue scikit. En 2016, fue Tensorflow. En 2017, fue Keras. En 2019, fue PyTorch. Existe un dicho en ingeniería de software que dice que puedes determinar el año de nacimiento de cualquier proyecto de software al observar su conjunto de software y sus dependencias. De hecho, tan pronto como implementes tus propios scripts de Python, incorporarás múltiples dependencias que pueden no envejecer bien. En contraste, con Envision, estamos aprovechando extensamente las reescrituras de código automatizadas10, para mantener los scripts “heredados” actualizados con un lenguaje en constante cambio.

Stack empaquetado: Los scripts de Python no pueden vivir en el vacío11. El código debe ser versionado (por ejemplo, Git) con derechos de acceso (por ejemplo, GitHub). Necesitan un entorno en el que ejecutarse que no sea tu máquina (por ejemplo, una máquina virtual de Linux en la nube). Se necesita un planificador para orquestar el flujo de datos (por ejemplo, AirFlow). Se necesita una capa de almacenamiento columnar distribuida para la preparación de datos (por ejemplo, Spark). Se necesita un conjunto de herramientas de aprendizaje automático para el análisis predictivo (por ejemplo, TensorFlow). Se necesita un conjunto de herramientas de optimización para resolver problemas combinatorios de la cadena de suministro (por ejemplo, GLPK). Los resultados en bruto deben ser expuestos en algún lugar para su posterior consumo (por ejemplo, un servidor SFTP). Los profesionales de la cadena de suministro deben poder monitorear lo que está sucediendo (por ejemplo, una interfaz de usuario web). Los derechos de acceso deben ser aplicados (por ejemplo, Active Directory), etc. Envision simplifica todo esto en una sola meta-aplicación, eliminando la carga de ensamblar docenas de piezas de software para entregar incluso la aplicación más básica.

Luego, aunque es un excelente lenguaje, Python no está exento de críticas:

  • El rendimiento de cálculo es malo, y es una batalla cuesta arriba canalizar cada cálculo a través de la biblioteca correcta (por ejemplo, NumPy) para evitar obtener un rendimiento terriblemente malo en tareas de procesamiento de datos. Además, el uso de múltiples bibliotecas tiende a crear mucha fricción cuando los datos deben ser transferidos de una a otra.
  • El rendimiento de la memoria también es malo, y en particular, la recolección de basura por recuento de referencias de Python está desactualizada, y todos los lenguajes de programación más recientes como Java, C# o JavaScript utilizan el rastreo en su lugar. Esto es perjudicial cuando se trata de tareas intensivas de memoria con grandes volúmenes de datos.
  • La gestión de paquetes en Python ha sido un desastre durante mucho tiempo, y se necesita un especialista en paquetes para hacerlo bien. Además, este problema se ha visto agravado por actualizaciones de lenguaje con mucha fricción.
  • La mayoría de las (pocas) comprobaciones de corrección solo ocurren en tiempo de ejecución, cuando se ejecuta el programa, lo que es una fuente de frustración interminable cuando se trata de procesamiento de datos. Los problemas obvios solo se manifiestan después de varios minutos de ejecución, lo que reduce la productividad.

En conclusión, aunque Python es increíble (lo es), no es una respuesta satisfactoria para la optimización de la cadena de suministro. Construir y mantener una aplicación de aprendizaje automático de calidad de producción en Python es muy posible, pero los costos son significativos, y a menos que tu empresa esté preparada para tener al menos un pequeño equipo de ingeniería de software dedicado al mantenimiento de esta aplicación, todo el proyecto no va a ofrecer resultados satisfactorios para tu cadena de suministro.

Desarrollar Envision, un lenguaje de programación específico del dominio dedicado a la optimización predictiva de la cadena de suministro, no fue nuestra primera opción. Ni siquiera fue nuestra décima opción. Fue más como la única solución que funcionaba que tuvimos después de agotar una larga lista de alternativas más convencionales durante cinco años. Siete años después y muchas empresas clientes después, cada nuevo cliente sigue logrando sorprendernos, de una forma u otra, con un nuevo giro en su cadena de suministro, que nunca hubiéramos logrado abarcar con un enfoque de software empresarial clásico. Se necesitaba programabilidad, pero Python no era la solución que necesitábamos.


  1. En 2013, todavía tenía la impresión de que era posible entregar una aplicación satisfactoria para la optimización de la cadena de suministro. De hecho, fue el enfrentamiento con desafíos de precios lo que de alguna manera nos obligó y llevó a Lokad por el camino de construir su propio lenguaje específico del dominio. Este lenguaje estaba destinado solo a la optimización de precios al principio, pero rápidamente nos dimos cuenta de que este enfoque también era exactamente lo que se necesitaba para la optimización de la cadena de suministro. ↩︎

  2. La idea de que ofrecer una precisión de pronóstico superior conduciría, por sí sola, a un rendimiento superior de la cadena de suministro fue probablemente una de las mayores concepciones erróneas que tuve al fundar Lokad. Mira este episodio de Lokad TV para obtener una perspectiva más sensata sobre este tema. ↩︎

  3. La mayoría de los problemas que identificamos con Python no tenían nada que ver con Python en sí, que es un gran lenguaje de programación, sino simplemente con el hecho de que Python es un lenguaje de programación genérico↩︎

  4. En 2013, Python aún no había alcanzado la dominancia que obtuvo en los pocos años siguientes en el campo del aprendizaje automático, R todavía era un fuerte competidor, sin embargo, SciPy y NumPy, dos excelentes bibliotecas, ya existían y prosperaban en ese momento. ↩︎

  5. Mira esta excelente charla Stop Writing Classes de Pycon 2012. Incluso los ingenieros de software experimentados tienden a equivocarse. ↩︎

  6. Ingeniería de software en contraposición a ciencias de la computación. Lo primero se trata de garantizar sistemas de producción, mientras que lo segundo se trata de resolver problemas difíciles, como descubrir algoritmos más rápidos. ↩︎

  7. Desafortunadamente, en cuestiones de seguridad del código, no hay sustituto para las revisiones sistemáticas por parte de los compañeros del código. ↩︎

  8. Debido al problema de detención, el lector atento podría inferir que Envision no es un lenguaje Turing completo. De hecho, Envision no lo es. ↩︎

  9. Envision se basa en la diferencia entre los gráficos de cálculo e intenta minimizar la cantidad de recalculaciones entre cambios incrementales para permitir una prototipado muy rápido sobre grandes conjuntos de datos. Sin embargo, dependiendo de la situación, cambiar una sola línea puede requerir recalcular todo el script. ↩︎

  10. Las reescrituras automáticas de código son extremadamente difíciles para un lenguaje de programación genérico. A menos que el lenguaje de programación y toda su biblioteca estándar hayan sido diseñados precisamente con este requisito en mente, las herramientas de actualización automatizada tienen poco efecto en la práctica. Al diseñar Envision, sabíamos que íbamos a cometer muchos errores (y así fue), por lo que prestamos mucha atención para asegurarnos de que el lenguaje fuera especialmente adecuado para reescrituras automáticas. Hasta la fecha, hemos realizado más de 100 reescrituras incrementales desde el inicio de Envision. ↩︎

  11. Irónicamente, “Baterías incluidas” es uno de los lemas de Python. Sin embargo, la cantidad de pegamento que se necesita para unir todos los elementos necesarios para construir una aplicación destinada a la optimización predictiva de la cadena de suministro es desalentadora. ↩︎