Наследование интерфейса для разрушения объектов бога?

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

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

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

Поскольку у меня есть интерфейс (и почти весь код был переработан для использования интерфейса), у меня возникла интересная идея. Что, если бы я сделал интерфейс ISession унаследованным от других интерфейсов.

Например, если бы у нас было что-то вроде этого:

interface IBar
{
  string Baz{get;set;}
}

interface IFoo
{
  string Biz{get;set;}
}

interface ISession: IFoo, IBar
{
}

Таким образом, существующий код, использующий ISession, не нужно будет обновлять, равно как и фактическую реализацию. Но в новом коде, который мы пишем и рефакторим, мы можем использовать более детализированные интерфейсы IFoo или IBar, но передавать ISession.

И, в конце концов, я вижу, что это, вероятно, облегчит в конечном итоге разделение фактического интерфейса/объекта бога ISession и Session.

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


person Earlz    schedule 08.02.2013    source источник
comment
+1: это звучит как разумный способ выполнить пошаговый рефакторинг.   -  person Daniel Hilgarth    schedule 08.02.2013
comment
Если вы еще не проверили это, Эффективная работа с устаревшим кодом Майкла Фезерса может оказаться полезным. Он содержит множество стратегий, которые помогут вам протестировать такой проект. Многие из них очевидны, но, увидев их в печатном виде, вы обретете уверенность в том, что сможете протолкнуться и сделать это.   -  person Anthony Pegram    schedule 08.02.2013
comment
@AnthonyPegram это следующая книга в моем списке, которую я хочу получить   -  person Earlz    schedule 08.02.2013
comment
100 методов это много? У нас есть классы бога с сотнями методов....   -  person C Johnson    schedule 08.02.2013
comment
@CJohnson Класс реализации имеет длину около 2000 строк. Я не удосужился посчитать   -  person Earlz    schedule 08.02.2013


Ответы (1)


С моей точки зрения, это хороший и правильный подход. Позже вы можете внедрить более конкретные экземпляры службы как IFoo/IBar, а не ISession, я бы сказал, что это хороший промежуточный шаг перед дальнейшим рефакторингом для извлечения классов из класса бога во многие конкретные службы.

Некоторые плюсы я вижу:

Первый этап: извлечение интерфейсов

  • Тип класса супер (бог) абстрагируется интерфейсами
  • Код становится менее связанным, поскольку полагается на однофункциональные ответственные интерфейсы (службы).
  • У вас есть основания двигаться дальше и разделить богоподобный класс на множество сервисов без масштабного рефакторинга, так как все уже полагается на интерфейсы API.

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

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

person sll    schedule 08.02.2013