00:05 Introducción
02:50 Dos ilusiones
09:09 Un pipeline de compilador
14:23 La historia hasta ahora
18:49 Conocimiento de embarque
19:40 Diseño de lenguaje
23:52 El futuro
30:35 El pasado
35:57 Elegir las batallas
39:45 Gramáticas 1/3
42:41 Gramáticas 2/3
49:02 Gramáticas 3/3
53:02 Análisis estático 1/2
58:50 Análisis estático 2/2
01:04:55 Sistema de tipos
01:11:59 Internos del compilador
01:27:48 Entorno de ejecución
01:33:57 Conclusión
01:36:33 Próxima clase y preguntas del público

Descripción

La mayoría de las cadenas de suministro todavía se ejecutan a través de hojas de cálculo (es decir, Excel), mientras que los sistemas empresariales han estado en funcionamiento durante uno, dos, a veces tres décadas, supuestamente para reemplazarlos. De hecho, las hojas de cálculo ofrecen una expresividad programática accesible, mientras que esos sistemas generalmente no lo hacen. Más en general, desde la década de 1960, ha habido un desarrollo conjunto constante de la industria del software en su conjunto y de sus lenguajes de programación. Existen pruebas de que la próxima etapa del rendimiento de la cadena de suministro estará impulsada en gran medida por el desarrollo y la adopción de lenguajes de programación, o más bien de entornos programables.

Transcripción completa

Slide 1

Bienvenidos a esta serie de clases sobre cadena de suministro. Soy Joannes Vermorel y hoy presentaré “Lenguajes y Compiladores para la Cadena de Suministro”. No recuerdo haber visto nunca compiladores discutidos en ningún libro de cadena de suministro, y sin embargo, el tema es de suma importancia. Hemos visto en el primer capítulo de esta serie, en la clase titulada “Entrega Orientada al Producto”, que la programación es la clave para capitalizar el tiempo invertido por los expertos en cadena de suministro. Sin programación, no podemos capitalizar su tiempo y tratamos a los expertos en cadena de suministro como prescindibles.

Además, en este cuarto capítulo, a través de las dos clases anteriores “Optimización Matemática para la Cadena de Suministro” y “Aprendizaje Automático para la Cadena de Suministro”, hemos visto que estos dos campos -optimización y aprendizaje- se han vuelto impulsados por paradigmas de programación durante la última década, en lugar de seguir siendo un conjunto de algoritmos y modelos como solía ser en el pasado. Todos estos elementos señalan la importancia primordial de los lenguajes de programación y, por lo tanto, plantean la pregunta de un lenguaje de programación y un compilador diseñados para abordar los desafíos de la cadena de suministro.

El propósito de esta clase es desmitificar el diseño de un lenguaje de programación destinado a fines de cadena de suministro. Es probable que su empresa nunca vaya a diseñar un lenguaje de programación propio. Sin embargo, tener una idea sobre el tema es fundamental para poder evaluar la adecuación de las herramientas que tiene y evaluar la adecuación de las herramientas que pretende adquirir para abordar los desafíos de la cadena de suministro que enfrenta su empresa. Además, esta clase también debería ayudarlo a evitar algunos de los grandes errores que las personas que no tienen ningún conocimiento en este tema tienden a cometer en esta área.

Slide 2

Comencemos desmintiendo dos ilusiones que han prevalecido en los círculos del software empresarial durante las últimas tres décadas aproximadamente. La primera es la ilusión de la “programación de Lego”, donde se piensa que la programación puede ser completamente obviada. De hecho, la programación es difícil y siempre hay proveedores que prometen que a través de su producto y su tecnología fantástica, la programación se puede convertir en una experiencia visual accesible para cualquier persona, eliminando por completo toda la dificultad de la programación en sí, de modo que la experiencia se convierte esencialmente en algo similar a simplemente armar Lego, algo que incluso un niño puede hacer.

Esto se ha intentado innumerables veces en las últimas dos décadas y siempre ha fracasado inevitablemente. En el mejor de los casos, los productos que pretendían ofrecer una experiencia visual se convirtieron en lenguajes de programación regulares que no son especialmente más fáciles de dominar en comparación con otros lenguajes de programación. Esta es, por cierto, anecdóticamente la razón por la cual, por ejemplo, en la serie de productos de Microsoft, existen las series “Visual”, como Visual Basic for Application y Visual Studio. Todos esos productos visuales se introdujeron en los años 90 con la esperanza de convertir la programación en una experiencia puramente visual con diseñadores donde todo sería simplemente arrastrar y soltar. La realidad es que todas esas herramientas finalmente lograron un grado muy significativo de éxito, pero hoy en día son solo lenguajes de programación bastante regulares. Queda muy poco de las partes visuales que estaban en el inicio de esos productos.

El enfoque de Lego fracasó porque fundamentalmente, el cuello de botella no es el obstáculo de la sintaxis de programación. Este es un obstáculo, pero es mínimo, especialmente en comparación con el dominio de los conceptos que están involucrados cuando se desea implementar cualquier tipo de automatización sofisticada. Su mente se convierte en el cuello de botella y su comprensión de los conceptos que están en juego es mucho más significativa que la sintaxis.

La segunda ilusión es la ilusión de la “tecnología de Star Wars”, que consiste en pensar que es fácil conectar y usar piezas de tecnología fantásticas. Esta ilusión es muy atractiva tanto para los proveedores como para los proyectos internos. Esencialmente, se vuelve muy tentador decir que hay esta base de datos NoSQL fantástica que podemos simplemente implementar, o hay esta pila de deep learning fantástica que podemos adoptar, o esta base de datos de gráficos, o este marco activo distribuido, etc. El problema con este enfoque es que trata la tecnología como se trata en Star Wars. Cuando tienes una mano mecánica, el héroe simplemente puede obtener la mano mecánica y funciona. Pero en realidad, los problemas de integración dominan.

Star Wars pasa por alto el hecho de que habría una serie de problemas: primero, necesitarías antibióticos, luego una larga reeducación de la mano para poder usarla. También necesitarías un programa de mantenimiento para la mano porque es mecánica, y ¿qué pasa con la fuente de energía, etc.? Todos estos problemas se pasan por alto. Simplemente conectas la fantástica pieza de tecnología y funciona. Esto no es así en la realidad. Los problemas de integración dominan y, por ejemplo, en las grandes empresas de software, la mayoría de los ingenieros de software no están trabajando en piezas de tecnología fantásticamente geniales. La mayor parte de la fuerza laboral de ingeniería de la gran mayoría de esos proveedores de software se dedica solo a la integración de todas las partes.

Cuando tienes módulos, componentes o aplicaciones, necesitas un pequeño ejército de ingenieros solo para unir todas esas cosas y lidiar con todos los problemas que surgen cuando intentas juntar esas cosas. Incluso una vez que has superado todos los obstáculos de integración, aún necesitas mucha fuerza laboral de ingeniería solo para lidiar con el hecho de que cuando modificas cualquier parte del sistema, tiendes a crear problemas en otras partes del sistema. Entonces necesitas esta fuerza laboral de ingeniería para solucionar esos problemas.

A propósito, como anécdota, otro problema que he presenciado con piezas geniales de tecnología es el efecto Dunning-Kruger que crea entre los ingenieros. Introduces una pieza genial de tecnología en tu stack y de repente los ingenieros, solo porque han comenzado a jugar con una pieza de tecnología que apenas entienden, piensan que de repente son expertos en IA o algo así. Ese es un caso típico del efecto Dunning-Kruger y está muy relacionado con la cantidad de piezas de tecnología geniales que insertas en tu solución. En conclusión, con esas dos ilusiones, vemos que realmente no podemos pasar por alto el problema de la programación. Tenemos que abordarlo de manera funcional, incluyendo las partes difíciles.

Slide 3

Ahora bien, dicho esto, lo interesante de los lenguajes de programación es que los proveedores de software empresarial siguen reinventando, accidentalmente, lenguajes de programación, y lo hacen todo el tiempo. De hecho, en la cadena de suministro, hay una necesidad feroz de configurabilidad. Como hemos visto en conferencias anteriores, el mundo de la cadena de suministro es diverso y los problemas son numerosos y variados. Por lo tanto, cuando tienes un producto de software de cadena de suministro, hay una necesidad extremadamente intensa de configurabilidad. Por cierto, configurar un software es típicamente un proyecto de varios meses y a veces de varios años. Esto se debe a que hay una gran cantidad de complejidad que se incluye en esta configuración.

La configuración de los ajustes a menudo es compleja, no solo botones o casillas de verificación. Puedes tener disparadores, fórmulas, bucles y todo tipo de bloques que van con eso. Rápidamente se sale de control y lo que obtienes a través de esos ajustes de configuración es un lenguaje de programación emergente. Sin embargo, dado que es un lenguaje de programación emergente, tiende a ser uno muy pobre.

