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

Мы решили использовать Require.js’s AMD [определение асинхронного модуля] для отложенной загрузки. Нам пришлось изменить наши файлы Javascript. И нам также нужно было применить определенные методы к внешним библиотекам [например, JQuery] для поддержки AMD. Мы начали с этого и поняли, что попадаем в черную дыру, так как нам пришлось буквально менять весь JS-код. Мы никак не отреагировали на наше обучение. И на полную поддержку AMD ушло около двух недель.

Мы увидели изменения в производительности приложения. Но как команда мы чувствовали себя ужасно, потому что в это время мы не могли работать ни над чем другим, потому что:

  • Это заняло больше времени, чем ожидалось, поэтому вся команда пыталась закончить быстрее.
  • За это время приложение было несколько сломано, поэтому развернуть что-то на продакшн не представлялось возможным.

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

Учимся на собственном опыте

Мы столкнулись с похожей ситуацией в недавнем прошлом. Мы разрабатывали приложение, которое позволяло пользователям создавать собственные дизайны, которые они могли печатать на своих футболках или толстовках. Мы использовали RGhost для создания дизайнов в формате PDF, но позже поняли, что из-за определенных ограничений RGhost лучше использовать LaTex.

Мы не хотели повторять прежнюю ошибку. Решили переписывать небольшими партиями. Мы написали слой абстракции для генерации PDF примерно так:

И мы меняем одну функцию за функцией на новую реализацию. Мы также добавили переключатель функций, чтобы переключиться на старую реализацию в случае, если мы обнаружим проблему в рабочей среде.

Подход работал хорошо, потому что мы могли точно настроить новую реализацию с учетом опыта производства. И так как это было небольшими партиями, и было нормально завершить порт за несколько недель, так как от этого не было никакой зависимости.

Филиал по абстракции

Вышеупомянутый метод известен как Ветвь по абстракции, т.е. введение уровня абстракции поверх существующей реализации.

Добавьте еще один уровень абстракции для новой реализации и перенаправьте на него по мере готовности.

Вы можете визуализировать Branch by Abstraction с помощью следующего примера, данного Полом Хаммантом. Рассмотрим замену колес автомобиля с условиями:

  • Механики должны иметь возможность одновременно работать с обивкой, двигателем и т. д.
  • Автомобиль должен быть управляемым после каждой замены.

Он работает и в больших масштабах. Этот кейс рассказывает о двух существенных изменениях, реализованных с помощью Branch by Abstraction, а именно:

  • Переход с iBatis на Hibernate [известные ORM в мире Java]
  • Переход от Velocity и JsTemplate к JRuby on Rails

Каждый коммит должен быть готов к развертыванию

Основная разработка и переключатели функций в значительной степени помогут вам достичь этой мантры. Но вопрос в том, как вы справляетесь со значительным рефакторингом или переписыванием?

Используйте шаблоны, такие как Branch by Abstraction или Expand Contract Pattern, для непрерывного развертывания больших рефакторингов или изменений в базе данных небольшими партиями.

Да, для правильного использования абстракций требуется дисциплина. Но почему бы и нет, если та же помощь для более качественного обслуживания.

Обновленная версия предыдущего сообщения, опубликованного на www.multunus.com.