• Спонсоры

  • Рубрики

  • Архивы

  • Популярное



Рефакторинг: перемещение поля и самоинкапсуляция

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

Суть приема перемещения поля такая же, как и у приема перемещения метода — переместить поле в тот класс, в который его больше всего использует. Причем под использованием здесь подразумевается и косвенное — через методы доступа. Еще, например, есть прием выделения класса, о котором я не говорил. Это противоположный встраиванию класса прием. Так вот, при выделении класса сначала перемещаются поля, а затем — методы.

Пусть у нас есть все те же (я о них упоминал в предыдущих статьях) взаимодействующие классы 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();
	}

	//...
}

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





Читайте также:



Один ответ на “Рефакторинг: перемещение поля и самоинкапсуляция”

  1. Привет, у тебя вроде как не спам-блог, хотя авторского маловато (все покрывает неплохое стремление рассказать о сложно-простых вещах).

    В общем, инвайт на Хабр нужен? 🙂 Если ты там будешь публиковать не кросспосты, а «сборки» из своих постов — было бы хорошо. Да и тебе выгода )

Оставить комментарий


© 2008 - 2017 i-novice.net | Все права защищены.