La ingeniería de un lenguaje de programación real es una tarea de ingeniería bien establecida. Hay docenas de libros sobre las prácticas de ingeniería de un compilador de calidad de producción. Un compilador es un programa que convierte instrucciones, típicamente instrucciones de texto, en código de máquina o en una forma de instrucciones de nivel inferior. Siempre que haya un lenguaje de programación, hay un compilador involucrado. Por ejemplo, dentro de una hoja de cálculo de Excel, tienes fórmulas y Excel tiene su propio compilador para compilar esas fórmulas y ejecutarlas. Lo más probable es que toda la audiencia haya estado usando compiladores durante toda su vida profesional sin saberlo.

En el diagrama, puedes ver un pipeline típico, y este arquetipo se ajusta a la mayoría de los lenguajes de programación que probablemente hayas escuchado, como Python, JavaScript, Java y C#. Todos estos lenguajes tienen un pipeline esencialmente similar al que se describe aquí. En un pipeline de compilador, tienes una serie de transformaciones y en cada etapa del proceso, tienes una representación que representa todo el programa. La forma en que se diseña un compilador es tener una serie de transformaciones bien identificadas y en cada etapa del proceso, estás trabajando con todo el programa. Solo se representa de manera diferente.

La idea es que cada transformación es responsable de un conjunto de problemas bien especificado. Abordas esos problemas y luego pasas a la siguiente transformación que abordará otro aspecto del proceso. Por lo general, en cada etapa, te acercas al código a nivel de máquina. El compilador comienza con el script y comienza con transformaciones que están muy cerca de la sintaxis del lenguaje de programación de interés. Durante estas primeras transformaciones, un compilador típico capturará errores sintácticos que impiden que el compilador convierta un script que ni siquiera representa un programa válido en algo ejecutable. Volveremos a echar un vistazo más de cerca a un pipeline de compilador más adelante en esta conferencia.

Slide 4

Esta conferencia es la quinta conferencia del cuarto capítulo de esta serie. En el primer capítulo, presenté mis puntos de vista sobre la cadena de suministro tanto como campo de estudio como práctica. En el segundo capítulo, examiné las metodologías apropiadas para tratar las situaciones que se encuentran en la cadena de suministro. Como hemos visto, la mayoría de las situaciones de la cadena de suministro son bastante adversariales, por lo que necesitamos estrategias y metodologías que sean resilientes a los comportamientos adversarios de todas las partes dentro y fuera de las empresas.

El tercer capítulo está dedicado al personal de la cadena de suministro y se dedica por completo al estudio de los problemas de la cadena de suministro en sí. Debemos tener mucho cuidado de no enredar el problema que estamos descubriendo con el tipo de solución que podemos imaginar para abordar este problema. Esas son dos preocupaciones distintas: debemos separar el problema de la solución.

El cuarto y presente capítulo de esta serie de conferencias está dedicado a las ciencias auxiliares de la cadena de suministro. Estas ciencias auxiliares no son la cadena de suministro en sí, pero son muy útiles para la práctica de la cadena de suministro moderna. Actualmente estamos avanzando a través de la escalera de abstracciones. Comenzamos este capítulo con la física de la computación, luego con algoritmos, nos adentramos en el ámbito del software. Introdujimos la optimización matemática, que es de gran interés para la cadena de suministro y también resulta ser la base del aprendizaje automático.

Hoy, estamos presentando los lenguajes y compiladores, esenciales para implementar cualquier tipo de paradigma de programación. Si bien el tema de los lenguajes y compiladores puede sorprender a la audiencia, creo que en este punto no debería ser demasiado sorprendente. Hemos visto que la optimización matemática y el aprendizaje automático deben abordarse hoy en día a través de paradigmas de programación, lo que plantea la pregunta de cómo implementar esos paradigmas de programación. Eso nos lleva al diseño de un lenguaje de programación y su compilador de soporte, que es exactamente el tema de hoy.

Slide 5

Este es un resumen del resto de esta conferencia. Comenzaremos con observaciones de alto nivel sobre la historia y el mercado de los lenguajes de programación. Revisaremos industrias que representan, en mi opinión, tanto el futuro como el pasado de la cadena de suministro. Luego nos adentraremos gradualmente en el diseño de lenguajes de programación y compiladores, avanzando con preocupaciones de nivel inferior y las cuestiones técnicas involucradas en el diseño de un compilador.

Slide 6

Desde la década de 1950, se han desarrollado miles de lenguajes de programación. Las estimaciones varían, pero el número de lenguajes de programación que se han utilizado con fines de producción probablemente oscila entre mil y diez mil. Muchos de esos lenguajes son solo variaciones o parientes entre sí, a veces incluso solo el código base del compilador bifurcado en una dirección ligeramente diferente. Es notable que varias empresas de software empresarial muy grandes se expandieron bastante a través de la introducción de lenguajes de programación propios. Por ejemplo, SAP introdujo ABAP en 1983, Salesforce introdujo Apex en 2006 e incluso Microsoft comenzó antes de Windows al diseñar el Altair BASIC en 1975.

Históricamente, aquellos de ustedes en la audiencia lo suficientemente mayores como para recordar los años 90 pueden recordar que en ese momento los proveedores estaban promocionando lenguajes de programación de tercera y cuarta generación. La realidad es que había una serie bien identificada de generaciones: primera, segunda, tercera, cuarta, etc., que llevaba a la quinta, donde básicamente la comunidad dejó de contar en términos de generaciones. Durante las tres o cuatro primeras décadas, todos esos lenguajes de programación seguían una progresión agradable hacia niveles más altos de abstracción. Sin embargo, a fines de los años 90, ya había muchas más direcciones además de tener un mayor grado de abstracción, dependiendo del caso de uso.

La creación de un nuevo lenguaje de programación se ha hecho muchas veces. Es un campo de ingeniería bien establecido y existen libros enteros dedicados al tema desde un ángulo muy práctico. La ingeniería de un nuevo lenguaje de programación es una práctica mucho más fundamentada y predecible que, digamos, llevar a cabo un experimento de ciencia de datos. Existe una certeza casi absoluta de que obtendrás el resultado que deseas si estás haciendo la ingeniería adecuada, considerando lo que se conoce hoy y lo que está disponible como conocimiento.

Todo eso realmente plantea la pregunta: ¿qué pasa con un lenguaje de programación específicamente diseñado para fines de cadena de suministro? De hecho, puede haber un gran potencial en términos de productividad, confiabilidad e incluso rendimiento de la cadena de suministro.

Slide 7

Para abordar esta pregunta, debemos echar un vistazo al futuro. Afortunadamente para nosotros, la forma más sencilla de hacerlo es examinar una industria que ha estado consistentemente una década por delante de todos los demás durante las últimas tres décadas más o menos, y esa es la industria de los videojuegos. Esta es una industria muy grande en la actualidad, y solo para darte una idea de su magnitud, la industria de los videojuegos ahora representa dos tercios de la industria aeroespacial a nivel mundial en términos de tamaño comparativo, y está creciendo mucho más rápido que la industria aeroespacial. Dentro de una década, los videojuegos podrían ser incluso más grandes que la industria aeroespacial.

Lo interesante de la industria de los videojuegos es que tiene una estructura muy bien establecida. Primero, tenemos los motores de juego, siendo Unity y Unreal los dos líderes. Estos motores de juego cuentan con componentes de bajo nivel que son de interés para gráficos 3D refinados y superintensivos, y establecen el panorama para el nivel de infraestructura de tu código. Hay algunas empresas que diseñan productos muy complejos llamados motores de juego, y estos motores son utilizados por toda la industria.

A continuación, tenemos los estudios de desarrollo de juegos, que desarrollan el código del juego para cada juego en particular. El código del juego va a ser una base de código que normalmente es específica para el juego que se está desarrollando. El motor de juego requiere ingenieros de software muy especializados que tienen habilidades técnicas muy sólidas pero que no necesariamente saben mucho sobre juegos. El desarrollo del código del juego no es tan intensivo en términos de habilidades técnicas puras y en bruto. Sin embargo, los ingenieros de software que desarrollan el código del juego necesitan comprender el juego en el que están trabajando. El código del juego establece la plataforma para la mecánica del juego, pero no especifica los detalles más finos.

Esta tarea normalmente es gestionada por los diseñadores de juegos, que no son ingenieros de software, pero escriben código en los lenguajes de script que les son proporcionados por el equipo de ingeniería encargado del código del juego. Tenemos estas tres etapas: motores de juego, que involucran a ingenieros de software muy técnicos y especializados que crean bloques de construcción fundamentales; estudios de desarrollo, que tienen equipos de ingeniería, normalmente uno por juego, que desarrollan el juego como una plataforma para la mecánica del juego; y finalmente, diseñadores de juegos, que no son ingenieros de software pero son especialistas en juegos, que implementan el comportamiento que hará felices a los jugadores, los clientes al final de la cadena de producción.

