Как стать автором
Обновить
145.79

Почему код становится legacy?

Время на прочтение7 мин
Количество просмотров11K

Небольшая метафора

Написание кода похоже на соединение двух точек. Ожидаемо, что самым простым путем будет нарисовать прямую линию между точками А и Б. 

Writing code is like connecting two points

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

Давайте увеличим количество препятствий на порядок. Линия становится все более извилистой.

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

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

Но и это еще не всё. Представьте, что мы знаем лишь приблизительное положение точек, и единственный способ узнать его — запрашивать их местоположение каждые 5 минут? Походит на безумие, или еще нет?

What if we only knew the approximate location of points?

Усложним еще немного. Допустим, мы знаем только приблизительное положение точек.

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

Обсуждение

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

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

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

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

Да, с классической точки зрения, легаси - это старый код, который нужно поддерживать как internet explorer, или код, написанный человеком, который уже не работает в вашей компании.

Но в современном обиходе этот термин более широкий и обозначает плохой ломкий код.

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

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

Как решить эту проблему?

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

Но шаблонов проектирования недостаточно. Гораздо важнее знать, что мы быстро движемся в правильном направлении, нежели правильно двигаемся в неправильном. И да, в мире полно устаревшего кода, который следует лучшим шаблонам проектирования. Фактически, чрезмерное использование шаблонов проектирования сверх необходимого называется "оверинжинерингом".

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

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

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

  2. Использовать заранее продуманные решения для быстрого и контролируемого построения пути (шаблоны проектирования).

Code with correctness feedback and design patterns in place

Что в итоге

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

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

Почему разработка пользовательского интерфейса особенно склонна к Legacy?

Используя метафору с линией из примера выше, мы пришли к определению того, что такое legacy-код:

Legacy-код — это код, который очень сложно изменить, ничего не сломав в процессе, и его переписывание обходится так же дорого, как написание с нуля.

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

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

Дисклеймер: Все приведенные ниже примеры являются выдуманными, упрощенными и нужны только для иллюстрации — любое сходство с реальными людьми случайно.

От идеи до legacy

Greenfield — проект одного человека, создаваемый с нуля

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

Greenfield project

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

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

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

С некоторыми неудачами (мы же с вами в реальном мире живем) вы справляетесь. Всё сделано вовремя, все довольны.

Конец.

Проект Brownfield

Более вероятен вариант, при котором вы окажетесь в другой ситуации и будете работать над чьим-то проектом «с нуля».

Brownfield project

Вам будет гораздо сложнее понять мыслительный процесс человека, который создавал приложение до вас. Как он думал, что делал, зачем. Скорее всего, он не обращал много внимания на что-то, кроме требований, поэтому тестирования тут будет мало (если оно вообще будет). А логика будет куда более запутанной из-за упрощения разработки.

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

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

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

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

Шаг за шагом, и кодовая база станет тем, что называется legacy.

Legacy-проект

И даже пример выше не такой печальный, как самая частая ситуация —  работа над legacy-проектом в качестве разработчика.

Legacy project

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

Заключение

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

Далее в цикле:

  • Так как же сделать пользовательский интерфейс легкотестируемым и легкоизменяемым?

  • Decoupler MVU или как реализовать MVU архитектуру для UI приложений

Полезные ссылки

  1. Black Box Testing: An In-Depth Tutorial — Этот туториал на Guru99 предоставляет всестороннее руководство по тестированию черного ящика. В нем рассматриваются его методы, типы, приемы, преимущества и недостатки.

  2. Design patterns — Подробное руководство по шаблонам проектирования программного обеспечения. Каждый шаблон подробно объясняется с примерами, чтобы лучше понять, когда и где их использовать.

  3. SOLID Principles: Explanation and examples — Этот пост на FreeCodeCamp разбирает принципы SOLID в понятной форме с большим количеством примеров.

  4. Understanding Legacy Code: Этот сайт — отличный источник информации для понимания legacy-кода и стратегий эффективной работы с ним. Поможет вам ориентироваться и улучшать legacy-системы.

  5. Greenfield vs Brownfield: В этой статье на LinkedIn Giorgi Bastos подробно рассматривает концепции проектов greenfield и brownfield. Автор дает отличное представление о различиях, преимуществах и вызовах обоих подходов.

  6. Greenfield vs Brownfield in Software Development: Synoptek предоставляет подробное сравнение между разработкой программного обеспечения greenfield и brownfield, дополнительно улучшая понимание этих концепций и их влияния на разработку пользовательского интерфейса.

  7. Advantages and Disadvantages of White Box Testing: На JavaTpoint опубликовано сбалансированное представление о тестировании белого ящика и подробное обсуждение его преимуществ и ограничений.

  8. White Box Testing: Pros and Cons: Segue Technologies предлагает другую точку зрения на тестирование белого ящика, подробно описывая его плюсы и минусы. Эта статья поможет вам понять, почему тестирование белого ящика может быть частью проблемы при поддержке кода пользовательского интерфейса.

Теги:
Хабы:
Всего голосов 18: ↑17 и ↓1+20
Комментарии16

Публикации

Информация

Сайт
beeline.ru
Дата регистрации
Дата основания
Численность
свыше 10 000 человек
Местоположение
Россия