X. Parità tra Sviluppo e Produzione

Mantieni lo sviluppo, staging e produzione simili il più possibile

Storicamente, ci sono sempre state differenze sostanziali tra gli ambienti di sviluppo (lo sviluppatore che effettua delle modifiche live a un deployment in locale) e quello di produzione (un deployment in esecuzione raggiungibile dagli utenti finali). Differenze (o gap) che si possono raggruppare in tre categorie:

Un’applicazione twelve-factor è progettata per il rilascio continuo, tenendo così queste differenze al minimo possibile. A proposito di queste tre tipologie di differenze appena viste:

Riassumendo tutto in una tabella:

App Tradizionale App Twelve-factor
Tempo tra i Deployment Settimane Ore
Sviluppatori e Ops Sono diversi Sono gli stessi
Sviluppo e Produzione Divergenti Il più simili possibile

I backing service, come il database dell’applicazione o la cache, sono una delle aree in cui la parità degli ambienti è molto importante. Molti linguaggi offrono delle librerie che facilitano l’accesso a questi servizi, tra cui anche degli adattatori per questi tipi di servizi. Eccone alcuni:

Tipologia Linguaggio Libreria Adattatore
Database Ruby/Rails ActiveRecord MySQL, PostgreSQL, SQLite
Code Python/Django Celery RabbitMQ, Beanstalkd, Redis
Cache Ruby/Rails ActiveSupport::Cache Memory, filesystem, Memcached

Gli sviluppatori, inoltre, trovano utile usare dei servizi “leggeri” in fase di sviluppo, passando quindi a qualcosa di più serio e robusto in produzione. Per esempio, usando SQLite localmente e PostgreSQL in produzione. Ancora, un sistema di cache in locale in fase di sviluppo e Memcached in produzione.

Lo sviluppatore twelve-factor “resiste” a questa necessità, anche se gli adapter ci sono e funzionano in modo tale da astrarre in modo sufficiente tutte le differenze nella gestione. Nulla impedisce, infatti, a qualche altra incompatibilità di uscire allo scoperto quando meno ce lo si aspetta, soprattutto se in ambiente di sviluppo funziona tutto e poi, magari, in produzione i test non vengono superati. Il costo di questa differenza può risultare abbastanza alto, soprattutto in situazioni in cui si effettua il rilascio continuo.

Rispetto al passato, usare dei sistemi “light” in locale è una prassi poco convincente. Si pensi al fatto che alcuni servizi moderni come Memcached o PostgreSQL si possono installare e usare senza difficoltà tramite alcuni sistemi di packaging come Homebrew e apt-get. In alternativa, esistono anche alcuni tool di provisioning come Chef e Puppet, che combinati con sistemi di ambienti virtuali come Vagrant permettono agli sviluppatori di riprodurre in locale delle macchine molto simili, se non identiche, a quelle in produzione. Ne risente quindi positivamente il costo di deployment.

Tutto questo, sia chiaro, non rende gli adapter meno utili: grazie ad essi infatti il porting verso nuovi servizi, in un secondo momento, rimane un processo indolore. Nonostante questo, comunque, rimane scontato che sarebbe buona norma usare uno stesso backing service su tutti i deployment di un’applicazione.