Hoy en día, el código del juego se pone frecuentemente a disposición de los fanáticos, lo que significa que los diseñadores de juegos pueden escribir reglas y potencialmente modificar el juego, pero los fanáticos, que son simplemente consumidores regulares de los juegos, también pueden hacerlo. Hay algunas anécdotas interesantes en la industria. Por ejemplo, el juego Dota 2, que es increíblemente exitoso, comenzó como una modificación de un juego existente. La primera versión, simplemente llamada Dota, fue una modificación pura de la base de fanáticos del juego World of Warcraft 3. Se puede ver que este grado de configurabilidad y programabilidad a nivel de reglas de juego es muy extenso, porque fue posible, a partir de un juego comercial existente, World of Warcraft 3, crear un juego completamente nuevo, que luego se convirtió en un gran éxito comercial por sí mismo a través de la segunda versión. Ahora, esto es interesante, y podemos comenzar a pensar, al mirar la industria de los videojuegos, ¿qué significa esto para la industria de la cadena de suministro?

Bueno, podríamos pensar en qué tipo de paralelo podríamos establecer. Podríamos tener un motor de cadena de suministro que se encargue de las partes algorítmicas muy difíciles, la infraestructura de bajo nivel y los bloques de construcción tecnológicos fundamentales, como la optimización matemática y el aprendizaje automático. La idea es que, para cada cadena de suministro, se necesitaría un equipo de ingeniería para reunir todos los datos relevantes e integrar todo el panorama aplicativo.

Como primera etapa, necesitaríamos el equivalente a diseñadores de juegos, que serían especialistas en cadena de suministro. Estos especialistas no son ingenieros de software, pero son las personas que escribirán, a través de código simplificado, todas las reglas y mecánicas necesarias para implementar la optimización predictiva de interés para la cadena de suministro. La industria de los videojuegos proporciona un ejemplo vívido de lo que probablemente sucederá en el espacio de la cadena de suministro en la próxima década.

Slide 8

Hasta ahora, el enfoque de la industria de los videojuegos en la cadena de suministro sigue siendo ciencia ficción, excepto para algunas empresas. Creo que la mayoría de esas empresas resultan ser clientes de Lokad. Volviendo al tema de hoy, hemos visto en conferencias anteriores que Excel sigue siendo el lenguaje de programación número uno en esta industria. Por cierto, en términos de lenguaje de programación, Excel es un lenguaje de programación funcional reactivo, por lo que es incluso su propia clase.

Es posible que estés escuchando en estos días a proveedores que proponen mejorar las cadenas de suministro utilizando algún tipo de configuración de ciencia de datos. Sin embargo, mi observación casual durante la última década es que la gran mayoría de estas iniciativas han fracasado. Esto ya es pasado, y para entender por qué, debemos comenzar a mirar la lista de lenguajes de programación involucrados. Si observamos Excel, vemos que involucra esencialmente dos lenguajes de programación: fórmulas de Excel y VBA. Incluso VBA no es un requisito; puedes llegar lejos solo con búsquedas V en Excel. Típicamente, será solo un lenguaje de programación, y estará al alcance de los no ingenieros de software.

Por otro lado, la lista de lenguajes de programación necesarios para replicar las capacidades de Excel con una configuración de ciencia de datos es bastante extensa. Necesitaremos SQL y potencialmente varios dialectos de SQL para acceder a los datos. Necesitaremos Python para implementar la lógica principal. Sin embargo, Python por sí solo tiende a ser lento, por lo que es posible que necesites un sublenguaje como NumPy. En este punto, aún no estás haciendo nada en términos de aprendizaje automático u optimización matemática, por lo que para un análisis numérico verdaderamente hardcore, necesitarás algo más, otro lenguaje de programación propio, como PyTorch, por ejemplo. Ahora que tienes todos estos elementos, ya tienes bastantes piezas en movimiento, por lo que la configuración de la aplicación en sí será bastante compleja. Necesitarás una configuración, y esta configuración se escribirá con otro lenguaje de programación, como JSON o XML. Se podría argumentar que estos no son lenguajes de programación súper complejos, pero es algo más que agregar a la lista.

Lo que sucede cuando tienes tantas piezas en movimiento es que típicamente necesitas un sistema de compilación, algo que pueda ejecutar todos los compiladores y recetas mundanas necesarias para producir el software. Los sistemas de compilación tienen sus propios lenguajes. El enfoque tradicional es un lenguaje llamado Make, pero hay muchos otros. Además, dado que Excel puede mostrar resultados, necesitas una forma de mostrar cosas al usuario y visualizar cosas. Esto se hará con una combinación de JavaScript, HTML y CSS, lo que agrega más lenguajes a la lista.

En este punto, tenemos una larga lista de lenguajes de programación, y una configuración de producción real podría ser aún más compleja. Esto explica por qué la mayoría de las empresas que intentaron adoptar este flujo de trabajo de ciencia de datos durante la última década han fracasado abrumadoramente y se han quedado solo con Excel en la práctica. La razón es que implica dominar casi una docena de lenguajes de programación en lugar de solo uno, como en el caso de Excel. Ni siquiera hemos comenzado a abordar ninguno de los problemas reales de la cadena de suministro; solo hemos estado discutiendo las cuestiones técnicas que impiden comenzar a hacer algo.

Slide 9

Ahora, vamos a empezar a pensar en cómo sería un lenguaje de programación para la cadena de suministro. Primero, tenemos que decidir qué está dentro del lenguaje y qué pertenece al lenguaje como ciudadano de primera clase y qué pertenece a las bibliotecas. De hecho, con los lenguajes de programación, siempre es posible transferir capacidades a las bibliotecas. Por ejemplo, veamos el lenguaje de programación C. Se considera un lenguaje de programación bastante de bajo nivel y C no tiene un recolector de basura. Sin embargo, es factible utilizar un recolector de basura de terceros como una biblioteca en un programa en C. Debido a que la recolección de basura no es un ciudadano de primera clase en el lenguaje de programación C, la sintaxis tiende a ser relativamente verbosa y tediosa.

Para fines de la cadena de suministro, existen preocupaciones como la optimización matemática y el aprendizaje automático que generalmente se tratan como bibliotecas. Entonces, tenemos un lenguaje de programación y todas esas preocupaciones se transfieren esencialmente a bibliotecas de terceros. Sin embargo, si tuviéramos que diseñar un lenguaje de programación para la cadena de suministro, tendría mucho sentido tener esas preocupaciones diseñadas como ciudadanos de primera clase en el propio lenguaje de programación. Además, tendría sentido tener datos relacionales como parte del lenguaje como ciudadano de primera clase. En la cadena de suministro, el panorama de aplicaciones, que incluye muchas piezas de software empresarial, tiene datos relacionales en forma de bases de datos relacionales, como bases de datos SQL, en todas partes. Prácticamente todos los productos de software empresarial que existen en la actualidad tienen en su núcleo una base de datos relacional, lo que significa que, para fines de la cadena de suministro, tan pronto como queramos acceder a los datos, la realidad es que interactuaremos con datos que son de naturaleza relacional. Los datos se presentan como una lista de tablas extraídas de todas esas bases de datos que alimentan varias aplicaciones, y cada tabla tiene una lista de columnas o campos.

Realmente tiene sentido tener datos relacionales dentro del lenguaje. Además, ¿qué pasa con la interfaz de usuario (UI) y la experiencia del usuario (UX)? Uno de los puntos fuertes de Excel es que todo eso está completamente integrado en el lenguaje, por lo que no tienes un lenguaje de programación y luego todo tipo de bibliotecas de terceros para lidiar con la presentación, el renderizado y la interacción del usuario. Todo eso es parte del lenguaje. Tener todo eso como ciudadano de primera clase también sería de un interés muy relevante en lo que respecta a la cadena de suministro, al menos si queremos ser tan buenos como Excel puede ser para las cadenas de suministro.

Slide 10

Ahora, en el diseño del lenguaje, la gramática representa la representación formal de las reglas que definen un programa válido según el lenguaje de programación recién introducido. Básicamente, comienzas con un fragmento de texto y, primero, aplicas un analizador léxico, que es una clase específica de algoritmos o un pequeño programa. El analizador léxico descompone tu fragmento de texto, el programa que acabas de escribir, en una secuencia de tokens. El analizador léxico aísla todas las variables y símbolos que intervienen en tu lenguaje de programación. La gramática ayuda a convertir la secuencia de tokens en la semántica real del programa, definiendo lo que significa el programa y el conjunto exacto y no ambiguo de operaciones que deben realizarse para ejecutarlo.

