Рефакторинг: перемещение поля и самоинкапсуляция
По мере разработки любой сложной системы выясняется, что необходимо переместить то или иное поле или метод в новый класс. Любое правильное проектное решение через некоторое время может оказаться неправильным.
Суть приема перемещения поля такая же, как и у приема перемещения метода - переместить поле в тот класс, в который его больше всего использует. Причем под использованием здесь подразумевается и косвенное - через методы доступа. Еще, например, есть прием выделения класса, о котором я не говорил. Это противоположный встраиванию класса прием. Так вот, при выделении класса сначала перемещаются поля, а затем - методы.
Пусть у нас есть все те же (я о них упоминал в предыдущих статьях) взаимодействующие классы Account и AccountType:
class Account { //... private $_type; // AccountType private $_interestRate; function interestForAmount_days($amount, $days) { return $this->_interestRate * $amount * $days / 365; } //... }
Теперь мы хотим переместить поле _interestRate (процентная ставка) в класс типа счета (AccountType). В классе Account существует несколько методов, которые обращаются к полю _interestRate - например, метод interestForAmount_days.
Для того чтобы перенести поле _interestRate в класс AccountType, мы должны создать в AccountType это поле и определить для него методы доступа:
class AccountType { //... private $_interestRate; function SetInterestRate($arg) { $this->_interestRate = $arg; } function GetInterestRate() { return $this->_interestRate; } //... }
Теперь переадресуем методы исходного класса (Account) для использования целевого класса (AccountType) и удалим поле _interestRate из исходного класса:
class Account { //... private $_type; // AccountType function interestForAmount_days($amount, $days) { return $this->_type->GetInterestRate() * $amount * $days / 365; } //... }
Вот мы и переместили поле в целевой класс.
Рассмотрим теперь пример с самоинкапсуляцией поля. Прием самоинкапсуляции желательно применять в том случае, когда у нас есть много методов, использующих поле _interestRate. Добавим в наш исходный класс Account методы доступа к полю:
class Account { //... private $_type; // AccountType private $_interestRate; function interestForAmount_days($amount, $days) { return $this->GetInterestRate() * $amount * $days / 365; } function SetInterestRate($arg) { $this->_interestRate = $arg; } function GetInterestRate() { return $this->_interestRate; } //... }
Теперь, чтобы нам избавиться от поля, достаточно выполнить переадресацию только в методах доступа:
class Account { //... private $_type; // AccountType function interestForAmount_days($amount, $days) { return $this->GetInterestRate() * $amount * $days / 365; } function SetInterestRate($arg) { $this->type->SetInterestRate($arg); } function GetInterestRate() { return $this->type->GetInterestRate(); } //... }
Позже мы можем выполнить переадресацию для клиентов методов доступа (для использования нового объекта). Прием самоинкапсуляции позволяет проделывать рефакторинг более мелкими и осторожными шагами. Это удобно, когда класс сильно переделывается.
Привет, у тебя вроде как не спам-блог, хотя авторского маловато (все покрывает неплохое стремление рассказать о сложно-простых вещах).
В общем, инвайт на Хабр нужен? Если ты там будешь публиковать не кросспосты, а “сборки” из своих постов - было бы хорошо. Да и тебе выгода )