Работа с богами - PullRequest
       19

Работа с богами

11 голосов
/ 12 декабря 2008

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

Например, представьте, что вы только что получили службу Windows для работы. Теперь в этой службе есть ошибка, и вам нужно выяснить, что делает служба, прежде чем вы сможете надеяться на ее исправление. Вы открываете сервис и видите, что кто-то решил использовать один файл для всего. Здесь есть метод Start, метод Stop, таймеры, вся обработка и функциональность. Я говорю тысячи строк кода. Методы под сотнями строк кода встречаются редко.

Теперь, если вы не можете переписать весь класс, и эти классы богов будут продолжать появляться, как лучше всего с ними справиться? С чего начать? Что вы пытаетесь сделать в первую очередь? Как ты справляешься с такими вещами, а не просто хочешь получить все, что нужно?

Если у вас есть какая-то стратегия, позволяющая просто сдерживать свой характер, это тоже приветствуется.

Советы на данный момент:

  1. Установить тестовое покрытие
  2. Код раскладной
  3. Реорганизация существующих методов
  4. Поведение документа при обнаружении
  5. Цель для постепенного улучшения

Edit:

Чарльз Конвей рекомендует подкаст, который оказался очень полезным. ссылка

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

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

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

Ответы [ 7 ]

9 голосов
/ 12 декабря 2008

Ой! Похоже на то место, где я работаю.

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

DotNetRocks недавно провел показ по работе с устаревшим кодом. Нет волшебной таблетки, которая заставит его работать.

Лучший совет, который я слышал, - начинайте постепенно оборачивать код в тестах.

4 голосов
/ 12 декабря 2008

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

4 голосов
/ 12 декабря 2008

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

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

3 голосов
/ 12 декабря 2008

Я чувствую твою боль. Однажды я решил что-то подобное для хобби-проекта, связанного с обработкой данных цифрового телевидения на моем компьютере. Сотрудник на форуме по аппаратному обеспечению написал замечательный инструмент для записи шоу, просмотра всего, что было, и многого другого. Кроме того, он проделал невероятно важную работу по устранению ошибок в реальных вещательных сигналах, которые нарушали стандарт. Он проделал потрясающую работу с планированием потоков, чтобы быть уверенным, что несмотря ни на что, вы не потеряете эти пакеты в реальном времени: на старом Pentium он мог записывать четыре потока одновременно, одновременно играя в Doom, и никогда не терял пакет. Короче говоря, этот код включает в себя массу больших знаний. Я надеялся взять некоторые фрагменты и включить их в свой собственный проект.

Я получил исходный код. Один файл, 22 000 строк C, без абстракции . Я часами читал это; была вся эта замечательная работа, но все было сделано плохо. Я не смог повторно использовать ни одну строку или даже одну идею.

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

3 голосов
/ 12 декабря 2008

Я тоже сталкивался с этой ситуацией.

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

Во-вторых, я идентифицирую основные алгоритмы и разлагаю их на части, используя систему нумерации, которая чередует цифры и буквы (это уродливо, но хорошо работает для меня). Например, вы можете посмотреть на часть алгоритма на 4 «уровня» глубиной, и нумерация будет 1.b.3.e или какая-то другая ужасная вещь. Обратите внимание, что когда я говорю «уровни», я не обязательно обращаюсь непосредственно к блокам управления или области видимости, но там, где я определил шаги и подэтапы алгоритма.

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

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

3 голосов
/ 12 декабря 2008

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

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

2 голосов
/ 12 декабря 2008

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

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

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

...