La gramática en sí se aborda típicamente como un compromiso entre las preocupaciones que deseas internalizar dentro de tu lenguaje y los conceptos que deseas externalizar. Por ejemplo, si abordamos los datos relacionales como una preocupación externa, el programador tendría que introducir muchas estructuras de datos especializadas como diccionarios, búsquedas y tablas hash para realizar manualmente dentro del lenguaje de programación todas esas operaciones. Si la gramática quiere internalizar el álgebra relacional, significa que el programador puede escribir típicamente toda la lógica relacional directamente en su forma relacional. Sin embargo, eso significa que de repente todas esas restricciones relacionales y todo este álgebra relacional se convierten en una carga que la gramática tiene que llevar.

Desde una perspectiva de la cadena de suministro, dado que los datos relacionales son muy comunes en el software empresarial, tiene mucho sentido tener una gramática que se encargue de todas las preocupaciones relacionales directamente a nivel de la gramática en el lenguaje es importante.

Slide 11

Las gramáticas en ciencias de la computación son un tema enormemente estudiado. Han existido durante décadas y, sin embargo, probablemente sea el único ámbito en el que los proveedores de software empresarial fracasan más. De hecho, invariablemente terminan creando lenguajes de programación accidentales que surgen naturalmente siempre que hay configuraciones complejas en juego. Cuando tienes condiciones, disparadores, bucles y respuestas, típicamente necesitas ocuparte de este lenguaje en lugar de dejar que surja por sí solo.

Slide 12

Lo que sucede es que cuando no tienes una gramática, cada vez que realizas cambios en la aplicación, terminas con consecuencias fortuitas en el comportamiento real del sistema. Por cierto, esto también explica por qué la actualización de una versión de un software empresarial a otra suele ser muy compleja. Se supone que la configuración es la misma, pero cuando intentas ejecutar la misma configuración en la siguiente versión del software, obtienes resultados completamente diferentes. La causa raíz de estos problemas es la falta de gramática y semántica formalizada establecida para lo que va a significar la configuración.

La forma típica de representar una gramática es formalmente utilizando la Forma de Backus-Naur (BNF), que es una notación especial. En la pantalla, lo que puedes ver es un lenguaje de programación en miniatura que representa las direcciones postales de EE. UU. Cada línea con un signo igual representa una regla de producción. Lo que tienes a la izquierda es un símbolo no terminal, y a la derecha del signo igual hay una secuencia de símbolos terminales y no terminales. Los símbolos terminales están en rojo y representan símbolos que no se pueden derivar más. Los símbolos no terminales están entre corchetes y se pueden derivar más. Esta gramática aquí no está completa; habría muchas más reglas de producción que agregar para una gramática completa. Solo quería mantener esta diapositiva razonablemente concisa.

Una gramática es algo muy sencillo de definir en términos de sintaxis para tu lenguaje de programación, y también asegura que será no ambigua. Sin embargo, no porque esté escrito con la Forma de Backus-Naur significa que será una gramática válida o incluso una buena gramática. Para tener una buena gramática, necesitamos hacer un poco más que eso. La forma matemática de caracterizar una buena gramática es tener una gramática libre de contexto. Se dice que una gramática es libre de contexto si las reglas de producción se pueden aplicar para cualquier símbolo no terminal, independientemente de los símbolos que encuentres a la derecha y a la izquierda. La idea es que una gramática libre de contexto es algo donde puedes aplicar las reglas de producción en cualquier orden, y tan pronto como veas una coincidencia o derivación, simplemente la aplicas.

Lo que obtienes de una gramática libre de contexto es una gramática que, si cambias algo en ella y este cambio crea una ambigüedad, el compilador no podrá compilar el programa donde ocurre la ambigüedad. Esto es de interés primordial cuando tienes la intención de mantener una configuración durante mucho tiempo. En las cadenas de suministro, la mayoría del software empresarial tiene una vida útil muy larga. No es infrecuente ver piezas de software empresarial que operan durante dos o tres décadas. En Lokad, estamos sirviendo a más de 100 empresas, y es bastante común que extraigamos datos de sistemas que han estado en funcionamiento durante más de tres décadas, especialmente con grandes empresas.

Con una gramática libre de contexto, obtienes la garantía de que si hay un cambio que se debe realizar en este lenguaje (y recuerda, cuando digo “lenguaje”, puedo referirme a algo tan básico como la configuración), podrás identificar las ambigüedades que surgen cuando aplicas este cambio. Esto en lugar de tener esas ambigüedades que ocurren sin que te des cuenta de que tienes un problema, lo que puede generar dificultades al actualizar de un sistema a otro.

Lo que sucede cuando las personas no saben nada acerca de las gramáticas es que escriben manualmente un analizador. Si nunca has oído hablar de una gramática, un ingeniero de software escribiría un analizador, que es un programa que crea de manera arbitraria una especie de árbol que representa la versión analizada de tu programa. El problema con eso es que terminas con una semántica para tu programa que es increíblemente específica para la versión del programa que tienes. Entonces, si cambias este programa, cambias la semántica y obtendrás resultados diferentes, lo que significa que puedes tener la misma configuración pero un comportamiento diferente para tu cadena de suministro.

Afortunadamente, en 2004, hubo un pequeño avance introducido por Brian Ford con un artículo titulado “Parsing Expression Grammars: A Recognition-Based Syntactic Foundation”. Con este trabajo, Ford proporcionó a la comunidad una forma de formalizar el tipo de analizador ad hoc accidental que existe en el campo. Por ejemplo, estas gramáticas se llaman Gramáticas de Expresión de Análisis (PEGs), y con las PEGs, puedes convertir esos analizadores empíricos semi-accidentales en gramáticas formales reales de algún tipo.

Python, por ejemplo, no tiene exactamente una gramática libre de contexto pero tiene una PEG. Las PEGs son bastante buenas si tienes un extenso conjunto de pruebas automatizadas porque, en este caso, puedes lidiar con la preservación de la semántica a lo largo del tiempo. De hecho, con las PEGs, tienes una formalización de tu gramática, por lo que estás en una mejor situación en comparación con no tener ninguna gramática y simplemente tener un analizador. Sin embargo, en términos de evolución de la semántica, con una PEG, no detectarás automáticamente que tienes un cambio de semántica si cambias la gramática en sí. Por lo tanto, necesitas tener un conjunto extenso de pruebas automatizadas sobre tu PEG, que, por cierto, es exactamente lo que tiene la comunidad de Python. Tienen un conjunto muy sólido y extenso de pruebas automatizadas. Ahora, desde una perspectiva de cadena de suministro, creo que las gramáticas no solo tienen un interés en hacerte darte cuenta de su importancia, sino que también constituyen una prueba de fuego. En realidad, puedes poner a prueba a los proveedores de software empresarial cuando discutes sobre una pieza de software con una complejidad significativa. Deberías preguntar al proveedor sobre la gramática que utilizan para la configuración compleja. Si el proveedor responde con “¿qué es una gramática?”, entonces sabes que tienes un problema y el mantenimiento probablemente será lento y costoso.

Slide 13

La programación es muy difícil y las personas cometen muchos errores. Si fuera fácil, ni siquiera necesitaríamos programación en primer lugar. Un buen lenguaje de programación minimiza el tiempo que se tarda en identificar un error y solucionarlo. Este es uno de los aspectos más críticos de un lenguaje de programación, asegurando una productividad decente para quienquiera que esté escribiendo código.

Consideremos la siguiente situación: mientras escribes código, si el error se puede detectar mientras escribes, como un error tipográfico con un subrayado rojo en Microsoft Word, entonces el ciclo de retroalimentación para solucionar el error puede ser tan corto como 10 segundos, lo cual es ideal. Si el error solo se puede detectar cuando comienzas a ejecutar el programa, el ciclo de retroalimentación será de al menos 10 minutos. En la cadena de suministro, a menudo tenemos conjuntos de datos grandes para procesar y no podemos esperar que el programa comience a recorrer todos los datos en cuestión de segundos. Como resultado, si el problema solo ocurre en tiempo de ejecución, el ciclo de retroalimentación será de 10 minutos o más.

Si el error solo se puede detectar después de que el script se completa, lo que significa que el programa tiene un error pero no falla, el ciclo de retroalimentación tomará alrededor de 10 horas o más. Pasamos de tener 10 segundos de retroalimentación en tiempo real a 10 minutos si tenemos que ejecutar el programa y luego 10 horas si tenemos que inspeccionar los resultados numéricos y los KPI producidos por el programa.

