Регулярно переписывайте программные компоненты, чтобы в конечном итоге не переписывать все.

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

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

В прошлом водопад был преобладающей моделью жизненного цикла разработки программного обеспечения (SDLC). У этого процесса был только один цикл проектирования и разработки, после которого программное обеспечение перешло на длительную стадию обслуживания, пока не умерло, что сделало «смерть» неотъемлемой стадией процесса.

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

Этот процесс получил дальнейшее развитие с практикой непрерывной интеграции и доставки (CI / CD), до такой степени, что граница между разработкой и сопровождением полностью стерлась. Программное обеспечение превратилось из неодушевленного в динамическое.

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

Переписать

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

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

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

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

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

Зачем переписывать?

Работать с запутанным кодом не так уж и весело. Вы должны потратить много времени, пытаясь прочитать и понять это, но на самом деле вы никогда этого не делаете. Когда вы, наконец, решаете прикоснуться к коду и что-то изменить, что-то неожиданно и ужасно ломается. Код больше не обслуживается. Так в чем же мы ошиблись?

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

  1. Выполните рефакторинг компонента. Заставьте код работать с новыми требованиями, применив обходной путь. Это «быстрое и грязное» решение.
  2. Перепишите компонент. Напишите код с нуля, основываясь на новых требованиях и уроках, извлеченных из старого кода. Это «медленное и чистое» решение.

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

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

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

Согласно Чистому коду: руководство по гибкому разработке программного обеспечения Роберта К. Мартина, самый быстрый способ писать код - медленно. Следовательно, быстрые рефакторы медленные, а медленные перезаписи на самом деле бывают быстрыми.

Когда переписывать

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

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

Регулярно переписывайте программные компоненты, чтобы в конечном итоге не переписать все.

Как переписать

Существует два типа перезаписи: внутренняя и внешняя.

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

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

Прекращение поддержки и принятие

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

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

Старый компонент получает статус устаревшего, который может быть обозначен его именем (т.е. MyComponent будет переименован в DeprecatedMyComponent или DEPRECATED_MyComponent, независимо от вашего соглашения) или в документации (например, JSDoc поддерживает ключевое слово @deprecated).

Зависимость / зависимое изменение

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

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

Заключение

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

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

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