Эта статья была составлена (и отредактирована) из двух статей Николаса: «Что такое закон о наследстве? Это код без тестов?» и «Ключевые моменты для эффективной работы с унаследованным кодом.«. Казалось бы, логично рассказать, что такое наследие и как с ним работать.
Что такое legacy code?
Я не могу найти перевод. Можете ли вы объяснить в двух словах, что это такое? В чем смысл?
Посмотрите его на сайте foldoc (Free On-Line Dictionary of Computing). Правда ли, что определение
@deprecated — это не тег, а подсказка. Он используется для пометки элементов публичного API, которые больше не рекомендуются и должны быть удалены в будущей версии библиотеки.
@ Grundy, другими словами, если этот код был унаследован от предыдущих разработчиков, является ли он по определению унаследованным кодом? И это не может быть «не наследие»?
Таким образом, вы можете сказать «наследие», если весь код является наследием, включая классы импорта. Является ли весь код наследием в широком смысле этого слова?
5 ответов 5
Унаследованный код — это тяжелое наследие : ) Унаследованный код, который больше не поддерживается и не обновляется, но используется. Второе значение — код от сторонних разработчиков или от старых версий.
«Тяжелое наследие» — это сильно сказано! ИМХО второе значение все же более правильное, с учетом уточнения @Barmaley о наследии.
Собрав воедино все определения, которые я нашел, я пришел к следующему выводу.
Код наследования — код, соответствующий одному или нескольким атрибутам:
- написанные другими разработчиками, которые могут быть больше недоступны для общения,
- которые не покрываются модульными тестами,
- поддерживается для совместимости с предыдущими версиями системы,
- устарели и/или больше не поддерживаются в связи с эволюцией системы (написаны на более раннем языке, для более старой архитектуры, аппаратной платформы, операционной системы и т.д.).
Требование «опыт работы со старым кодом» в описании вакансии означает, что вам будут давать код, написанный 10-20 лет назад разработчиками-пенсионерами. Скорее всего, код изначально был написан плохо, требования проекта менялись несколько раз, и каждый раз код исправлялся в строго установленные сроки без написания документации и рефакторинга. Поэтому вместо того, чтобы писать новый код с использованием передовых технологий, вам приходится тратить большую часть своего времени на анализ и исправление старого кода, а затем отслеживать повторяющиеся ошибки. Добро пожаловать в удивительный мир проклятого предприятия, основного пользователя Java.
@sergiks написал правильно, но позвольте мне уточнить: В целом, термин «наследие» в программировании означает прилагательное, обозначающее принадлежность к какому-либо наследию. Например, legacy driver означает драйвер от производителя и т.д.
Существует также «унаследованный код», который никто не знает, как он работает. Только программист здесь вряд ли поможет — нужен либо аналитик, либо data scientist, а программист максимум, что может написать это интерфейс для них, если его нет, т.е. с точки зрения того, что можно извлечь из того, что есть в коде.
Чрезвычайно активный вопрос. За ответ на этот вопрос вы получите 10 баллов репутации (без учета бонуса за регистрацию). Требование репутации помогает защитить этот вопрос от спама и отсутствия ответов.
Связанные
Чтобы подписаться на канал, скопируйте и вставьте эту ссылку в свой RSS-ридер.
Дизайн/логотип сайта © 2022 Stack Exchange Inc; материалы пользователей лицензированы по CC BY-SA. rev 2022.10.4.22331
Нажав кнопку «Принять все файлы cookie», вы соглашаетесь с тем, что Stack Exchange будет хранить файлы cookie на вашем устройстве и делиться информацией в соответствии с нашей политикой использования файлов cookie.
Теперь вы можете использовать библиотеку для изучения контекста запущенного приложения. В следующем примере мы берем хост/порт, на котором запущена каждая служба. Примечание: Чтобы избежать конфликтов на сервере, порты отображаются так, чтобы они менялись при каждом последующем запуске.
Что такое легаси в программировании
Унаследованный код — Унаследованный код — это код, который команда разработчиков «унаследовала» от предыдущей команды. Это общее среднее определение, которое описывает термин унаследованный код.
Легаси – термин, который трактуют по-разному
Как видно из названия, этим дело не ограничивается: термин имеет около дюжины определений, все они более или менее вращаются вокруг феномена «унаследованного» кода; вот, например, несколько известных:
Наследие — это устаревший код, который больше не поддерживается, не обновляется, но все еще используется,
Наследие — это код, который не охвачен тестированием или документацией и был написан очень давно, настолько давно, что никто не знает, как он будет работать до конца.
В общем, оставим это здесь (хотя вариации все равно есть), главное, что основная идея ясна: наследие — это наследие в негативном смысле. В своей практике автор этой статьи никогда не слышал вызова, который хорошо покрыт тестами и документацией, но очень старый унаследованный код.
Общие характеристики или как появляется легаси
Не все точки должны совпадать, достаточно одной.
Во-первых, код был написан программистами, с которыми больше нельзя связаться. По этой причине нынешняя команда не может понять, как работают некоторые целые модули. Это очень проблематично, если этот старый код находится в ядре приложения (обычно так и бывает).
Во-вторых, код модуля был написан давно на другом языке программирования или в старом фреймворке, он активно используется в текущей программе, но все новые возможности добавляются более новыми технологиями.
В-третьих, код, который оставлен только для обратной совместимости: для поддержки старых версий программ или операционных систем.
В примерах используется Composer для управления зависимостями пакетов и Symfony Dependency Injection в качестве IoC-контейнера для сервисов. У вас может быть другой контейнер. Если в вашем приложении нет IoC-контейнера, вам придется перенастроить и внедрить Dependency Injection. Простейший пример добавления IoC-контейнера в приложение.
Тест определения характеристик
В начале своей карьеры я работал над приложением, разработанным другим разработчиком. Сам продукт стал неотъемлемой частью продуктовой линейки компании, но разработчик в итоге разочаровался и ушел из компании в другую сферу деятельности. Приложение было непроверенным и изобиловало всевозможными хаками. В итоге получился высокоинтегрированный код, который было трудно разделить. Прежде чем приступать к ремонту, вам нужен прочный фундамент, на котором вы будете стоять.
В своей книге «Эффективная работа с унаследованным кодом» Майкл Фезерс предлагает стратегию для выявления и сохранения истинного поведения системы.
Он состоит из следующих этапов:
1. использовать фрагмент кода в тестовой системе.
2. напишите утверждение, которое априори будет неудачным.
3. определить поведение на основе этого сбоя.
4. измените тест так, чтобы он ожидал поведения идентифицированного кода.
Чем больше тестов добавляется для выявления особенностей, тем лучше как понимание самого кода, так и уверенность в его изменении. Вы можете создать тесты, которые обнаруживают ошибку или нехарактерное поведение — это прекрасно, пометьте их все как подозрительные, чтобы изучить их позже. Стоит отметить, что мы не пишем здесь тесты «черного ящика». Мы можем направить тесты на определенные участки кода, которые мы не до конца понимаем, чтобы повысить нашу уверенность в них.
Характеризующие тесты могут быть эффективно применены на уровне модульных тестов с типичными преимуществами скорости, краткости и простоты. Однако многое в поведении часто становится очевидным только при сборке модулей. В отличие от хорошо протестированного кода, унаследованный код также имеет тенденцию к запутанным зависимостям и нечетким областям ответственности, что значительно усложняет изоляцию компонентов для модульного тестирования.
Legacy in a box + Test Containers
Отличным ресурсом для отслеживания общих тенденций отрасли является Thoughtworks Technology Radar, который несколько лет назад расширился, включив в себя Legacy in a Box — стратегию, облегчающую разработчикам работу с устаревшим программным обеспечением.
Работа с унаследованным кодом, особенно с большими монолитами, очень расстраивает разработчиков и отнимает у них много времени. Чтобы уменьшить сложность этого процесса, мы начали использовать контейнеры Docker для создания неизменяемых образов унаследованных систем и их конфигураций. Цель — изолировать унаследованную систему внутри коробки, чтобы она могла работать локально без необходимости перестраивать, перенастраивать или совместно использовать окружение (Thoghtworks).
При таком подходе мы помещаем живую версию унаследованного приложения, поддерживаемую его зависимостями, в контейнерную среду. Более того, это немодифицируемые образы, которые можно создавать и уничтожать по своему усмотрению — конфигурация везде одинакова, поэтому больше нет никаких оговорок о том, что это работает на моем устройстве.
Последняя часть головоломки заключается в успешном взаимодействии с этими контейнерами. Конечно, можно использовать команды оболочки (Docker/Docker compose), но есть и более удобные способы.
Test Containers — это библиотека Java, которая облегчает использование контейнеров Docker в качестве интегрированной тестовой среды. Он предоставляет удобную функцию вложения стека для управления и мониторинга выполнения контейнеров в вашем тестовом наборе. Этот инструмент неоценим для упрощения всего процесса.
Практический эксперимент
Давайте проанализируем небольшой эксперимент. Во-первых, нам нужен пример приложения — в качестве кандидата мы возьмем REST-клиент Spring Petclinic.
Этим я не хочу сказать, что данное приложение для ветеринарных клиник является наследием — наоборот.
- Это приложение с определенной сложностью (т.е. не приложение «hello world»).
- Имеет зависимости и статус — база данных SQL.
- Это программное обеспечение, написанное кем-то другим, поэтому мы можем работать с ним так, как если бы это был незнакомый нам проект.