Рефакторинги на уровне класса

17. May 2010

 

Перемещение метода и/или поля ( Move Method / Move Field ).

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

 

Выделение класса ( Extract Class ).

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

 

Встраивание касса ( Inline Class ).

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

 

Сокрытие посредника (  Hide Delegate ).

    Рефактонинг, в котором последовательность вызовов совершаемые клиентом упаковывать в отдельный метод и помещается в используемый класс. Допустим у нас есть клиентской объект, который хочет отправить пакет по TCP. Он открывает канал связи при помощи экземпляра класса TCPChannel, потом упаковывает данные в экземпляр класса TCPDataPackedge, и только теперь отдает канал связи и пакет в TCPManager. Слишком сложно для клиента, он знает о всех трех классах и для отправки строки "Hello!" должен совершить кучу действий. Спрашивается, зачем такие сложности? Скроем все это внутри метода SendString в TCPManager, скроем в нем создание подключения и упаковку данных. Клиентский код счастлив и довольно мурлычет, у него больше не болит голова при работе с множеством классов(их может быть далеко не три), он дружит только с TCPManager.

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

 

Удаление посредника ( Remove Middle Man ).

    Антипод предыдущего рефакторинга. Применяется когда приходится создавать слишком много делегирующих методов. Слишком много комбинаций возможных состояний большого числа объектов используется для разных нужд в проекте. Продумывать каждую ситуацию и создавать метод слишком утомительно и в конце концов мы получим вязанку методов с названиями SendMail, SendMailWithBcc, SendMailWithEncription,SendMailBySchedule and etc. К черту, пусть лучше клиентский код сам конфигурирует механизм отправки писем как ему хочется. В конечном счете слишком много клиентов, всем не угодишь. Золотая середина между двумя крайностями - вот где скрыта гармония. 

 

Введение внешнего метода ( Introduce Foreign Method ).

    Рефакторинг применяется когда используемый код невозможно изменить, но в него очень хочется добавить метод. Тогда в клиенткой коде создается метод обертка, принимающий на вход расширяемый объект и производящий над ним все необходимые действия. Часто применяется в случае, когда одни и те же операции приходится делать над одними и теми же объектами. В .NET 3.5 есть отличная возможность создавать внешние методы, это фактически реализация данного рефакторинга на уровне фреймворка. Почитать про Extension методы в .NET можно тут.

Введение локального расширения ( Introduce Local Extension ).

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

    К сожалению как и любой прокси-объект, наша extenstion обертка, может плохо обрабатывать неявные(implicit) операции с оригинальным объектом. Например, нам необходимо перегрузить equal и операторы сравнения, чтоб мы могли корректно обрабатывать ситуации ExtensionObject == Object.

 

Послесловие:

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

 

Refactoring, Architecture

Comments

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading