View on GitHub

wiki

Technical Excellence Wiki

Принцип разделения команд и запросов (CQS)

Перевод статьи на русский язык Мартина Фаулера CommandQuerySeparation.

Термин “разделение команд и запросов” (command query separation) был введён Бертраном Мейером в книге “Object Oriented Software Construction” - одной из самых влиятельных книг по ООП во время его рассвета. (Первое было действительно хорошим таким, а второе издание стало настолько большим, что вам понадобится несколько месяцев в тренажерном зале, прежде чем вы сможете его поднять).

Основная идея состоит в том, что мы должны разделить методы объекта на две четко разделенные категории:

Поскольку термин “команда” часто используется в других контекстах, я предпочитаю называть их “модификаторами” (modifiers), вы также можете встретить термин “мутаторы” (mutators).

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

Этот принцип служит, чтобы избавится от различий типов возвращаемых значений. Это хорошее соглашение, потому что в большинстве случаев оно работает. Рассмотрим пример обхода коллекции в Java с помощью итератора: метод java.util.Iterator<E> {... E next(); ... } возвращает следующий элемент типа E и передвигает курсор итератора на него. Я бы предпочел стиль, в котором есть отдельные методы продвижения итератора и возвращения текущего элемента.

Мейер любит абсолютное разделение команд и запросов, но существуют исключения. Извлечение стека хороший пример запроса, изменяющего состояние. Мейер правильно говорит, что этого метода можно избежать, но это полезная схема. Поэтому я предпочитаю следовать этому принципу, когда могу, но я готов нарушить его, чтобы получить выгоду.

Было бы хорошо, если бы язык программирования поддерживал это понятие. Я мог представить себе язык, который обнаруживал бы методы изменения состояния или, по крайней мере, позволял бы программисту отмечать их. Одна из причин, по которой языки не могут обнаруживать их автоматически, заключается в том, что правило не изменять состояние действительно применяется только к ObservableState системам. Использование маркировки программиста кажется более разумным, но редко. Единственный случай, с которым я действительно столкнулся это модификатор const в C++. Поскольку я не использовал C++ много лет, мне трудно оценить, насколько он полезен на практике. Я считаю, что хорошие C++ разработчики часто используют const и им это нравится.

Перевёл: Кротов Артём.

Остались вопросы? Задавай в нашем чате.