Работа с унаследованным кодом: Риски, анализ проекта и стратегии работы

8 января 2014 г.

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

Сейчас я хочу рассмотреть более общий вариант работы со старыми или плохоработающими системами. Хочу дать ответ на вопрос: Что делать, если вам досталась в работу legacy system? В статье я буду использовать термины legacy system (унаследованная система) и legacy code (унаследованный код).

Вообще унаследованный не значит плохой по-умолчанию. Бывают унаследованные системы с отличной архитектурой, документацией и т.п. В этой статье унаследованный будет иметь негативную окраску. Я буду говорить о проектах с проблемами в архитектуре, плохим кодом, отсутсвием тестов и документации. В этих системах бывает много чего "так исторически сложилось", "это лучше не трогать", использованы устаревшие фреймворки, подходы к разработке, языки программирования и СУБД.

Что такое унаследованная система?

Какие признаки можно выделить для унаследованных систем:

  • Реализованы на старых технологиях и платформах
  • Используются устаревшие подходы к разработке, дизайну и архитектуре
  • Нет модульных и интеграционных тестов. Может при текущем дизайне вообще нельзя написать модульные тесты?
  • В систему трудно вносить изменения, она хрупкая, ломается в неожиданных местах, в целом может быть низкое качество кода
  • Плохой нечитаемый код со множеством запахов, иногда непонятно почему он вообще работает
  • Не автоматизированы рутинные операции, что периодически приводит к однотипным ошибкам и повышает bus-фактор.
  • Нет документации по системе и инфрастуктуре

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

Как системы становятся унаследованными? Можно выделить несколько популярных сценариев:

  1. Разработка началать много лет назад, за это время было реализовано много различной функциональности. Команды уже несколько раз полностью сменились. Разные части системы написаны в разном стиле. Такая система является большой ценностью для заказчика. Возможно система немного нестабильна, но для заказчика это не столь критично.
  2. Система разрабатывалась недолго, но командой с низкой технической компетентностью. Код оброс техническими долгами, является очень хрупким. Система почти остановила свое развитие и ждет героя, который проведет правильный рефакторинг. Изменения в системе, как и в предыдущем пункте, будут осложнятся тем, что ее уже используют в работе.
  3. Разработка первой версии оказалась неудачной (например, команда не справилась), система не была запущена. Теперь нужно сделать выводы из первого провала и реализовать всё как полагается.
  4. Ваша текущая система, которая раньше была такой небольшой и понятной, превращается в ужасного монстра, который выходит из под контроля. Нужно сломить ситуацию и сделать ее управляемой.

Риски и ответственность

Какие риски могут вас ожидать:

  • Унаследованные системы зачастую очень важны для заказчика. Этими системами уже пользуются, они уже приносят деньги, поэтому ошибки в коде могут очень дорого стоить.
  • Если система уже была запущена, то пользователи научились с ней работать, обходить проблемы, которые она содержит. Например, вы наверняка слышали в магазинах: "Сейчас система зависла, надо подождать немного, потом перезагрузить компьютер, потом я проведу оплату еще раз. Ничего страшного так бывает". Ваша новая реализация может быть будет лучше, но не забывайте про переобучение пользователей
  • Знания об истории развития унаследованной системы могут быть потеряны, поэтому вы рискуете забыть реализовать функциональность, которая была в старой системе
  • Или просто сломать то, что уже работает
    Например, недавно мы рефакторили большую систему, она заливалась на несколько идентичных серверов для баланса нагрузки. Как оказалось, только на одном из них в файле конфигурации менялся параметр, чтобы один из сервисов запускался. Информации об этом нигде не было. Через месяц узнали случайно от разработчика из предыдущей команды.
  • Из-за проблем в коде можно не сделать поставку новых функций к планируемой дате
  • Обычно работа идет под давлением сроков и большого количества технических долгов, это грозит потерей мотивации в команде
  • На некоторое время будет замедление разработки, т.к. вы будете входить в проект. Надо убедиться, что заказчик готов к этому

Допустим, взвесив все риски, вы согласились взяться за работу. В этот момент надо понять важную вещь. Для заказчика не будет разделения на "наш код" и "не наш код". Код теперь весь ваш, вы с ним работаете. Возникли неожиданные проблемы в неожиданном месте? Теперь это ваша проблема. Вы в этом не виноваты? Код был хрупким и поэтому всё сломалось? Для заказчика теперь вы отвественный за код, вам и решать все проблемы. Приготовьтесь к тому, что будете искать, отлаживать, профилировать унаследованную систему значительное время.

С точки зрения условий контракта я бы рекомендовал работать с унаследованными системами по T&M. Это частично снизит ваши риски. Работа по фиксированной цене и объему работы может быть опасна, т.к. унаследованные системы несут много сюрпризов. Есть риск сильно ошибиться, неправильно оценив объем работы.

Анализ унаследованной системы

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

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

Где находится исходный код?

Под контроль нужно взять изменения в исходном коде системы и всех подсистем. Я бы рекомендовал следить за всеми ветками во всех репозиториях, к которым удастся получить доступ. Это позволит избежать побочных эффектов работы предыдущей команды или её остатков, которые будут работать вместе с вами.

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

  1. Контроллировать все изменения, которые будут поступать от вашей команды и возможно от остатков старой команды
  2. Собрать все исходники системы и всех подсистем в одном месте

Где развернута система?

Скорее всего про инфрастуктуру системы будет известно немного. Вам необходимо будет провести аудит серверов, политик безопасности, настроек домена, настроек бэкапа и т.п. Это довольно тяжелая и кропотливая работа для системного администратора. О доступе к серверам я бы рекомендовал позаботиться заранее, т.к. возможно придется получать специальные разрешения, восстанавливать логины/пароли или искать "того единственного, который помнит пароль".

Если вам досталась актуальная документация инфрастуктуры, то это большая удача. В любом случае стоит ввести системного администратора в курс дела и дать ему задачу актуализировать документацию.

Какая версия сейчас работает?

Если системой уже начали пользоваться, то нужно понять, какая версия в данный момент залита на боевых серверах. Номер версии должен быть однозначно сопоставим с номером ревизии в системе контроля версий. Это вам пригодится при изучении работы системы, анализе её поведения, отладке и профилировании.

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

Как выпустить новую версию?

Выпуск новой версии системы и любой её части должен быть автоматизирован. В идеале, вам надо получить доступ к CI-серверу и убедиться, что выпуск новых версий делается одним нажатие кнопки.

Нередко в проектах нет CI. В этом случае нужно запланировать с заказчиком время и настроить CI. В выпуск версии вам стоит включить как минимум:

  1. Сборку последних версий всех проектов в системе
  2. Проставление номера текущей версии
  3. Модификацию файлов конфигурации под окружение
  4. Запуск автоматических тестов
  5. Выпуск артефактов для заливки

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

Если вы будете использовать TeamCity, то можно сразу включить плагины для анализа кода.

Интегрирована ли система с другими системами?

Перед тем, как вносить в унаследованную систему какие-то изменения, нужно получить схемы интеграции со сторонними проектами. Возможно система что-то выгружает или забирает со сторонних FTP, у нее есть публичные веб-сервисы, она делает выгрузки в бухгалтерские системы и т.д.

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

Стоит проверить есть ли интеграция со сторонними сервисами типа Google Webmaster, картами и т.п. В пример могу привести систему, которую мы недавно в срочном порядке доделывали. Одна из команд заказчика после заливки потеряла из индекса Google около миллиона страниц. Они сделали несколько измений в архитектуре системы и не убедились, что интеграция с Google работает корректно.

Если вам предоставили документацию обо всех точках интеграции, то её необходимо актуализировать.

Логирование работы

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

Если системы логирования нет, то эту систему необходимо развернуть до внесения изменений в код. Если эта система есть, но логи просто лежат на серверах, то надо настроить уведомления к вам на почту. Желательно прикрутить систему типа elmah, чтобы было проще обрабатывать логи со всех серверов.

Не надо бояться, что вас завалит ошибками. Вам нужна ситуация в системе "как есть", а поток ошибок, который вы увидите:

  1. Откроет глаза заказчику на реальную ситуацию на проекте
  2. Придаст вам дополнительную мотивацию поскорее всё исправить