Hay incluso un escenario peor: si la plataforma en la que operas no es estrictamente determinista, lo que significa que con la misma entrada y datos, puede darte resultados diferentes. Esto no es tan extraño como parece, ya que en la cadena de suministro podemos tener cosas como simulaciones de Monte Carlo en marcha. Si hay alguna aleatoriedad en los resultados, podemos tener algo que falla solo de vez en cuando, y en esta situación, el ciclo de retroalimentación suele ser más largo que 10 días. Entonces, pasamos de 10 segundos a 10 días, y hay mucho en juego en acortar este ciclo de retroalimentación. El análisis estático representa un conjunto de técnicas que se pueden aplicar para detectar problemas, errores o fallas sin siquiera ejecutar el programa en primer lugar. Con el análisis estático, la idea es que ni siquiera ejecutarás el programa, lo que significa que puedes informar del error en tiempo real mientras las personas están escribiendo, al igual que un subrayado rojo para errores tipográficos en Microsoft Word. Más en general, hay un gran interés en transformar cada problema para que se mueva hacia una clase anterior de retroalimentación, cambiando problemas que tomarían días en identificar en minutos o minutos en segundos, y así sucesivamente.

Desde una perspectiva de la cadena de suministro, hemos visto en una de las conferencias anteriores que las cadenas de suministro pueden esperar mucho caos. No podemos tener ciclos de lanzamiento clásicos donde esperas a que se entregue la próxima versión de tu software. A veces hay eventos extraordinarios, como un cambio arancelario, un barco de carga que queda atrapado en un canal o una pandemia. Estas situaciones de emergencia requieren correcciones de emergencia, y la cantidad de análisis estático que puedes hacer sobre tu lenguaje de programación define en gran medida cuánto caos tendrás en producción debido a errores que no se capturaron en tiempo real mientras se escribía el código. Los eventos extraordinarios pueden parecer raros, pero en la práctica, las sorpresas en la cadena de suministro son bastante comunes.

Slide 14

Hay pruebas matemáticas de que no es posible detectar todos los errores con un lenguaje de programación general en una situación general. Por ejemplo, ni siquiera es posible demostrar que el programa se completará, lo que significa que no es posible garantizar que lo que has escrito no seguirá ejecutándose indefinidamente.

Con el análisis estático, típicamente obtienes tres categorías: algunas partes del código son probablemente buenas, algunas partes son probablemente malas y para muchas cosas intermedias, simplemente no lo sabes. La idea es que cuanto más te desplaces de “no lo sabes” a “código malo”, más esfuerzo necesitarás en términos de diseño de lenguaje para convencer al compilador de que tu programa es válido. Entonces, tenemos que encontrar un equilibrio entre cuánto esfuerzo quieres invertir para convencer al lenguaje de programación de que tu código es correcto versus cuántas garantías quieres tener sobre el programa en tiempo de compilación, incluso antes de que el programa se ejecute realmente. Esto es una cuestión de productividad.

Ahora, una lista rápida de errores típicos detectados con el análisis estático incluye errores de sintaxis, como comas o paréntesis olvidados. Algunos lenguajes de programación ni siquiera pueden detectar errores de sintaxis antes de la ejecución, como Bash, el lenguaje de shell en Linux. El análisis estático también puede detectar errores de tipo, que ocurren cuando tienes el tipo incorrecto o el número incorrecto de argumentos para una función que estás llamando.

También se puede detectar código inalcanzable, lo que significa que el código está bien, pero nunca se ejecutará porque el programa completo puede ejecutarse sin llegar nunca a esa parte de código. Es como código muerto o una conexión lógica olvidada. El código inconsecuente es otro problema que se puede identificar, donde el código se ejecuta pero no tiene impacto en la salida final. Es una variante de código inalcanzable.

También se puede detectar código que consume demasiados recursos, lo que se refiere a código que se ejecutaría, excepto que la cantidad de recursos informáticos necesarios supera con creces lo que puedes permitirte para tu programa. Un programa consume recursos informáticos como memoria, almacenamiento y CPU. A través del análisis estático, puedes demostrar que un bloque de código consume muchos más recursos de los que puedes permitirte, considerando tus restricciones como tener el cálculo completo dentro de un marco de tiempo específico. Querrías que esto falle en tiempo de compilación en lugar de ejecutar tu programa durante una hora y luego que falle debido a un tiempo de espera, lo que llevaría a una productividad muy baja.

Sin embargo, hay un giro cuando se trata del análisis estático. A medida que escribes, estás lidiando con un programa que es inválido todo el tiempo. A medida que escribes tecla por tecla, estás transformando un programa válido en uno inválido. Una solución de calidad industrial para esta situación se llama Protocolo del Servidor de Lenguaje. Esta herramienta viene con un lenguaje de programación y es el estado del arte cuando se trata de retroalimentación de errores en tiempo real para los programas que estás escribiendo.

A través de un Protocolo del Servidor de Lenguaje, puedes acceder a funciones como “ir a la definición” cuando haces clic en una variable. El Protocolo del Servidor de Lenguaje es fundamentalmente estatal, recordando la última versión de tu programa que era correcta, junto con las anotaciones y semánticas disponibles. Preserva estas anotaciones y detalles adicionales al tratar con tu programa roto solo porque has presionado una tecla adicional y ya no es un programa válido. Es un cambio de juego en términos de productividad y siempre que haya algún grado de urgencia, marca una gran diferencia para fines de la cadena de suministro.

Slide 15

Ahora, profundicemos en el sistema de tipos. Como primera aproximación aproximada, un sistema de tipos es un conjunto de reglas que aprovecha la categorización dentro de los objetos de tu programa, o la categorización de los elementos que manipulas, para aclarar si ciertas interacciones están permitidas o no. Por ejemplo, los tipos típicos incluyen cadenas de texto, enteros y números de punto flotante, todos los cuales son tipos muy básicos. Definirá que sumar dos enteros juntos es válido, pero sumar una cadena de texto y un entero no es válido, excepto en JavaScript porque la semántica es diferente allí.

Los sistemas de tipos, en general, son un problema de investigación abierto y pueden volverse increíblemente abstractos. Para arrojar algo de luz, debemos aclarar que hay dos tipos de tipos, que a menudo se confunden. En primer lugar, están los tipos de valores, que solo existen en tiempo de ejecución cuando el programa se está ejecutando realmente. Por ejemplo, en Python, si estamos considerando una función que devuelve el primer elemento de un arreglo de enteros, entonces el tipo del valor devuelto por esta función va a ser un entero. Desde esta perspectiva, todos los lenguajes de programación tienen tipos, todos están tipados.

En segundo lugar, están los tipos de variables, que solo existen en tiempo de compilación mientras el programa se está compilando y aún no se está ejecutando. El desafío con los tipos de variables es extraer la mayor cantidad de información posible sobre esas variables en tiempo de compilación. Si volvemos al ejemplo anterior, en Python, puede o no ser posible identificar el tipo del valor de retorno devuelto por la función, porque Python no es completamente fuertemente tipado en tiempo de compilación.

Desde una perspectiva de la cadena de suministro, buscamos un sistema de tipos que admita lo que pretendemos hacer en beneficio de la cadena de suministro. Queremos ser lo más restrictivos posible para capturar problemas y errores temprano, pero también lo más flexibles posible para permitir todas las operaciones que podrían ser de interés. Por ejemplo, consideremos la suma de una fecha y un entero. En un lenguaje de programación regular, probablemente dirías que no es legítimo, pero desde una perspectiva de cadena de suministro, si tenemos una fecha y queremos agregar siete días, tendría sentido escribir “fecha + 7”. Hay muchas operaciones en la planificación de la cadena de suministro que implican desplazar fechas por un cierto número de días, por lo que sería útil tener un álgebra donde sea aceptable realizar una suma entre una fecha y un número.

En cuanto a los tipos, ¿queremos permitir la suma de una fecha a otra? Probablemente no. Sin embargo, ¿queremos permitir la resta entre dos fechas? ¿Por qué no? Si restamos una fecha de otra que ocurre antes, obtenemos el delta, que podría expresarse en días. Esto tiene mucho sentido para cálculos involucrados en la planificación.

Continuando con el tema de las fechas, también hay características que podrían ser de interés cuando se piensa en lo que un sistema de tipos debería hacer por nosotros en términos de preocupaciones de la cadena de suministro. Por ejemplo, ¿qué tal si restringimos el rango de tiempo aceptable? Podríamos decir que las fechas fuera del alcance de 20 años en el pasado y 20 años en el futuro simplemente no son válidas. Es probable que si estamos realizando una operación de planificación y en algún momento del programa manipulamos una fecha que está más de 20 años en el futuro, las probabilidades sean abrumadoras de que no sea una planificación válida para la mayoría de las industrias. En la mayoría de los casos, no planificarías operaciones a nivel diario más de 20 años en el futuro. Por lo tanto, no solo podemos tomar los tipos habituales, sino redefinirlos de manera más restrictiva y más adecuada para los propósitos de la cadena de suministro.

