Autumn SALE

Разделение запроса и модификатора

Также известен как: Separate Query from Modifier

Проблема

У вас есть метод, который возвращает какое-то значение, но при этом в процессе работы он изменяет что-то внутри объекта.

Решение

Разделите метод на два разных метода. Один из них пускай возвращает значение, а второй модифицирует объект.

До
Separate Query from Modifier - Before
После
Separate Query from Modifier - After

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

Этот рефакторинг является реализацией принципа разделения команд от запросов данных. Суть принципа сводится к тому, чтобы отделять код получения каких-то данных от кода, который изменяет что-то внутри объекта.

Код получения данных называют запросами, а код изменения видимого состояния объекта — модификаторами. Когда запрос и модификатор совмещены, у вас нет способа получить данные из объекта без того, чтобы не внести изменения в его состояние. Другими словами, вы задаёте вопрос и можете изменить ответ прямо в процессе его получения. Усугубляется эта проблема тем, что человек, вызывающий запрос, может не знать о «побочных действиях» такого метода, что нередко приводит к ошибкам выполнения программы.

Однако стоит подчеркнуть, что «побочными действиями» опасны только те модификаторы, которые меняют видимое состояние объекта. Это, например, поля, которые доступны из публичного интерфейса объекта, записи в базе данных, в файлах и т. д. Если какой-то модификатор всего лишь кеширует какую-то сложную операцию и сохраняет её внутри приватного поля класса, он вряд ли приведёт к «побочным действиям».

Достоинства

  • Если у вас есть запрос, который не меняет состояние программы, вы можете вызывать его сколько угодно раз, не опасаясь того, что результат изменится от самого факта вызова метода.

Недостатки

  • В некоторых случаях, удобно возвращать какие-то данные после осуществления команды. Например, удаляя что-то из базы данных, вы хотите узнать, сколько при этом строк было удалено.

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

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

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

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

  4. Избавьтесь от кода возврата значения в оригинальном методе. После этого он станет правильным методом-модификатором.