Настроен ли мониторинг и аналитика?

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

Модульные и интеграционные тесты

Если в проекте есть модульные или интеграционные тесты, то это отличная возможность изучить сценарии работы системы. Для начала нужно прогнать все тесты, удалить пустые или бесполезные, чтобы они не висели техническим долгом. Бывают тесты, написанные ради увеличения покрытия кода, их тоже лучше удалить в самом начале. В проекте могут быть закомментированные тесты или отмеченны атрибутом [Skip], иногда их узучение может показать проблемы в проекте.

Зеленые тесты будут вашими лучшми друзьями, т.к. являются самой актуальной документацией к системе. Существующие тесты надо обязательно включить в CI, если этого еще не было сделано.

Если тестов недостаточно, то можно потратить некоторое время на Characterization Testing. Это позволит лучше изучить поведение системы.

Если тестов нет, то вам захочется покрыть код тестами. Здесь вы можете столкнуться с несколькими проблемами:

  1. Заказчик не выделяет время на покрытие кода тестами. Тогда QA обязательно должны сделать полное ручное тестирование системы и перед каждым релизом перепроверять регресс.
  2. Модульные тесты невозможно написать из-за ошибок в проектировании системы. В этом случае нежелательно кидать все силы на рефакторинг системы и постепенное покрытие кода тестами, т.к. этот процесс может затянуться, а при нехватке опыта оказаться безуспешным.

Где можно найти тестовые сценарии?

Перед внесением изменений всю систему надо протестировать. QA обязательно спросят про тестовые сценарии и документацию, чтобы сделать полное тестирование текущей версии. Также будет необходимо получить доступ к bug-tracker'у для актуализации известного списка ошибок и задач.

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

Какие требования предъявлялись к системе?

На протяжении разработки унаследованной системы к ней предъявлялся ряд требований. Желательно найти все документы/письма/страницы в вики проекта, где эти требования написаны. В них вы можете найти ответы на вопросы:

  1. Максимальное время отклика веб-интерфейса при обычной нагрузке
  2. Максимальное время отклика веб-интерфейса при пиковой нагрузке
  3. Ожидаемая нагрузка на систему
  4. Частота бэкапов
  5. ...

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

Очевидно, что список требований к системе нужно знать до начала внесения первых изменений. Команда QA должна провести анализ системы, уточнить какие из требований в данный момент выполняются, а какие нет. В дальнейшем QA должны постоянно проверять систему на соответствие этим требованиям и фиксировать улучшения или ухудшения ситуации.

Общие рекомендации для начала работы

  • Для анализа кода можно прогнать его через разлиные инструменты аналитики и визуализации. Например, можно взять NDepend или FxCop. После анализа можно исправить самые критичные ошибки, которые выявят инструменты, если заказчик выделит на это время. В самом начале работы над унаследованной системой проблем довольно много, поэтому эти метрики не сыграют решающей роли. Они покажут, что всё плохо с отчетами в сотни ошибок, но что это даст? Вы и так знали, что в проекте много проблем. По мере разработки эти инструменты будут всё более и более востребованы.
  • Заказчик может предложить тех. лида со своей стороны. Это довольно хорошая практика, но надо быть осторожными. Если этот тех. лид участвовал в разработке неудачной версии, которая провалилась, то он может продолжить реализацию ошибочных идей в вашей команде. Согласитесь, что трудно признавать свое творение ужасным. Мы однажды допустили такую ошибку, за что поплатились 4-мя месяцами борьбы со стереотипами, сложившимися на проекте.
  • Несмотря на это взять, разработчика из предыдущей команды, который находится на проекте на правах консультанта, это хорошая идея. Вы будете придумывать решения, которые прошлая команда уже пробовала и они оказались неудачными по ряду причин, специфичных для проекта. Эти знания о развитии проекта пригодятся в будущем.
  • Кроме численных метрик, вам будут нужны люди способные понять, что система становится лучше или хуже. Скорее всего это будет кто-то из отделов тех. поддержки, аналитики, сам заказчик или один из ключевых (или группа) пользователей. Используйте любые возможности для закрепления текущего состояния системы, чтобы при каждом изменении делать сравнение.
  • Нужно собрать и занести в таблицу все технологии, фреймворки, ОС, СУБД и т.п., которые используется в системе. Посмотреть их версии, выделить те, которые уже не поддерживаются и составить план по обновлению. Это довольно рискованные и длительные изменения, поэтому вряд ли заказчик даст возможность сделать это в начале вашей работы, но иметь эту информацию пригодится.
  • Если в системе нет тестового сервера (staging, UAT), то желательно его развернуть в самом начале. Это может оказаться трудоемкой задачей из-за сложности инфрастуктуры проекта или больших объемов данных, необходимых для работы системы.
  • Если в самом начале непонятно куда двигаться, то можно разделиться на несколько команд, каждая из которых будет идти по своему пути развития. Таким образом, вы сможете быстрее выработать нужные решения.