Además, está todo el aspecto de la incertidumbre. En la gestión de la cadena de suministro, siempre estamos mirando hacia adelante, pero desafortunadamente, el futuro siempre es incierto. La forma matemática de abrazar la incertidumbre es a través de variables aleatorias. Tendría sentido incorporar variables aleatorias en el lenguaje para representar la demanda futura incierta, los tiempos de entrega y las devoluciones de los clientes, entre otras cosas.

Slide 16

En Lokad, hemos desarrollado Envision, un lenguaje de programación dedicado a la optimización predictiva de las cadenas de suministro. Envision es una combinación de SQL, Python, optimización matemática, aprendizaje automático y capacidades de big data, todo integrado como ciudadanos de primera clase dentro del propio lenguaje. Este lenguaje viene con un Entorno de Desarrollo Integrado (IDE) basado en web, lo que significa que puedes escribir un script desde la web y tener todas las características modernas de edición de código. Estos scripts operan sobre un sistema de archivos distribuido integrado que viene con el entorno de Lokad, por lo que la capa de datos está completamente integrada en el lenguaje de programación.

Los scripts de Envision se ejecutan en una flota de máquinas diseñadas para aprovechar toda la capacidad de la nube. Cuando se ejecuta el script, se distribuirá en muchas máquinas para que se ejecute más rápido. En la pantalla, puedes ver la tubería del compilador utilizada por Envision. Hoy no vamos a discutir este lenguaje de programación; solo vamos a discutir su tubería de compilación porque ese es el tema de interés para la conferencia de hoy.

Primero, comenzamos con un fragmento de texto que contiene el script de Envision. Representa un programa que ha sido escrito por un experto en cadena de suministro, no por un ingeniero de software, para abordar un desafío específico de la cadena de suministro. Este desafío podría ser decidir qué producir, qué reponer, qué mover o si ajustar un precio hacia arriba o hacia abajo. Estos casos de uso implican decisiones sobre qué producir, reponer, mover o si ajustar los precios hacia arriba o hacia abajo. El texto del script contiene las instrucciones, y la idea es procesar este script y obtener el Árbol de Sintaxis Sin Pérdidas (LST, por sus siglas en inglés). El LST es de interés porque es una representación muy específica que no descarta ningún carácter. Incluso se preservan los espacios en blanco no significativos. La razón de esto es asegurarse de que cualquier reescritura automatizada del programa no altere el código existente. Este enfoque evita situaciones en las que las herramientas reordenan el código, mueven las indentaciones o causan otras interrupciones que dificultan el reconocimiento del código.

Una operación básica de refactorización, por ejemplo, podría implicar cambiar el nombre de una variable y todas sus apariciones en el programa sin tocar nada más. A partir del LST, pasamos al Árbol de Sintaxis Abstracta (AST), donde simplificamos el árbol. Los paréntesis no son necesarios en esta etapa porque la estructura del árbol define las prioridades de todas las operaciones. Además, realizamos una serie de operaciones de desugaring para eliminar cualquier sintaxis proporcionada para beneficio del programador final.

Pasando del AST al Grafo de Sintaxis Abstracta (ASG), aplanamos el árbol. Este proceso implica descomponer declaraciones complejas con expresiones altamente anidadas en una secuencia de declaraciones elementales. Por ejemplo, una declaración como “a = b + c + d” se dividiría en dos declaraciones, cada una con solo una adición. Esto es precisamente lo que sucede durante la transición del AST al ASG.

A partir del ASG, pasamos al Grafo de Optimización (OG), donde realizamos el moldeado y la transmisión de tipos, especialmente en relación con el álgebra relacional. Como se mencionó anteriormente, Envision incorpora un álgebra relacional dentro del lenguaje. Como se insinuó muchas veces antes, Envision incorpora un álgebra relacional, como en las bases de datos relacionales o las bases de datos SQL, como ciudadano de primera clase. Hay numerosas operaciones relacionales, y verificamos que estas operaciones relacionales sean válidas según el esquema de las tablas con las que estamos operando al hacer la transición de ASG a OG. El Grafo de Optimización (OG) representa el último paso de nuestro compilador de front-end y consiste en operaciones relacionales puras y elementales que se aplican al programa, representando pequeñas partes de lógica. Al igual que en SQL, estos elementos son de naturaleza relacional.

El grafo de optimización se llama “optimización” porque hay numerosas transformaciones que ocurren de OG a OG. Estas transformaciones ocurren porque, al tratar con álgebra relacional, organizar las operaciones de ciertas maneras puede hacer que el programa se ejecute mucho más rápido. Por ejemplo, en SQL, si tienes un filtro y luego una operación, o una operación primero y luego un filtro, es mucho mejor filtrar los datos primero y luego aplicar la operación. Esto asegura que las operaciones se apliquen solo a los datos necesarios, mejorando la eficiencia.

En Lokad, el último paso del compilador de front-end es la Representación Intermedia Alta (HIR). El HIR es una frontera limpia, estable y documentada entre el front-end y el back-end del pipeline del compilador. A diferencia del Grafo de Optimización (OG), que cambia constantemente debido a heurísticas, el HIR es estable y proporciona una entrada consistente para el back-end del compilador. Además, el HIR es serializable, lo que significa que se puede transformar fácilmente en un paquete de bytes para moverlo de una máquina a otra. Esta propiedad es esencial para distribuir cálculos en varias máquinas.

A partir de la Representación Intermedia Alta, pasamos a “funcs”. Los funcs son valores que aún no se han evaluado y representan los bloques atómicos de cálculo dentro de una ejecución distribuida. Por ejemplo, al sumar dos vectores gigantes de una tabla con miles de millones de líneas, habrá una serie de funcs que representan varias partes de estos vectores. Cada func es responsable de sumar una parte de los dos vectores y se ejecuta en una máquina. Los cálculos grandes se dividen en muchos funcs para distribuir la carga de trabajo en múltiples CPUs y múltiples máquinas si el cálculo es lo suficientemente grande como para justificar este grado de distribución. Los funcs se llaman “perezosos” porque no se evalúan al principio; se evalúan cuando se necesitan. Se pueden realizar muchos cálculos antes de que algunos funcs se calculen realmente, y una vez que se calcula un func, el func en sí se reemplaza por su resultado.

Dentro del func, encontrarás la representación intermedia baja, que representa la lógica imperativa de bajo nivel que se ejecuta dentro del func. Por ejemplo, puede incluir bucles y accesos a diccionarios. Finalmente, esta representación intermedia de bajo nivel se compila en bytecode, que representa el objetivo final de nuestro pipeline de compilación. En Lokad, apuntamos al bytecode .NET, conocido técnicamente como MSIL.

Desde una perspectiva de la cadena de suministro, lo realmente interesante es que a través de este pipeline de compilación, que podría considerarse complejo, estamos reproduciendo el grado de integración que se encuentra en Microsoft Excel. El lenguaje está integrado con la capa de datos y la capa de UI/UX, lo que permite a los usuarios ver e interactuar con los resultados del programa, tal como lo harían con una hoja de cálculo de Excel. Sin embargo, a diferencia de Excel, nos adentramos en territorios mucho más interesantes para la gestión de la cadena de suministro al adoptar conceptos relacionales como ciudadanos de primera clase, así como la optimización matemática y el aprendizaje automático.

Tanto la optimización matemática como el aprendizaje automático en este pipeline pasan por todo el pipeline, en lugar de simplemente llamar a una biblioteca que se encuentra en algún lugar. Tener el aprendizaje automático como ciudadano de primera clase en el pipeline permite mensajes de error más comprensibles, lo que marca una gran diferencia en términos de productividad para los expertos en cadena de suministro.

Slide 17

Como tema final, los compiladores en la actualidad casi siempre apuntan a una máquina virtual, pero a su vez, estas máquinas virtuales se compilan hacia otra máquina virtual. En la pantalla, las capas típicas de la máquina virtual que se encuentran en una configuración basada en servidores son muy similares a las que tenemos con un script de Envision. Acabo de presentar el pipeline de compilación, pero fundamentalmente, sería prácticamente la misma pila si estuviéramos pensando en un script de Python o una hoja de cálculo de Excel operada desde un servidor. Al diseñar un compilador, esencialmente eliges la capa en la que vas a inyectar el código. Cuanto más profunda sea la capa, más tecnicismos tendrás que abordar. Para elegir la capa, hay una serie de preocupaciones que deben abordarse.

