Autumn SALE

Замена кодирования типа классом

Также известен как: Replace Type Code with Class

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

Проблема

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

Решение

Создайте новый класс и применяйте его объекты вместо значений закодированного типа.

До
Replace Type Code with Class - Before
После
Replace Type Code with Class - After

Причины рефакторинга

Одной из самых частых причин появления кодирования типа является работа с базой данных, в полях которой какая-то сложная концепция кодируется каким-то числом или строкой.

Например, у вас есть класс Пользователь с полем роль_пользователя, в которой содержится информация о доступе каждого пользователя, будь то администратор, редактор или обычный пользователь. Причём эта информация кодируется в поле как символы A, E, и U соответственно.

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

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

Достоинства

  • Мы хотим превратить наборы значений примитивных типов, коими являются закодированные типы, в стройные классы, которые бы обладали всеми мощными свойствами ООП.

  • Заменив кодирование типа классами, мы обеспечим возможность контроля и проверки типов значений (type hinting), передаваемых в методы и поля на уровне языка программирования.

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

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

Когда нельзя применить

Если значения закодированного типа используются внутри управляющих структур (if, switch и др.), и управляют каким-то поведением класса, вам следует прибегнуть к одному из двух других рефакторингов устранения кодирования типа:

Порядок рефакторинга

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

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

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

  4. В исходном классе, замените тип закодированного поля на класс типа. Создавайте новый объект этого типа в конструкторе, а также в сеттере поля. Измените геттер поля так, чтобы он вызывал геттер класса типа.

  5. Замените любые упоминания значений закодированного типа вызовами соответствующих статических методов класса типа.

  6. Удалите константы закодированного типа из исходного класса.