Стратегия изменения

После проработки вышепечечисленных вопросов вы должны понять, что за система вам досталось и в каком она состоянии. Теперь надо понять, как двигаться дальше.

Набор конретных тактик уже описан в книгах:

  1. Рефакторинг. Улучшение существующего кода про тестирование, Мартин Фаулер
  2. Рефакторинг с использованием шаблонов, Джошуа Кериевски
  3. Эффективная работа с унаследованным кодом, Майкл К. Физерс

В этих книгах разобраны конкретные примеры и даны ответы на вопросы про улучшение кода и его покрытие тестами. Например, что делать с длинным методом, который сложно тестировать? Как разорвать ненужные зависимости? Как убрать зависимость от статического класса? И многое другое. Рекомендую прочитать эти книги и 90% проблем в коде будут для вас не проблемой.

Я же предлагаю рассмотреть основные стратегии, которые можно использовать при работе с унаследованными системами, показать их плюсы и минусы.

1. Переписать

Вы смотрите на чужой код, видите в нем множество недочетов. Хочется просто написать правильно с нуля. Почему бы и нет? Один из возможных вариантов развития старой системы - это ее перерождние в greenfield-проекте.

Плюсы:

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

Минусы:

  • Заказчик оплатит создание той же системы во второй раз
  • Заказчик долго не увидит разницы между тем, что было и как стало. Первый релиз новой системы, который превзойдет старую систему по количеству фич, появится не скоро
  • Если система уже используется, то переписывание старых функций может занять значительное время
  • Вам придется поддерживать одновременно и старую и новую системы, до тех пор пока все пользователи перейдут на новую
  • Система может оказаться сложнее, чем вы изнально предполагали, есть шанс сделать также плохо как было или хуже. Вы не знаете всех нюансов системы и подсистем, которые копились годами.

Рекомендация, когда стоит браться за переписывание всей системы с нуля:

  1. Заказчик дает время и деньги на переписывание старой системы с нуля, а вы со своей стороны уверены в своих силах
  2. Систему еще не начали использовать, возможно она представляет из себя прототип или 'proof of concept'
  3. Система действительно не работает, пользователи отказываются от нее. Например, у нас был проект, который предыдущая команда писала год, в итоге он просто не соответствовал заявленным характеристикам. Дописывать или рефакторить его не было смысла. Мы проанализировали то, что было сделано не так и реализовали с учетом предыдущих ошибок новую версию с нуля

Пример проекта, когда пришлось полностью переписать первую неудачную версию.

2. Оставляем как было

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

Плюсы:

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

Минусы:

  • Заказчик может настаивать на том, чтобы не тратить время на абстрактное улучшение дизайна, а просто поправить пару критичных ошибок. Если код в системе плохой, то вы добавляете туда еще больше костылей и стараетесь быстрее избавиться от этого проекта
  • Есть шанс попасть в ситуацию, описанную Бруксом: "Все исправления имеют тенденцию к разрушению структуры, увеличению энтропии и дезорганизации системы. Все меньше сил тратится на исправление ошибок исходного проекта и все больше — на ликвидацию последствий предыдущих исправлений"
  • Реанимация системы в разы сложнее, чем создание новой. Для этой работы нужна высокая квалификация
  • Есть вероятность потратить время разработчиков и в итоге откатить все изменения