Primero, está la seguridad. ¿Cómo proteges tu memoria y qué debe o no debe acceder el programa? Si tienes un lenguaje de programación genérico, tus opciones son limitadas. Es posible que necesites operar a nivel del sistema operativo invitado, aunque incluso eso puede no ser muy seguro. Hay formas de aislar, pero es muy complicado, por lo que incluso es posible que tengas que ir más allá de eso.

En segundo lugar, está la preocupación por las características de bajo nivel en las que estás interesado. Por ejemplo, esto podría ser importante si deseas lograr una ejecución más eficiente, reduciendo la cantidad de recursos informáticos necesarios para completar tu programa. Puedes decidir ir lo suficientemente bajo como para administrar la memoria y los hilos. Sin embargo, con este poder viene la responsabilidad de administrar realmente la memoria y los hilos.

En tercer lugar, hay características de conveniencia como la recolección de basura, el seguimiento de la pila, el depurador y el perfilador. Por lo general, toda la instrumentación alrededor del compilador es más compleja que el compilador en sí. La cantidad de características de conveniencia de las que te beneficias no debe subestimarse.

En cuarto lugar, hay preocupaciones de asignación de recursos. Si estás trabajando con una hoja de cálculo de Excel en tu escritorio, Excel puede consumir todos los recursos informáticos de tu estación de trabajo. Sin embargo, con Envision o SQL, tienes múltiples usuarios a los que atender, y debes decidir cómo asignar los recursos. Además, con Envision, no solo hay múltiples usuarios, sino también múltiples empresas a las que atender, ya que Lokad es multiinquilino. Esto tiene sentido en la cadena de suministro porque la necesidad de recursos informáticos es muy intermitente para la mayoría de las cadenas de suministro.

Por lo general, solo necesitas una ráfaga muy intensa de cómputo durante aproximadamente media hora o tal vez una hora, y luego nada durante las siguientes 23 horas. Luego, enjuaga y repite diariamente. Si asignaras recursos informáticos de hardware a una empresa, esos recursos permanecerían sin usar el 90% del tiempo o incluso más. Por lo tanto, deseas poder distribuir la carga de trabajo en muchas máquinas y en muchas empresas, potencialmente empresas que operan en diferentes zonas horarias.

Por último, está la preocupación del ecosistema. La idea es que cuando decidas un nivel específico y una máquina virtual específica a la que apuntar para tu compilador, será bastante conveniente integrar e interconectar tu compilador con lo que también apunta a las mismas máquinas virtuales exactas. Esto plantea la cuestión del ecosistema: ¿qué puedes encontrar al mismo nivel que el que apuntas, para no reinventar la rueda para cada pequeño detalle involucrado en toda tu pila? Esta es la última y importante preocupación.

Slide 18

En conclusión, felicitaciones a los pocos afortunados que llegaron hasta aquí en esta serie de conferencias sobre la cadena de suministro. Esta es probablemente una de las conferencias más técnicas hasta ahora. Los compiladores son una pieza muy técnica; sin embargo, la realidad de las cadenas de suministro modernas es que todo se mediatiza a través de un lenguaje de programación. Ya no existe tal cosa como una cadena de suministro cruda y directamente observable. La única forma de observar una cadena de suministro es a través de la mediación de registros electrónicos producidos por todas las piezas de software empresarial que constituyen el panorama aplicativo. Por lo tanto, se necesita un lenguaje de programación, y por defecto, este lenguaje de programación resulta ser Excel.

Sin embargo, si queremos hacerlo mejor que Excel, debemos pensar detenidamente en lo que significa “mejor” desde una perspectiva de cadena de suministro y lo que significa en términos de lenguajes de programación. Si una empresa no tiene la estrategia o la cultura adecuada, ninguna tecnología la salvará. Sin embargo, si la estrategia y la cultura son sólidas, entonces las herramientas realmente importan. Las herramientas, incluidos los lenguajes de programación, definirán su capacidad de ejecución, la productividad que puede esperar de sus expertos en cadena de suministro y el rendimiento que obtendrá de su cadena de suministro al convertir la estrategia macro en las miles de decisiones mundanas diarias que su cadena de suministro necesita tomar. Ser capaz de evaluar la adecuación de las herramientas, incluidos los lenguajes de programación que planea utilizar para abordar los desafíos de la cadena de suministro, es de suma importancia. Si no puedes evaluar, entonces es simplemente un culto completo.

Slide 19

La próxima conferencia tratará sobre ingeniería de software. Hoy, discutimos las herramientas; sin embargo, la próxima vez, discutiremos las personas que utilizan las herramientas y qué tipo de trabajo en equipo se requiere para hacer bien el trabajo. La conferencia se llevará a cabo el mismo día de la semana, miércoles, a las 3 p.m., hora de París.

Ahora, echaré un vistazo a las preguntas.

Pregunta: Al seleccionar software para cadenas de suministro, ¿cómo pueden evaluar las empresas que no tienen conocimientos técnicos si el compilador y la programación son adecuados para sus necesidades?

Bueno, estoy bastante seguro de que una empresa típica que opera una cadena de suministro típica no tiene las calificaciones para diseñar un vehículo, sin embargo, logran comprar camiones que son adecuados para sus necesidades de cadena de suministro y transporte. No es porque no seas un experto y no puedas reconstruir y rediseñar un camión que no puedas tener una opinión muy sólida sobre si es un buen camión para tus necesidades de transporte. Entonces, no estoy diciendo que las empresas que no tienen conocimientos técnicos deban dar un salto increíble hacia adelante y de repente convertirse en expertos en el diseño de compiladores. Sin embargo, creo que en solo una hora y media, cubrimos bastante terreno. Con 10 horas más de una introducción más detallada y a un ritmo más lento, aprenderías todo lo que necesitarías saber en términos de diseño de lenguaje para fines de cadena de suministro.

Hay una diferencia entre ser un experto y ser tan increíblemente ignorante que las personas pueden venderte un scooter pretendiendo que es un camión. Si tradujéramos este tipo de ignorancia que observé en términos de diseño de software empresarial a la industria automotriz, las personas afirmarían que un scooter es un semirremolque y viceversa, y se saldrían con la suya.

Esta serie de conferencias trata sobre ciencias auxiliares, por lo que no hay intención de que las personas que deseen ser practicantes de la cadena de suministro se conviertan en expertos en estos campos. Sin embargo, al tener algún conocimiento básico, puedes llegar muy lejos en la evaluación. La mayoría de las veces, solo necesitas tener suficiente conocimiento para hacer preguntas difíciles. Si el proveedor te da una respuesta sin sentido, no se ve bien. Si ni siquiera sabes qué preguntas técnicas hacer, puedes ser engañado.

Mi sugerencia es que no necesitas volverte increíblemente experto en tecnología; solo necesitas ser lo suficientemente hábil como para ser un aficionado de nivel básico que pueda encontrar fallas y evaluar si todo se desmorona o si hay sustancia real detrás de ello. Lo mismo ocurre con la optimización matemática, el aprendizaje automático, las CPUs, y así sucesivamente. La idea es saber lo suficiente para diferenciar entre algo fraudulento y algo legítimo.

Pregunta: ¿Abordaste directamente el problema de los lenguajes de programación existentes que no están diseñados para la cadena de suministro?

Esta es una muy buena pregunta. Diseñar un nuevo lenguaje de programación puede parecer completamente loco. ¿Por qué no optar por algo ya establecido, como Python, y hacer las pequeñas modificaciones que necesitamos? Hubiera sido una opción. El problema es que el problema principal no es realmente lo que necesitamos agregar a esos lenguajes, sino lo que necesitamos eliminar.

Mi principal preocupación con Python no es que no tenga un álgebra probabilística o que no tenga un álgebra relacional incorporada. Mi crítica número uno es que es un lenguaje de programación completamente capaz y genérico, y por lo tanto expone a la persona que va a escribir código a todo tipo de conceptos, como la programación orientada a objetos en Python, que son completamente inconsecuentes en lo que respecta a la cadena de suministro. El problema no fue tanto tomar un lenguaje y agregar algo, sino tomar un lenguaje y tratar de eliminar toneladas de cosas. Sin embargo, el problema es que tan pronto como eliminas cosas de un lenguaje de programación existente, rompes todo.

Por ejemplo, la primera versión de Python fue en 1990, por lo que es un lenguaje de programación de 30 años. La cantidad de código en una pila popular como Python es absolutamente gigantesca, y por una buena razón. No lo estoy criticando; es una pila muy sólida, pero también es enorme. Entonces, al final, evaluamos varias opciones: tomar un lenguaje de programación, restar toneladas de cosas hasta que estemos satisfechos con lo que tenemos, o considerar que todos esos lenguajes de programación tienen toneladas de legado propio.

