The Twelve-Factor App

X. Ισοτιμία dev/prod

Κράτησε τα περιβάλλοντα υλοποίησης, ελέγχου και παραγωγής όσο πιο όμοια γίνεται

Ιστορικά, έχουν υπάρξει μεγάλα χάσματα μεταξύ υλοποίησης (development) (ο προγραμματιστής να κάνει αλλαγές σε πραγματικό χρόνο σε μία τοπική ανάπτυξη της εφαρμογής) και της παραγωγής (production) (μία εκτελούμενη ανάπτυξη της εφαρμογής προσβάσιμη μόνο από τελικούς χρήστες). Αυτά τα χάσματα εκδηλώνονται σε τρία σημεία:

Η εφαρμογή δώδεκα παραγόντων είναι σχεδιασμένη για συνεχή αναπτύξη (continuous deployment) με το να κρατάει το χάσμα μεταξύ υλοποίησης (development) και παραγωγής (production) μικρό. Κοιτώντας τα τρία χάσματα που περιγράψαμε παραπάνω:

Συνοψίζοντας τα παραπάνω σε ένα πίνακα:

Παραδοσιακή εφαρμογή Εφαρμογή δώδεκα παραγόντων
Χρόνος μεταξύ αναπτύξεων Εβδομάδες Ώρες
Συγγραφείς κώδικα ή αναπτυκτές του κώδικα Διαφορετικοί άνθρωποι Ίδιοι άνθρωποι
Περιβάλλοντα υλοποίησης (dev) ή παραγωγής (production) Αποκλίνοντα Όσο πιο όμοια γίνεται

Οι υπηρεσίες υποστήριξης, όπως η βάση δεδομένων (database) της εφαρμογής, το σύστημα ουρών (queueing system), ή η προσωρινή μνήμη (cache), είναι ένας τόπος όπου η ισοτιμία dev/prod είναι σημαντική. Πολλές γλώσσες προγραμματισμού προσφέρουν βιβλιοθήκες οι οποίες απλοποιούν την πρόσβαση στην υπηρεσία υποστήριξης, συμπεριλαμβανομένων προσαρμογέων (adapters) για διάφορους τύπους υπηρεσιών. Μερικά παραδείγματα περιέχονται στον παρακάτω πίνακα.

Τύπος Γλώσσα Προγραμματισμού Βιβλιοθήκη Προσαρμογείς
Βάση δεδομένων Ruby/Rails ActiveRecord MySQL, PostgreSQL, SQLite
Ουρά εργασιών Python/Django Celery RabbitMQ, Beanstalkd, Redis
Προσωρινή μνήμη Ruby/Rails ActiveSupport::Cache Memory, filesystem, Memcached

Οι προγραμματιστές μερικές φορές βρίσκουν πολύ ελκυστικό να χρησιμοποιήσουν μια ελαφρά υπηρεσία υποστήριξης στο τοπικό περιβάλλον ανάπτυξής τους, ενώ μια πιο στιβαρή και εύρωστη υπηρεσία υποστήριξης θα χρησιμοποιηθεί στην παραγωγή. Για παράδειγμα, χρησιμοποιώντας την SQLite τοπικά και την PostgreSQL στην παραγωγή, ή την τοπική μνήμη διεργασίας για προσωρινή μνήμη κατά την υλοποίηση και το Memcached στην παραγωγή.

Ο προγραμματιστής δώδεκα παραγόντων αντιστέκεται στην ορμή να χρησιμοποιήσει διαφορετικές υπηρεσίες υποστήριξης μεταξύ υλοποίησης και παραγωγής, ακόμα και όταν οι προσαρμογείς θεωρητικά μπορούν να αφαιρέσουν τις επιμέρους διαφορές στις υπηρεσίες υποστήριξης. Οι διαφορές μεταξύ υπηρεσιών υποστήριξης σημαίνουν ότι μικρές ασυμβατότητες ανακύπτουν, που προκαλούν τον κώδικα που λειτουργούσε και πέρναγε τα τεστ στην υλοποίηση ή στον έλεγχο να αποτυγχάνει στην παραγωγή. Αυτού του είδους τα σφάλματα δημιουργούν τριβή η οποία είναι αντικίνητρο στην συνεχή ανάπτυξη (continuous deployment). Το κόστος αυτής της τριβής και της επακόλουθης μείωσης της συνεχούς ανάπτυξης είναι εξαιρετικά υψηλό όταν ληφθεί υπόψη η συσσώρευσή του κατά την διάρκεια του χρόνου ζωής της εφαρμογής.

Οι ελαφρές τοπικές υπηρεσίες είναι λιγότερο ελκυστικές από ότι ήταν κάποτε. Οι μοντέρνες υπηρεσίες υποστήριξης όπως το Memcached, η PostgreSQL, και το RabbitMQ δεν είναι δύσκολο να εγκατασταθούν και να τρέξουν χάριν στα μοντέρνα συστήματα πακεταρίσματος (modern packaging systems), όπως το Homebrew και το apt-get. Εναλλακτικά, τα εργαλεία δηλωμένων παροχών (declarative provisioning tools) όπως το Chef και το Puppet συνδυασμένα με ελαφρά εικονικά περιβάλλοντα (light-weight virtual environments) όπως το Docker και το Vagrant επιτρέπουν στους προγραμματιστές να τρέξουν τοπικά περιβάλλοντα τα οποία προσομοιάζουν κατά πολύ τα περιβάλλοντα παραγωγής. Το κόστος εγκατάστασης και χρήσης αυτών των συστημάτων είναι χαμηλό συγκρινόμενο με το πλεονέκτημα της ισοτιμίας dev/prod και της συνεχούς αναπτύξεως.

Οι προσαρμογείς στις διαφορετικές υπηρεσίες υποστήριξης είναι ακόμα χρήσιμοι, επειδή η μετάβαση σε νέες υπηρεσίες υποστήριξης γίνεται σχετικά αβασάνιστα. Αλλά όλες οι αναπτύξεις (deploys) της εφαρμογής (περιβάλλοντα υλοποίησης, ελέγχου, παραγωγής) θα πρέπει να χρησιμοποιούν τον ίδιο τύπο και έκδοση για κάθε μια από τις υπηρεσίες υποστήριξης.