Perché non Python
Anni fa, ma anche anni dopo la fondazione di Lokad, ho capito che nessuna singola app avrebbe mai offerto qualcosa di vicino alla grandezza per quanto riguarda l’ottimizzazione della supply chain. Abbiamo fatto del nostro meglio, ma non è stato sufficiente. Non importa quante funzionalità inserissimo nelle prime versioni di Lokad, ogni nuovo cliente sembrava disperatamente diverso da tutti quelli coperti finora. Supply chain challenges sono semplicemente troppo diverse e caotiche per essere incasellate in un numero sensato di menu, pulsanti e opzioni.

Infatti, la maggior parte dei nostri concorrenti ammette questa situazione e ha intrapreso la via della realizzazione di prodotti software caratterizzati da un numero pazzesco di menu, pulsanti e opzioni, tutto ciò come disperato tentativo di far fronte a tutte le supply chain challenges. Purtroppo, questa strada porta a mostruosità software che si trasformano in spettacolari fallimenti quando implementati su scala. Mi riferisco a questo antipattern come al Orrore Non Euclideo.
Così, di fronte a una classe di problemi – cioè le supply chain challenges – che semplicemente non potevano essere risolti con una singola app, abbiamo iniziato, in parte per caso1, ad affrontare invece il meta-problema: come realizzare app su misura in cui ciascuna app si dedichi alla risoluzione di un singolo problema per una determinata situazione, ad esempio l’ottimizzazione del riapprovvigionamento per una specifica azienda.
Fornire software su misura per le imprese non è una novità. L’industria del software ha avuto inizio in questo modo negli anni ‘60, per poi evolversi negli anni ‘80 verso il dominante shrinkwrap model che conosciamo oggi. In linea generale, il software su misura tende ad avere molte proprietà indesiderate rispetto allo shrinkwrap: investimenti iniziali più elevati, configurazioni lunghe, costi di manutenzione maggiori, rischi più alti, ecc.
Tuttavia, l’esperienza accumulata nei primi anni di Lokad indicava che, per quanto riguarda l’ottimizzazione della supply chain, il software su misura aveva un vantaggio chiave: forniva davvero risultati eccellenti. Infatti, mentre la nostra app originale, al meglio, produceva risultati accettabili2 indipendentemente dalla precisione delle previsioni, quei prototipi riuscivano spesso a ottenere risultati eccellenti. Inoltre, l’unico trucco consisteva nell’estrema specializzazione del pezzo di software destinato al problema in questione.
Dopo aver esaurito quelle che sembravano essere tutte le alternative, abbiamo concluso che fornire app su misura era l’unica strada percorribile. Tuttavia, la scalabilità – come distribuire molte app – e la manutenibilità – come mantenere sotto controllo i costi di manutenzione – erano due preoccupazioni fondamentali. Prima di tutto, dovevamo scegliere un linguaggio di programmazione. A quel tempo, considerammo molte opzioni: R, Python, JavaScript, Lua, C#, … e lo sviluppo del nostro domain-specific programming language (DSL), che in seguito sarebbe conosciuto come Envision. Discutere i pro e i contro di tutte quelle opzioni sarebbe stato alquanto tedioso3, per cui, per motivi di chiarezza, la discussione si sarebbe concentrata sulla scelta tra Python e Envision; Python era il candidato più forte rispetto allo sviluppo del nostro DSL.
Python era attraente per la sua semplicità e per il suo ricco ecosistema di librerie di terze parti, in particolare nel campo del machine learning4. Era anche un’opzione a basso costo per Lokad: poiché Python, e praticamente tutte le sue librerie popolari, sono open source, ci saremmo limitati a ripacchettare un ristretto sottoinsieme di Python, includendo in whitelist una dozzina di pacchetti accuratamente selezionati, e basta. La maggior parte del lavoro per Lokad si sarebbe concentrata sul fornire un’esperienza PaaS attorno a Python in stile Heroku, ma il più possibile su misura per le supply chain challenges.
Eppure, ecco un banco di prova che abbiamo considerato: era ragionevole aspettarsi che un business analyst – successivamente conosciuto come Supply Chain Scientist – lavorando 1 giorno a settimana per 6 mesi potesse realizzare un’app di livello produzione per risolvere una supply chain challenge critica, come il riapprovvigionamento, per un’azienda da $10M? Considerando l’opzione Python, era chiaro che non saremmo mai riusciti neppure ad avvicinarci a un tale livello di efficienza operativa.
Innanzitutto, Python richiede ingegneri del software. Infatti, Python, come qualsiasi linguaggio di programmazione a pieno titolo, espone una marea di complessità tecniche a chi scrive codice in Python. Sebbene il ruolo di supply chain scientist sia stato formalizzato solo in seguito, avevamo intuito fin dall’inizio che, pur contando persone intelligenti e talentuose, aspettarsi che fossero esperti sia in ingegneria della supply chain che in ingegneria del software fosse troppo. Avevamo bisogno di capacità programmatiche accessibili a un ampio spettro di persone con mentalità tecnica, non solo a ingegneri del software professionisti.
Così, abbiamo creato Envision come linguaggio per eliminare intere classi di problemi tecnici che sono inevitabili con Python. Per esempio:
- Gli oggetti possono essere null, le date possono essere assurdamene lontane nel passato o nel futuro, i NaN possono propagarsi felicemente attraverso la tua pipeline di dati, le stringhe possono diventare absurdamente lunghe… Nella supply chain, queste “caratteristiche” non sono altro che problemi in attesa di accadere.
- Gli elementi orientati agli oggetti (cioè le classi) sono destinati a essere utilizzati in modo scorretto5, e lo stesso vale per eccezioni personalizzate o Regexes. La mera presenza di tali elementi è, nel migliore dei casi, una distrazione nociva.
- Diverse operazioni di base, come il parsing di file tabellari eterogenei (inclusi i fogli di calcolo Excel), non fanno parte del linguaggio e richiedono di trattare con molti pacchetti eterogenei, ciascuno con le proprie complessità tecniche.
Nessuna di queste classi di problemi tecnici può essere rimossa da Python senza compromettere il linguaggio stesso. Envision, come linguaggio di programmazione, è accessibile agli supply chain specialists (contro software specialists), solo grazie al suo focus estremamente mirato sui problemi di ottimizzazione predittiva della supply chain.
Pensate all’ultima volta che avete dovuto eseguire calcoli con un foglio di Excel, e immaginate di dettare al telefono tutte le modifiche apportate a quel foglio senza potervelo vedere. Questo è l’aspetto di un’iniziativa di ottimizzazione della supply chain guidata da professionisti, ma implementata da ingegneri del software (non specialisti in supply chain). Il business impiega un’enorme quantità di tempo per comunicare ciò che desidera all’IT; e l’IT impiega un’enorme quantità di tempo per cercare di capire cosa vuole il business. Dopo un decennio di esperienza a Lokad, osservo che affidarsi a sviluppatori software, che non sono specialisti in supply chain, per realizzare un’iniziativa di ottimizzazione quantitative supply chain moltiplica i costi di almeno un fattore 5, non importa quanto agile e talentuoso sia il team.
In secondo luogo, i costi di manutenzione dei prototipi Python affrettati raggiungono cifre esorbitanti. Al di fuori dell’industria del software, poche persone si rendono conto che l’ingegneria del software6 riguarda soprattutto il mantenere sotto controllo i costi di manutenzione. Eppure, risolvere i problemi di ottimizzazione della supply chain è un processo disordinato: i dati provenienti da molti sistemi (poco) affidabili devono essere incanalati in modo affidabile, processi imperfetti e in costante evoluzione vanno documentati e modellati, le metriche di ottimizzazione riflettono una strategia aziendale in continuo mutamento, ecc. Di conseguenza, qualunque pezzo di software venga scritto per realizzare l’ottimizzazione della supply chain, esso incorpora sempre una massiccia dose di complessità specifica del dominio, limitandosi a far fronte a ciò che il mondo ci lancia addosso.
Eppure, il tempo è essenziale. Non ha senso avere il piano perfetto per il piano di produzione dell’anno scorso. In linea di massima, è lecito presumere che, nel giorno in cui il prototipo software inizia a funzionare, questo verrà portato in produzione in poche settimane, indipendentemente dal fatto che il prototipo sia ben o male scritto.
Aspettarsi che il top management approvi un ritardo di 6 mesi per riscrivere il prototipo e renderlo adatto alla produzione dal punto di vista della manutenzione è un’illusione. Eppure, mettere in produzione un prototipo Python affrettato è la ricetta per costi di manutenzione epici, combattendo una battaglia in salita contro un flusso infinito di bug che dovranno essere riparati con del nastro adesivo 24/7.
Pertanto, l’unico modo pratico per mantenere la produzione sotto controllo è scrivere il prototipo con un linguaggio di programmazione che garantisca un alto grado di correttezza per progettazione. Per esempio, a differenza di Python, Envision fornisce:
- Tempo di esecuzione finito garantito a compile time: quando si elaborano diversi terabyte di dati, diventa estremamente faticoso dover attendere ore prima di rendersi conto che un calcolo non terminerà mai.
- Consumo di memoria limitato garantito a compile time: lottare contro errori di memoria insufficiente nel batch notturno di produzione è tutt’altro che divertente e, in pratica, interrompe gravemente le operazioni.
- Letture e scritture atomiche: Envision previene, per progettazione, letture e scritture concorrenti all’interno del filesystem, anche quando i file vengono trasferiti via FTP mentre gli script sono in esecuzione. Il filesystem che supporta Envision è praticamente un Git su misura per file flat enormi. Senza un adeguato versionamento dei dati, molti bug si trasformano in heisenbug: quando qualcuno si immerge nel problema, i dati sono stati aggiornati e il problema non può più essere replicato.
- Esecuzione in ambient scale-out del programma su una cloud di risorse di calcolo, eliminando tutti gli ostacoli alla parallelizzazione che sono inevitabili non appena i dati superano qualche decina di gigabyte.
I linguaggi di programmazione generici forniscono poca correttezza per progettazione; e Python, facendo largo uso del late binding, fornisce straordinariamente poco in quest’area. Anche considerando alternative migliori – dal punto di vista della correttezza per progettazione – come Rust, queste alternative sono tutt’altro che soddisfacenti per l’ottimizzazione della supply chain.
Ecco alcune altre aree in cui Envision eccelle in modi semplicemente non accessibili a Python:
Difesa in profondità: Non appena qualcuno inizia a scrivere codice nella vostra organizzazione, a meno che non vengano prese precauzioni molto speciali7, il loro codice diventa un’immediata responsabilità dal punto di vista della sicurezza IT. Con Python è praticamente possibile fare qualsiasi cosa sulla macchina che esegue lo script. Effettuare una corretta sandboxing di Python, nella pratica, è un problema di complessità infernale. In particolare, ogni stringa prodotta dallo script Python è un potenziale vettore di iniezione. Mentre le iniezioni SQL sono ben note, poche persone si rendono conto che anche file di testo semplici, come i CSV, sono vulnerabili ad attacchi di injection. Envision offre un grado di sicurezza che semplicemente non può essere replicato con Python. Le violazioni dei dati sono in aumento, e distribuire frammenti di Python ovunque non farà alcun bene alla sicurezza IT.
Prestazioni trasparenti: Se un programma è impropriamente lento nell’esecuzione, allora non dovrebbe nemmeno compilare fin da subito8. Se un programma viene accorciato di una sola riga, allora dovrebbe funzionare più velocemente. Se viene modificata solo una singola riga, solo quella riga dovrebbe essere ricalcolata9 durante la riesecuzione del programma sugli stessi dati. Durante la compilazione, il compilatore non dovrebbe mirare a una qualsiasi macchina, ma a una cloud di risorse di calcolo, fornendo una parallelizzazione automatica basata sui dati. Envision fa molto per fornire tutte queste proprietà di default senza alcuno sforzo di coding. Al contrario, in Python è necessario un uso massiccio di librerie specializzate per anche solo iniziare ad avvicinarsi a tali proprietà.
Aggiornamento trasparente: Lo stato dell’arte è un bersaglio in continuo movimento per quanto riguarda il software. Nel 2010, il miglior toolkit per il machine learning era SciPy (si potrebbe dire). Nel 2013, era scikit. Nel 2016, era Tensorflow. Nel 2017, era Keras. Nel 2019, era PyTorch. Esiste un detto nell’ingegneria del software secondo il quale si può datare l’anno di nascita di un progetto osservando il suo stack tecnologico e le sue dipendenze. Infatti, non appena distribuirete i vostri script Python, vi troverete con numerose dipendenze che potrebbero non invecchiare bene. Al contrario, con Envision, facciamo largo uso di riscritture di codice automatizzate10 per mantenere gli script “legacy” aggiornati in un linguaggio in costante evoluzione.
Stack confezionato: Gli script Python non possono vivere in un vuoto11. Il codice deve essere versionato (ad es. Git) con diritti di accesso (ad es. GitHub). Hanno bisogno di un ambiente in cui eseguire che non sia la vostra macchina (ad es. una VM Linux nel cloud). Serve uno scheduler per orchestrare la pipeline dei dati (ad es. AirFlow). È necessario uno strato di storage columnar distribuito per la preparazione dei dati (ad es. Spark). Occorre un toolkit di machine learning per l’analisi predittiva (ad es. TensorFlow). Occorre un toolkit di ottimizzazione per affrontare problemi combinatori della supply chain (ad es. GLPK). I risultati grezzi devono essere esposti da qualche parte per un successivo utilizzo (ad es. un server SFTP). I colleghi supply chain practitioners devono poter monitorare ciò che accade (ad es. un’interfaccia web). I diritti di accesso devono essere applicati (ad es. Active Directory), ecc. Envision semplifica tutto questo in una singola meta-app, eliminando il peso di dover assemblare dozzine di pezzi software per fornire anche l’app più basilare.
Poi, pur essendo un linguaggio eccellente, Python non è esente da critiche:
- Le prestazioni di calcolo sono scarse ed è una lotta in salita riuscire a canalizzare ogni singola operazione attraverso la libreria giusta (ad es. NumPy) per evitare prestazioni abissalmente scadenti nell’elaborazione dei dati. Inoltre, l’uso di più librerie tende a generare molta frizione quando i dati devono essere trasferiti da una all’altra.
- La performance della memoria è scarsa, e in particolare, la garbage collection basata sul conteggio dei riferimenti di Python è obsoleta - e tutti i linguaggi di programmazione più recenti come Java, C# o JavaScript utilizzano invece il tracciamento. Quando si affrontano compiti ad alta intensità di memoria con big data, questo penalizza.
- La gestione dei pacchetti in Python è stata un disastro per tanto tempo, e serve un specialista di pacchetti per sistemarla. Inoltre, questo problema è stato aggravato da aggiornamenti linguistici ad alta frizione.
- La maggior parte dei (pochi) controlli di correttezza avviene solo in runtime, quando il programma viene eseguito, il che è fonte di infinite frustrazioni quando si tratta di elaborazione dei dati. Problemi evidenti si manifestano solo dopo diversi minuti di esecuzione, riducendo la produttività.
In conclusione, sebbene Python sia fantastico (lo è), non è una risposta soddisfacente per l’ottimizzazione della supply chain. Costruire e mantenere un’app di machine learning a livello di produzione in Python è assolutamente possibile, ma i costi sono significativi, e a meno che la tua azienda non sia pronta ad avere almeno un piccolo team di ingegneria software dedicato alla manutenzione di questa app, l’intera soluzione non produrrà risultati soddisfacenti per la supply chain.
Sviluppare Envision, un linguaggio di programmazione specifico per il dominio dedicato all’ottimizzazione predittiva della supply chain, non è stata la nostra prima scelta. Non è stata nemmeno la nostra decima scelta. È stato più come l’unica soluzione funzionante che abbiamo ottenuto dopo aver esaurito una lunga lista di alternative più convenzionali in cinque anni. Sette anni dopo, e con molte aziende clienti alle spalle, ogni nuovo cliente riesce ancora a sorprenderci, in un modo o nell’altro, con un ulteriore svolta nella supply chain, che non saremmo mai riusciti a gestire con un approccio classico da enterprise. Era necessaria la programmabilità, ma Python non era la soluzione che ci serviva.
-
Nel 2013 ero ancora convinto che fosse possibile realizzare un’app soddisfacente per l’ottimizzazione della supply chain. In realtà, fu il confronto con le sfide dei prezzi a costringerci e a portare Lokad verso la creazione di un proprio linguaggio specifico per il dominio. Inizialmente questo linguaggio era destinato solo all’ottimizzazione dei prezzi, ma presto ci siamo resi conto che era esattamente ciò di cui si aveva bisogno per l’ottimizzazione della supply chain. ↩︎
-
L’idea che fornire una superiore accuratezza delle previsioni da solo porterebbe a una performance migliore della supply chain è probabilmente stata una delle più grandi idee sbagliate che ho avuto fondando Lokad. Guarda questo episodio di Lokad TV per una prospettiva più sensata su questo argomento. ↩︎
-
La maggior parte dei problemi che abbiamo identificato con Python non avevano a che fare con Python per se, che è un ottimo linguaggio di programmazione, ma semplicemente con il fatto che Python è un linguaggio di programmazione generico. ↩︎
-
Nel 2013, Python non aveva ancora raggiunto il dominio che avrebbe guadagnato nei pochi anni successivi nel campo del machine learning, R era ancora un forte contendente, tuttavia, SciPy e NumPy, due eccellenti librerie, erano già presenti e attive all’epoca. ↩︎
-
Guarda questo eccellente intervento Stop Writing Classes di Pycon 2012. Anche gli ingegneri del software più esperti tendono a commettere errori in tal senso. ↩︎
-
L’ingegneria del software, a differenza della computer science, si occupa di garantire il funzionamento dei sistemi di produzione, mentre la computer science è dedicata a risolvere problemi complessi, come scoprire algoritmi più veloci. ↩︎
-
Sfortunatamente, in materia di sicurezza del codice, non esiste praticamente alcun sostituto per revisioni sistematiche del codice da parte dei colleghi. ↩︎
-
A causa del problema della fermata, il lettore attento potrebbe dedurre che Envision non è un linguaggio Turing complete. In effetti, Envision non lo è. ↩︎
-
Envision si basa sulle differenze tra grafi computazionali e cerca di minimizzare il numero di ricalcoli tra le modifiche incrementali per permettere un prototyping molto rapido su grandi dataset. Tuttavia, a seconda della situazione, modificare una singola riga potrebbe richiedere di ricalcolare l’intero script. ↩︎
-
La riscrittura automatica del codice è estremamente difficile per un linguaggio di programmazione generico. A meno che il linguaggio e l’intera sua libreria standard non siano stati progettati con precisione tenendo conto di questo requisito, gli strumenti di aggiornamento automatico fanno ben poco in pratica. Durante la progettazione di Envision, sapevamo che avremmo commesso innumerevoli errori (e li abbiamo commessi), e per questo abbiamo prestato molta attenzione a rendere il linguaggio particolarmente adatto alle riscritture automatiche. Ad oggi, abbiamo effettuato oltre 100 riscritture incrementali dalla nascita di Envision. ↩︎
-
Ironia della sorte, “Batteries Included” è uno degli slogan di Python. Tuttavia, la quantità imponente di “colla” necessaria per mettere insieme tutti gli elementi richiesti per costruire un’app destinata all’ottimizzazione predittiva della supply chain è scoraggiante. ↩︎