Каковы ключевые моменты эффективной работы с устаревшим кодом? [закрыто]

133

Я видел книгу « Эффективная работа с устаревшим кодом», рекомендованную несколько раз. Каковы ключевые моменты этой книги?

Есть ли что-то большее в работе с унаследованным кодом, чем добавление модульных / интеграционных тестов, а затем рефакторинг?

Armand
источник
2
Конечно, дело в том, чтобы добавить тесты, а затем рефакторинг. Книга в основном о том, как вам удается тестировать невероятно запутанный код, и в этом есть много откровений. Скажем так, Перья не берут в плен!
Килиан Фот
9
Возможно, вы должны просто прочитать книгу
HLGEM
Хороший обзор здесь: andreaangella.com/2014/03/…
rohancragg

Ответы:

157

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

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

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

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

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

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

Безопасное сокращение зависимостей может быть сложным. Знакомство с интерфейсами, макетами и Dependency Injection - это чистая и приятная цель, просто не обязательно безопасная на данном этапе. Поэтому иногда нам приходится прибегать к подклассу тестируемого класса, чтобы переопределить некоторый метод, который обычно, например, запускает прямой запрос к БД. В других случаях нам может даже понадобиться заменить класс зависимости / jar на поддельный в тестовой среде ...

Для меня самая важная концепция, предложенная Feathers, это швы . Шов - это место в коде, где вы можете изменить поведение вашей программы без изменения самого кода . Встраивание швов в ваш код позволяет отделить тестируемый фрагмент кода, но также позволяет вам почувствовать поведение тестируемого кода, даже если это трудно или невозможно сделать напрямую (например, потому что вызов вносит изменения в другой объект или подсистему). , чье состояние невозможно запросить непосредственно из метода теста).

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

Петер Тёрёк
источник
5
Обратите внимание: когда в приведенном выше ответе говорится «модульные тесты», это фактически означает «автоматизированные тесты» . Для унаследованного приложения большая часть изначально полезных автоматизированных тестов будет фактически интеграционными тестами (где логика тестирования выполняет большую часть всего кода и может вызвать сбои из-за дефектов во многих разных местах), а не истинным модулем тесты (которые предназначены для анализа только одного модуля и выполнения гораздо меньших частей кода каждый).
Лутц Пречелт
99

Быстрые способы получить ключевые моменты эффективной работы с устаревшим кодом

MarkJ
источник
3
Ссылка на MP3 на этой странице Hanselminutes не работает, а ссылка на hanselminutes.com/165/…e - s3.amazonaws.com/hanselminutes/hanselminutes_0165.mp3 .
Питер Мортенсен
Спасибо Rosston за исправление ссылки PDF. Похоже, что objectmentor.com ушел - может, «Дядя Боб» обанкротился?
MarkJ
Я не уверен, что случилось с наставником объекта, но в эти дни дядя Боб работает на 7-й свет.
Жюль
40

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

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

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

Сколько времени потрачено на эту 20-летнюю унаследованную систему с миллионными линиями? Допустим, 20 разработчиков по 20 лет умножили на 2000 часов в год (они работали довольно усердно). Давайте теперь выберем число - у вас есть новые компьютеры и новые инструменты, и вы намного умнее, чем парни, которые изначально написали этот кусок $% ^^ - допустим, вы стоите 10 из них. У тебя есть 40 человеко-лет, ну, у тебя ...?

Таким образом, ответ на ваш вопрос есть гораздо больше. Например, эта процедура, которая состоит из 1000 строк (у меня есть несколько из которых более 5000), она слишком сложна и является частью спагетти. Потребуется всего лишь (еще одно четырехбуквенное слово) несколько дней, чтобы переформулировать его в несколько подпрограмм по 100 строк и еще несколько помощников по 20 строк, верно? НЕПРАВИЛЬНО. В этих 1000 строках скрыто 100 исправлений ошибок, каждая из которых является недокументированным требованием пользователя или неясным крайним случаем. Это 1000 строк, потому что оригинальная процедура из 100 строк не справилась с этой задачей.

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

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

mattnz
источник
2
спасибо за советы! Это твое или из книги?
Арманд
3
Вероятно, и то и другое - я прочитал книгу после нескольких лет выполнения этой работы, и, вероятно, должен прочитать ее agian. Как и любая хорошая книга, она заставит вас бросить вызов кое-чему из того, что вы делаете в настоящее время, усилить большую часть того, что вы делаете, но не имеет ответов на все ваши конкретные проблемы.
Mattnz
7
«Это 1000 линий, потому что обычная процедура 100 линий не справилась». Так что очень редко это действительно так. Чаще всего это 1000 строк просто потому, что первоначальный разработчик закатал рукава и начал кодировать, не пожалев ни минуты на планирование или дизайн.
Стивен Таусет
3
Нет. Я говорю, что в большинстве случаев (с которыми я лично сталкивался), 1000 строковых подпрограмм являются четким признаком того, что люди начали писать код, прежде чем думать о том, как написать правильную абстракцию. Процедуры с тысячами строк практически по определению слишком сложны. Вы говорите, что процедура с тысячами строк с сотнями скрытых, некомментированных исправлений является отличительной чертой ответственного разработчика?
Стивен Таусет
16
Если вы поверили каждому посту на этом сайте, каждый должен иметь дело с 1000-строчным кодом спагетти, но никто никогда не писал его. По моему опыту, 1000 (и 10000) линейных подпрограмм являются отличительной чертой разработчиков, которые делают все возможное с тем, что у них есть, чтобы предоставить то, что от них требуется, начальнику, который платит им зарплату. Я нахожу оскорбительным и высокомерным то, как многие разработчики могут свободно комментировать со стороны, не зная обстоятельств, и при этом никогда не подвергают критике свою собственную работу.
Mattnz
19

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

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

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

Майкл Браун
источник
6
+1 Отличное замечание: «Всякий раз, когда вам нужно внести изменения в унаследованный код, найдите время, чтобы удалить его унаследованный статус».
Джон
3
Снятие статуса Наследие, получите мой голос :)
Рэйчел
7

В скорлупе ореха это правда - добавление тестов и рефакторинг - вот что все это значит.

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

Одед
источник