Рекомендация, когда стоит оставить всё как есть:

  1. Бизнесу не нужны новые функции, нужно только исправить часть существующих. Такое случается, когда дальнейшее развитие системы не планируется. Возможно, параллельно создается новая система, с новыми идеями на новый платформе.
  2. Нужно очень быстро дать результат, даже путем осознанного добавления костылей в код. Я понимаю, что это может усугубить ситуацию, но если заказчик с этого рывка получит огромную прибыль, то в дальнейшем сможет инвестировать её в другие стратегии работы с унаследованной системой
  3. Код достаточно хороший, есть тесты, архитектура отвечает требованиям клиента

3. Душитель

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

Метафора была описана у М. Фаулера в статье Strangler Application.

Плюсы:

  • Все плюсы первого подхода с полным переписыванием
  • Работа старой системы не останавливается и при этом мы добавляем новые функции
  • Заказчик сразу начинает видеть результаты своих вложений
  • Если унаследованная система построена на Event Sourcing или с общей шиной, то реализация перехвата событий будет очень простой

Минусы:

  • Если в системе были серьезные ошибки, то нам придется исправлять их в унаследованном коде
  • Есть опасность "не додушить" (например, финансирование закончится или прекратите работу с заказчиком), тогда система станет еще большим чудовищем с двумя головами
  • При сложной и запутанной архитектуре унаследованной системы этот подход может быть трудно реализуем
  • На мой взгляд это один из самых сложных подходов, который требует хорошего предварительного анализа и высокого уровня разработчиков

Рекомендация, когда стоит "душить":

  1. Унаследованная система стабильно работает
  2. В основном надо добавлять новые функции, а не расширять уже существующие

4. Переработка по модулям

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

Плюсы:

  • Постепенное улучшение качества системы
  • Возможность сделать постоянную скорость поставки, не максимально высокую, но стабильную
  • Пользователи продолжают работать с уже знакомой системой, получая периодические обновления

Минусы:

  • Не будет резкого скачка качества системы, возможно скорость разработки будет слишком низкой для заказчика
  • Не всегда возможно выделить модули (добавление от hazzik)

Рекомендация, когда стоит постепенно переписывать по модулям:

  1. Унаследованная система имеет высокую ценность для заказчика
  2. В системе реализовано много отлаженных модулей
  3. В основном надо расширять уже существующие функции

Поддержка и развитие

Мы рассмотрели в основном технические вопросы при работе с унаследованными системами. Только технических изменений не будет достаточно для долгосрочного успеха. Например, внедрение CI или Continuous Deployment в корне меняет сами подходы, которые были на проекте.

Для успеха проекта нужно поменять культуру разработки. Привить новые ценности владельцам продукта и пользователям. Убрать все потери, автоматизировать рутину.

Была ли в вашей практике работа с унаследованной системой с плохим кодом? Удавалось ли выбросить плохой код и убедить заказчика переписать всё с нуля? Если она была успешно изменена, то что вам помогло решить проблемы? Если успеха не было, то что стало проблемой?

Кроме того, вы можете заказать у меня анализ вашей системы и план по ее переработки.

Истории работы с унаследованными системами

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

