Установщик для определенного поля присутствует: возможно, это сгенерированный метод или используется для внедрения зависимостей.
Однако в текущем состоянии кода нет вариантов его использования [больше]: это либо метод, который никогда не вызывался, либо метод, вызываемый только во время построения.
Метод Remove Установка рефакторинга делает вас выбросить этот метод и формально сохранить неизменность объекта. Вы знаете, что не следует ожидать изменения состояния объекта, только когда у него нет методов, присваивающих его приватным полям (кроме конструктора).
Зачем удалять сеттер?
Если метод не служит какой-либо цели, желательно отбросить его, чтобы упростить дизайн (независимо от того, насколько он прост). Это верно для любого метода, но в случае с установщиком мы можем захотеть переложить его ответственность на другие методы, чтобы избавиться от очень общего фрагмента API, позволяя любому, имеющему ссылку на объект, связываться с внутреннее состояние.
Если у метода или поля слишком большая область видимости (общедоступная, хотя вызывается только внутри класса), мы можем ограничить область видимости, чтобы упростить допущения, которые люди, впервые знакомые с кодом, делают в дизайне. Под новичками в коде я имею в виду и вас, и меня через 2 недели.
Например, применяя дальнейшую технику рефакторинга, вы будете пользоваться большей свободой, поскольку вам нужно будет только проверять вызовы внутри класса, а не исследовать всю кодовую базу с помощью grep .
Объекты часто используются как неизменяемые: удаляя установщик, вы заставляете эту неизменность (по крайней мере, для этого поля). Класс, в котором вы удалили все сеттеры и методы изменения состояния, создают неизменяемые объекты.
В преимущества неизменности выходят за рамки данной статьи, и это не говорит о том , что объект достигнет неизменность только за счет устранения одного сеттера. Тем не менее, он может достичь этого путем удаления многих сеттеров, и в этом смысле этот рефакторинг является основным инструментом.
меры
- Проверьте вызовы к установщику: он должен вызываться только внутри конструктора или никогда не вызываться вообще. Цель — сделать поле неизменным: обязательным условием является никогда не вызываемый сеттер.
- Если в фазе построения есть вызов , измените код для прямого доступа к полю.
- Если установщик вызывается сразу после new () , переместите значение в качестве параметра конструктора. Этот шаг охватывает использование сеттеров для внедрения зависимостей.
- Удалить метод настройки.
Тестовый набор должен пройти все время, не ломаясь.
пример
Объект предъявителя Вопроса должен отображаться в качестве заголовка вопроса, например, для использования в ссылке или элементе списка. Сеттер вызывается во время построения, чтобы убедиться, что текст правильно обрезан (конечные пробелы выбрасываются).
<?php class RemoveSettingMethod extends PHPUnit_Framework_TestCase { public function testAQuestionIsDisplayedTogetherWithTheNumberOfResponses() { $question = new Question('How do I install PHP on the washing machine?', 10); $this->assertEquals('How do I install PHP on the washing machine? (responses: 10)', $question->__toString()); } } class Question { private $text; private $responses; public function __construct($text, $responses = 0) { $this->setText($text); $this->responses = $responses; } public function setText($text) { $text = trim($text); $this->text = $text; } public function __toString() { return $this->text . ' (responses: ' . $this->responses . ')'; } }
Однако мы замечаем, что это просто объект, созданный для рендеринга, а не доменный; нам никогда не придется менять его текст (мы просто создадим новый объект). Метод setText () предоставляет возможность, которая нам не нужна и не нужна: давайте устраняем ее, начиная с тех мест, где он вызывается.
class Question { private $text; private $responses; public function __construct($text, $responses = 0) { $text = trim($text); $this->text = $text; $this->responses = $responses; } public function setText($text) { $text = trim($text); $this->text = $text; } public function __toString() { return $this->text . ' (responses: ' . $this->responses . ')'; } }
Теперь сеттер больше не вызывается. Мы можем удалить это вообще.
class Question { private $text; private $responses; public function __construct($text, $responses = 0) { $text = trim($text); $this->text = $text; $this->responses = $responses; } public function __toString() { return $this->text . ' (responses: ' . $this->responses . ')'; } }
Объект теперь формально неизменен и может передаваться везде, не беспокоясь о псевдонимах и о том, что будет делать с ним клиентский код. Класс также имеет меньше методов для поддержки.