2009-02-24 2 views
10

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

Мандар сошел. Нам нужно реорганизовать класс монстров. Большая часть плана состоит в том, чтобы определить категории функциональности в своих классах с отношением has-a с классом монстра.

Это означает, что много ссылок, которые в настоящее время читать, как это:

var monster = new orMonster(); 
var timeToOpen = monster.OpeningTime.Subtract(DateTime.Now); 

скоро читать, как это:

var monster = new Monster(); 
var timeToOpen = monster.TimeKeeper.OpeningTime.Subtract(DateTime.Now); 

Вопрос: Как на Земле мы координируем такие изменения ? Ссылки на «orMonster» помещают каждый бизнес-класс. Некоторые методы вызывают буквально тысячи мест в коде. Гарантируется, что в любой момент, когда мы сделаем такой шанс, кто-то еще (возможно, несколько человек-elses) в команде будет проверен код, который вызывает свойство .OpeningTime

Как вы координируете такое крупномасштабное изменение без продуктивной шлифовки на остановке?

+0

С помощью Visual Studio щелкните правой кнопкой мыши «Найти все ссылки ...» и замените. – core

ответ

27

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

Для получения дополнительной информации см. Move Method в классике Мартина Фаулера, Refactoring.

+0

Это. И отмечайте, что они устарели или что-то еще, если ваш язык имеет эту функцию. Они все равно будут работать, но в среде IDE они получат уродливые подчеркивания/зачеркивания и заполнят консоль предупреждениями. –

10

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

1

Не рефакторируйте его.

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

И вместо этого: "monster.TimeKeeper.OpeningTime.Subtract (DateTime.Now)"

ли это: monster.SubtractOpeningTime (DateTime.Now). Не убейте себя точечным обозначением (отсюда и demeter)

2

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

7

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

6

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

http://dotnettipoftheday.org/tips/ObsoleteAttribute.aspx

+0

Удивительный отзыв. Хотел бы я дважды проголосовать за это. –

+0

Принимая это как ответ на 15 баллов, не так ли? Почти так же хорошо! ;) –

3

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

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

1

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

2
var monster = new Monster(); 
var timeToOpen = monster.TimeKeeper.OpeningTime.Subtract(DateTime.Now); 

Я не уверен, что его разворачивание и просто создание его частей доступно для публики. Это нарушает закон demeter и может привести к боли NullReference.

Я предлагаю подвергать хронометристу людям без участия монстра.

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

+0

С другой стороны, это может быть отправной точкой - разделить ее на функциональную, а затем удалить класс монстров на более поздний срок. – TofuBeer

+0

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

4

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

Это концентрирует поломку, когда вы сливаетесь - не весь цикл разработки.

Объедините это с предложением Патрика have the monster call the small monsters. Это позволит вам легко вернуться, если ваш объединенный клиентский код нарушит изменения этого клиента. Как говорит Патрик, вы сможете удалить методы монстра (теперь заглушки), как только вы докажете, что никто не использует его.

Я также рекомендую советы нескольких плакатов, чтобы разоблачить разбитые классы напрямую - не через монстра. Зачем применять только половину лечения? С такими же усилиями вы можете применить полное лечение.

И наконец: написать единичные тесты. Напишите много модульных тестов. О, мальчик, тебе нужны юнит-тесты, чтобы спокойно снять это. Я упоминал, что вам нужны модульные тесты?

+0

+1 Мои мысли точно. – si618

-2

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

1

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

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

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

Смежные вопросы