28 комментариев:

  1. Да, об одном из прошлых. Что-то подсказывает, не я один сталкивался с такой ситуацией

    ОтветитьУдалить
  2. У меня было такое дважды. Первый раз я всё досконально обосновал, сделал прототип, но никто не слушал. Пришлось уйти с работы.
    Второй раз я тоже всё обосновал и достучался до директора компании. После этого за месяц мы переделали весь говнокод, который копился в системе год. Все оказались в плюсе.
    Я думаю надо пробовать одходчиво объяснять, а уж если не слышат, то не стоит на них время тратить.

    ОтветитьУдалить
  3. Поддерживаю. Единственное, что мне непонятно - как на проблемы в проекте могут закрывать глаза люди с огромным опытом в IT, в разы больше моего. Если схожее отношение заказчика еще как-то объяснимо, то человека из IT - я даже не знаю. Может это синдром перехода в менеджмент?

    ОтветитьУдалить
  4. Да множество причин. Возможно опыта много (по времени), а глубины понимания нет. Или стало плевать на работу. Или сидит на теплом месте и страшно брать на себя ответственность за такие решение. В общем, куча причин :)

    ОтветитьУдалить
  5. Так случилось, что последние два года я и мои коллеги занимались только работой с унаследованным кодом. Всё, что накопилось, я описал в статье.

    На счет книги, я ее указал среди трех книг в списке "Набор конретных тактик уже описан в книгах...". В любом случае спасибо за уточнение.

    ОтветитьУдалить
  6. В "Переработка по модулям" ты не учитываешь "минус", когда невозможно эти самые модули выделить.

    ОтветитьУдалить
  7. Вообще, на мой взгляд, любой код после того, как попадает в главный репозиторий становится унаследованным.

    ОтветитьУдалить
  8. Точно, я ведь хотел написать про это, но второй пункт оказался копипастом из предыдущего. Спасибо, сейчас поправлю.

    ОтветитьУдалить
  9. У Фаулера буквально вчера вышла статья Branch By Abstraction о том, как изолировать и рефакторить унаследованные системы http://martinfowler.com/bliki/BranchByAbstraction.html

    ОтветитьУдалить
  10. Спасибо за ссылку, пополнит коллекцию.
    Что-то похожее было у Eric Evans с Anti-Corruption layer и чем-то подход напоминает "душителя".

    ОтветитьУдалить
  11. Вообще ссылка всплыла из "Workflows of Refactoring" из части "Long Term Refactoring" http://martinfowler.com/articles/workflowsOfRefactoring/ и скорее всего была написана именно для статьи по рефакторингу.


    Это скорее техника где-то по-середине между душителем и по-модульной переработкой. Такой микро-душитель на уровне модулей, а не системы.


    Подходит, когда невозможно выделить четкие границы модулей.


    Работает примерно как клин или топор.

    ОтветитьУдалить
  12. Не, лучше "Топор абстракции"

    ОтветитьУдалить
  13. Добавлю :)
    1. Признаки: к признакам унаследованной системы я бы добавил еще один пункт, который считаю самым главным - нарушение проектирования БД, что обязательно должно быть выявлено при анализе перед тем, как заключать контракт по T&M. Чаще всего проекты развиваются годами и скорость изменений фреймворков идет гораздо быстрее, чем метода проектирования баз данных в СУБД, поэтому чаще всего мы готовы переписать "морду" приложения, но как только мы погружаемся в структуру БД, у многих опускаются руки, т.к. применение того же ORM и работа по DDD никак отдельно не живет от структуры хранения. Исправление структуры данных - это чаще всего приведение к правильной НФ.
    2. Сценарии: компания купила еще одну со своей системой и командой, и необходимо скрестить их работу в совместную КИС. Здесь вариант развития может быть и переход к SOA-архитектуре, как один из методов интеграции.
    3. Стратегия изменений: добавил бы книгу для прочтения "Рефакторинг баз данных"
    4. Далее по подходам изменений есть пара вопросов. Ну, если есть теория, то почему бы ее не подкрепить реальными примерами, ведь народ читает про подход, но точка приложения в голове у них не усваивается, поэтому статься - снова только теория. Никто не опирается на плюсы и минусы при выборе, они вообще следствие и в компаниях делается для конкретной системы свой SWOT-анализ.

    ОтветитьУдалить
  14. Олег спасибо за добавления.
    На счет описания примеров, я думал их добавлять, но тогда статью бы никогда не закончил, она и так огромная. В дальнейшем буду описывать изменения в системах, которые были на практике.

    ОтветитьУдалить
  15. Как раз недавно писал про полное переписывание системы после первой неудачной попытки http://blog.byndyu.ru/2013/12/intergration-patterns.html

    ОтветитьУдалить
  16. Во-первых, с вашим кодом начинают работать другие программисты и для них он по определению унаследованный.


    Во-вторых, вы и вы из прошлого это два совершенно разных человека. Прошлый "вы" знает, скорее всего, гораздо меньше вас настоящего. У вас настоящего гораздо больше сведений о том, как работает система и т.д.


    У вас никогда не было такого, вы открываете проект, и думаете: "о боже, какой чудак написал ЭТО?", а git blame (к примеру) показывает, что это были вы месяца два назад?


    В-третьих требования постоянно изменяются


    Ну и так далее.

    ОтветитьУдалить
  17. Тем не менее, отличный RoadMap, спасибо Саша!

    ОтветитьУдалить
  18. Спасибо, Олег! Я вообще отчасти статьи для себя, чтобы не забыть :)

    Например, вот эту http://blog.byndyu.ru/2010/11/stand-up-meeting.html и http://blog.byndyu.ru/2012/09/pair-programming.html

    Такие чек-листы для самопроверки.

    ОтветитьУдалить
  19. Ясно. Отчасти согласен. )

    ОтветитьУдалить
  20. Тогда весь код можно считать legacy по умолчанию и отказаться от этого термина. Если мы его вводим, то для того, чтобы все-таки разделить на legacy и не очень :)

    ОтветитьУдалить
  21. Ну для меня так и есть. Весь код по умолчанию legacy. В моей теории не legacy код, это тот код, который еще не зафиксирован в главном репозитории, т.е. тот, который живет в feature branch, в локальном репозитории или в незавершенном pull request и т.д.


    Встречный вопрос: какой код является legacy?

    ОтветитьУдалить
  22. Ну, т.е. если ты вернешься к своему коду во feature branch через месяц, он также может быть для тебя legacy, если скорость твоего обучения достаточно высока, чтобы считать его устаревшим. Таким образом нет разницы зафиксирован он в главном репозитории или нет. Я думаю, что сам термин означает принадлежность к чему-то, т.е. в к лицу или группе разработки. Другими словами - тот код, которого ты никогда не касался, а был написан другими.

    ОтветитьУдалить
  23. Хорошая статья. Но есть ряд моментов. Например, "Для начала нужно прогнать все тесты, удалить пустые или бесполезные, чтобы они не висели техническим долгом. Бывают тесты, написанные ради увеличения покрытия кода, их тоже лучше удалить в самом начале." - действительно ли есть нужно это делать в самом начале, когда только изучаешь систему и есть шанс ошибиться и удалить нужное? Что такое "пустые" тесты? Что такое тесты "для покрытия"?

    ОтветитьУдалить
  24. Действительно подробнее расписать этот абзац, иначе может возникнуть заблуждение.

    Тут ход мыслей какой: Смотрим код -> Не понимаем его -> Смотрим тесты на код -> Начинаем понимать что делает. Т.е. в самом начале только тесты и помогают разобраться, если они есть.

    > Что такое "пустые" тесты?

    Пустые тесты, это пустые тесты :) В них есть название, открывающая скобка и закрывающая, вообще нет кода, они проходят и прибавляют кол-во тестов в системе. Целенаправленно заниматься только удалением пустых тестов не надо, но надо удалять их по мере нахождения.

    > Что такое тесты "для покрытия"?

    Заказчики могут выдвигать требования о минимальном % покрытия кода тестами. В этом случае, чтобы догнать % до нужного разработчики начинают писать тесты, которые ничего не тестируют, а просто гоняют код. В них часто нет Assert. Опять же просто тратить время на их выявление не стоит, но при обнаружение лучше сразу удалять.

    ОтветитьУдалить
  25. так я себе приблизительно и представил. Но это жесть конечно :) (я про пустые тесты и без проверок). Ясно, спасибо.

    ОтветитьУдалить
  26. не "повышают bus-фактор", а наоборот понижают! чем меньше bus-фактор, тем хуже.

    ОтветитьУдалить
  27. Bus-фактор равный 1 означает, что только 1 человек знает, что творится в коде :) Я имел ввиду повышают отрицательный эффект от этого. Спасибо, тут не совсем точно написал!

    ОтветитьУдалить

Моя книга «Антихрупкость в IT»

Как достигать результатов в IT-проектах в условиях неопределённости. Подробнее...