Evaluamos cuánto esfuerzo requería crear un nuevo lenguaje y, al final, fue mucho más favorable crear un nuevo lenguaje. La ingeniería de un nuevo lenguaje de programación es un campo muy establecido, por lo que aunque pueda sonar increíble, no lo es. Hay cientos de libros que te dan recetas, e incluso ahora es accesible para los estudiantes de ciencias de la computación. Incluso hay profesores en departamentos de ciencias de la computación que asignan a sus estudiantes en un semestre la tarea de crear un compilador para un nuevo lenguaje de programación.

Al final, decidimos que las cadenas de suministro eran lo suficientemente masivas como para justificar un esfuerzo dedicado. Sí, siempre puedes reciclar cosas que no fueron diseñadas para las cadenas de suministro, pero las cadenas de suministro son una industria y un conjunto de problemas a nivel mundial y masivos. Entonces pensamos, considerando la escala que estamos viendo, tiene sentido hacer lo correcto y crear algo directamente para la cadena de suministro en lugar de reciclar accidentalmente.

Pregunta: Para la optimización de la cadena de suministro, Envision es apropiado ya que incluye SQL, Python, etc. Sin embargo, para WMS, ERP, donde el flujo de procesos es clave en lugar de la optimización matemática, ¿cómo puedes evaluar su compilador y lenguaje de programación?

Esa es una muy buena pregunta. Personalmente, he estado jugando con la idea de que hay actores en esta industria que han creado lenguajes de programación propios, solo para obtener los beneficios de implementar algo completamente transaccional y orientado al flujo de trabajo. La cadena de suministro, tal como yo la veo, se trata esencialmente de optimización predictiva. Sin embargo, el Sr. Nannani tiene toda la razón; ¿qué pasa con toda la parte de gestión, como el ERP, WMS, etc.?

Resulta que hay muchas empresas en este campo que han creado su propio lenguaje de programación. Mencioné SAP, que tiene ABAP, diseñado específicamente para eso. Desafortunadamente, en mi opinión, ABAP no ha envejecido muy bien. Hay muchas cosas en ABAP que no tienen mucho sentido en el siglo XXI. Realmente se nota que esto fue diseñado en el ‘83, y se nota. Por ejemplo, en Microsoft Dynamics, el ERP tiene su propio lenguaje de programación. Dynamics AX tiene su propio lenguaje de programación, y hay muchos proyectos de ERP que, en gran medida, traen su propio lenguaje de programación. Así que sí, existe.

Ahora bien, ¿esos lenguajes son realmente el pináculo de lo que podemos hacer en términos de lenguajes de programación modernos y de última generación en 2021? No lo creo, y ese también es el problema del que estaba hablando: los proveedores de software empresarial siguen reinventando lenguajes de programación, pero generalmente hacen un trabajo muy deficiente en eso. Es simplemente un diseño de ingeniería improvisado. Ni siquiera se toman el tiempo de leer los muchos libros que están disponibles en el mercado, y luego hay ingenieros pobres que se quedan con un montón de desorden.

Volviendo a tu pregunta, he estado jugando con la idea de que Lokad se aventurara en esta área y creara un lenguaje que no estuviera diseñado para la optimización, sino para apoyar el flujo de trabajo. Sin embargo, en este momento, el crecimiento de Lokad es tanto que no podemos desviarnos y ocuparnos de los flujos de trabajo. Estoy absolutamente seguro de que esto es correcto, y habrá nuevos actores que surgirán y harán un muy buen trabajo para la parte de gestión del problema. Lokad solo está abordando la parte de optimización de las cadenas de suministro; también está la parte de gestión.

Pregunta: Python se considera actualmente un lenguaje de programación estándar. ¿Hay alguna evolución en curso en el mercado?

Esa es una muy buena pregunta. Verás, cuando la gente me habla de “los estándares”, he estado aquí el tiempo suficiente como para ver cómo los estándares vienen y van. No soy muy viejo, pero cuando estaba en la escuela secundaria, el estándar era C++. En los años 90, C++ era el estándar. ¿Por qué lo harías de otra manera? Luego vino Java, alrededor del año 2000, y la combinación de Java y XML era el estándar.

Incluso la gente decía que las universidades en ese momento se habían convertido en “escuelas de Java”. Ese era literalmente el término de moda alrededor del año 2000; la gente decía: “Esto ya no es una universidad de ciencias de la computación; esto es solo una escuela de Java”. Unos años más tarde, cuando fundé Lokad, el lenguaje de programación para cualquier cosa relevante para la estadística seguía siendo R. Python todavía era muy marginal, y R dominaba absolutamente el campo en términos de análisis estadístico.

A medida que avanzamos en términos de lenguajes de programación, C++ fue desapareciendo. Microsoft introdujo C# en 2002 y la plataforma .NET, que canibalizó una parte importante del ecosistema de C++. Una gran parte de los desarrolladores de C++ en todo el mundo estaban en Microsoft, una empresa muy masiva. El punto al que quiero llegar es que ha habido una evolución continua completa, y cada año, la gente mira esto como si hubiera un estándar, pero este estándar cambia todo el tiempo.

JavaScript había estado presente durante 20 años, pero no era algo significativo. Luego, un libro publicado alrededor de 2009 o 2012 llamado “JavaScript: The Good Parts” reveló que JavaScript no era completamente insano. Podías usar JavaScript para un proyecto real sin perder la cordura; solo tenías que quedarte con las partes buenas. De repente, JavaScript estaba de moda y la gente comenzó a usarlo en el lado del servidor con un sistema llamado Node.js.

Python solo se hizo prominente hace unos años, después de que la comunidad de Python pasara por una actualización agotadora de la versión 2.7 a la versión 3.x. Al final de esta actualización, el interés por Python se renovó. Sin embargo, hay muchos peligros que acechan a Python. No es un lenguaje muy bueno según los estándares del siglo XXI. Es un lenguaje de 30 años y muestra su edad. Si quieres algo mejor en todas las dimensiones excepto la madurez, podrías mirar a Julia. Julia es superior en casi todos los aspectos a Python para la ciencia de datos, excepto en madurez, donde Julia todavía está años atrás.

Hay toneladas de evoluciones en curso y es fácil confundir el estado de la industria con algo que es un estándar que se supone que debe durar. Por ejemplo, en el ecosistema de Apple, estaba Objective-C, y luego Apple decidió producir Swift como reemplazo, que ahora está reemplazando a Objective-C. El panorama de los lenguajes de programación todavía está evolucionando mucho y, aunque lleva tiempo, si miramos el ecosistema dentro de diez años, es probable que haya una cantidad significativa de evolución. Python puede no surgir como el lenguaje de programación dominante, ya que hay muchas opciones rivales que ofrecen mejores respuestas.

Pregunta: Las empresas de alimentos y las startups de comercio electrónico a menudo piensan que pueden ganar la batalla con equipos de ciencia de datos y lenguajes de propósito general. ¿Cuál sería su punto de venta principal para hacer que refinen este enfoque y se den cuenta de que necesitan algo más específico para el problema?

Como dije, este es el problema del efecto Dunning-Kruger. Le das a un ingeniero de software un sistema de programación lineal entera mixta para hacer programación entera, y una semana después, esta persona pensará que de repente se ha convertido en un experto en optimización discreta. Entonces, ¿cómo gano la batalla? La verdad es que, por lo general, no las ganamos. Lo que hago es describir cómo se desarrollarán las catástrofes.

Es sencillo cuando se utilizan bloques genéricos de tecnología para crear prototipos fantásticos. Estos prototipos funcionan de manera brillante debido a la ilusión de Star Wars: solo tienes tu pieza de tecnología en aislamiento. A medida que estas empresas comienzan a intentar llevar esas cosas a producción, lucharán, la mayoría de las veces debido a problemas muy mundanos. Enfrentarán problemas de integración en curso, no como Google o Microsoft o Amazon, que pueden permitirse tener mil ingenieros para lidiar con todas las tuberías.

TensorFlow, por ejemplo, es difícil de integrar. Google tiene los 1000 ingenieros necesarios para pegar TensorFlow en todas sus tuberías de extracción de datos y aplicaciones para sus propósitos. Pero la pregunta es, ¿pueden las startups o las empresas de comercio electrónico permitirse tener tantas personas para encargarse de todas las tuberías? Por lo general, la respuesta es no. La gente imagina que simplemente eligiendo estas herramientas, podrán seleccionar cosas y juntarlas, y mágicamente funcionará. Pero no lo hace. Requiere una gran cantidad de ingeniería.

Por cierto, algunos proveedores de software empresarial también sufren el mismo problema. Tienen demasiados componentes en su solución, y eso explica por qué implementar una solución, sin ninguna personalización, ya lleva meses porque hay tantas partes inestables en el sistema que solo están débilmente integradas. Se vuelve muy difícil.

Supongo que esta fue la última pregunta. Nos vemos la próxima vez.