X. Паритет окружений разработки и продуктива (Dev/prod parity)

Держите окружения разработки, промежуточного развёртывания (staging) и рабочего развёртывания (production) максимально похожими

Исторически существуют значительные различия между разработкой (разработчик делает живые изменения на локальном развёртывании приложения) и работой приложения (развёртывание приложения с доступом к нему конечных пользователей). Эти различия проявляются в трёх областях:

Приложение двенадцати факторов спроектировано для непрерывного развёртывания благодаря минимизации различий между разработкой и работой приложения. Рассмотрим три различия, описанных выше:

Резюмируя сказанное выше в таблицу:

Традиционное приложение Приложение двенадцати факторов
Время между развёртываниями Недели Часы
Автор кода/тот кто разворачивает Разные люди Те же люди
Окружение разработки/работы приложения Различные Максимально похожие

Сторонние службы, такие как базы данных, системы очередей сообщений и кэш, являются одной из областей, где паритет при разработке и работе приложения имеет важное значение. Многие языки предоставляют библиотеки, которые упрощают доступ к сторонним службам, включая адаптеры для доступа к различных типам сервисов. Некоторые примеры, в таблице ниже.

Тип Язык Библиотека Адаптеры
База данных Ruby/Rails ActiveRecord MySQL, PostgreSQL, SQLite
Очередь сообщений Python/Django Celery RabbitMQ, Beanstalkd, Redis
Кэш Ruby/Rails ActiveSupport::Cache Память, файловая система, Memcached

Иногда разработчики находят удобным использовать лёгкие сторонние службы в их локальном окружении, в то время как более серьёзные и надёжные сторонние сервисы будут использованы в рабочем окружении. Например используют SQLite локально и PostgreSQL в рабочем окружении; или память процесса для кэширования при разработке и Memcached в рабочем окружении.

Разработчик приложения двенадцати факторов сопротивляется искушению использовать различные сторонние сервисы при разработке и в рабочем окружении, даже когда адаптеры теоретически абстрагированы от различий в сторонних сервисах. Различия в используемых сторонних сервисах означают, что может возникнуть крошечная несовместимость, которая станет причиной того, что код, который работал и прошёл тесты при разработке и промежуточном развёртывании не работает в рабочем окружении. Такой тип ошибок создаёт помехи, которые нивелируют преимущества непрерывного развёртывания. Стоимость этих помех и последующего восстановления непрерывного развёртывания является чрезвычайно высокой, если рассматривать в совокупности за всё время существования приложения.

Установка локальных сервисов стала менее непреодолимой задачей, чем она когда-то была. Современные сторонние сервисы, такие как Memcached, PostgreSQL и RabbitMQ не трудно установить и запустить благодаря современным менеджерам пакетов, таким как Homebrew и apt-get. Кроме того, декларативные инструменты подготовки окружения, такие как Chef и Puppet в сочетании с легковесным виртуальным окружением, таким как Vagrant позволяют разработчикам запустить локальное окружение которое максимально приближено к рабочему окружению. Стоимость установки и использования этих систем ниже по сравнению с выгодой, получаемой от паритета разработки/работы приложения и непрерывного развёртывания.

Адаптеры для различных сторонних сервисов по-прежнему полезны, потому что они позволяют портировать приложение для использования новых сторонних сервисов относительно безболезненно. Но все развёртывания приложения (окружение разработчика, промежуточное и рабочее развёртывание) должны использовать тот же тип и ту же версию каждого из сторонних сервисов.