Рефакторинг: встраивание класса
Представим себе такую ситуацию, когда мы провели серию приемов рефакторинга и в результате оказалось, что от класса становится мало пользы, т.к. в нем осталось мало функций. Проблема, которая может быть решена с помощью сегодняшнего приема, – это устранение малого класса. Хотя это, конечно, не проблема. Но все же
Суть приема встраивания класса состоит в том, чтобы встроить имеющиеся функции нашего класса А в другой класс Б, который чаще всего использует функции класса А. Сам класс А при этом удалить.
Подробно я описывать процесс не буду. Приведу лишь небольшой пример, который далее можно разобрать самостоятельно.
Допустим у нас есть два класса – Person и PhoneNumber. При этом класс Person использует методы класса PhoneNumber:
class Person {
private $_name;
private $_officePhone;
public function __construct() {
$this->_officePhone = new PhoneNumber();
}
public function GetName() {
return $this->_name;
}
public function GetPhoneNumber() {
return $this->_officePhone->GetPhoneNumber();
}
public function GetOfficePhone() {
return $this->_officePhone;
}
}
class PhoneNumber {
private $_number;
private $_areaCode;
public function GetPhoneNumber() {
return '('.$this->_areaCode.') '.$this->_number;
}
public function GetAreaCode() {
return $this->_areaCode;
}
public function SetAreaCode($arg) {
$this->_areaCode = $arg;
}
public function GetNumber() {
return $this->_number;
}
public function SetNumber($arg) {
$this->_number = $arg;
}
}
Чтобы применить наш прием, сначала нужно добавить в класс Person методы из класса PhoneNumber:
class Person {
…
public function GetAreaCode() {
return $this->_officePhone->GetAreaCode();
}
public function SetAreaCode($arg) {
$this->_officePhone->SetAreaCode($arg);
}
public function GetNumber() {
return $this->_officePhone->GetNumber();
}
public function SetNumber($arg) {
$this->_officePhone->SetNumber($arg);
}
…
}
После этого шага мы можем использовать код
$myPerson = new Person();
$myPerson->setAreaCode ("123");
вместо кода, который мы использовали бы раньше:
$myPerson = new Person();
$myPerson->getOfficePhone()->setAreaCode("123");
Таким образом, мы избавляемся от создания лишнего объекта (который на самом деле пока создается внутри класса Person).
А после этого шага мы можем спокойно применять такие приемы рефакторинга, как «Перемещение метода» и «Перемещение поля», о которых я расскажу в следующих постах.
Но и без их описания не трудно догадаться, что мы теперь можем выкинуть метод GetOfficePhone из класса Person, и можем переместить тела методов GetPhoneNumber, GetAreaCode, SetAreaCode, GetNumber, SetNumber. Но перед этим конечно нужно переместить внутренние поля _number и _areaCode класса PhoneNumber в класс Person. А затем мы можем смело удалить класс PhoneNumber, инициализацию поля _officePhone в классе Person и само поле _officePhone в классе Person.
В результате применения этих приемов класс PhoneNumber исчезнет совсем, чего мы и добивались, а класс Person станет таким:
class Person {
private $_name;
private $_number;
private $_areaCode;
public function GetName() {
return $this->_name;
}
public function GetPhoneNumber() {
return '('.$this->_areaCode.') '.$this->_number;
}
public function GetAreaCode() {
return $this->_areaCode;
}
public function SetAreaCode($arg) {
$this->_areaCode = $arg;
}
public function GetNumber() {
return $this->_number;
}
public function SetNumber($arg) {
$this->_number = $arg;
}
}
Думаю, это полезный прием очищения кода, который кому-нибудь обязательно пригодится
Ноябрь 18th, 2008
Такое может понадобиться только изночально при неправельной архитектуре проекта
По мне так статья бесполезная(
Ноябрь 18th, 2008
Если говорить про архитектуру, то не всегда удается с первого раза создать такую архитектуру, которая была бы идеальна для конкретного проекта. А то, что статья бесполезная – это Ваше субъективное мнение.
Ноябрь 22nd, 2008
У класса Person метод setAreaCode не совсем понятен. Если же # $myPerson->getOfficePhone()->setAreaCode(”123″) вот так делаем, то понимаем, что устанавливаем код для телефона. Каждый класс и объект этого классы занимается теми вещами, которые ему присущи. Смотрите антипаттерн – Божественный объект.
Декабрь 16th, 2008
Нормальная статья. Насчет правильной архитектуры, построить такую сразу не реально, поэтому и есть реффакторинг.