CQS — это принцип проектирования, который означает разделение команд и запросов. Сам принцип довольно прост: разработчик должен разделить методы внутри приложения на две отдельные категории.
- Команды изменяют состояние и создают побочные эффекты
- Запросы возвращают состояние
Сначала рассмотрим команды.
public class User { public readonly Guid Id; public readonly string Name; public readonly int Age; public Address address; } public User AddAge(User user, int age) { User.Age = age; return user; }
Эта функция изменяет возраст пользователей, функция, которая изменяет состояние, также называется командой, но если мы посмотрим поближе, у нас будет проблема с дизайном внутри вашей новой функции, проблема в том, что мы получаем пользователя и новый возраст и возвращаем пользователя. Команда, чтобы соответствовать принципу CQS, должна изменять состояние и не возвращать никакого состояния, поэтому для исправления функции мы просто делаем следующее.
public void AddAge(User user, int age) { User.Age = age; }
Вторая категория внутри CQS — это запрос, запрос — это функция, которая возвращает состояние, помня, что запрос не имеет побочных эффектов, мы не можем изменять или создавать побочные эффекты внутри него.
public async Task<User> GetUser(Guid Id) { return await _userRepository.GetUserById(Id); }
Это действительно все, о чем CQS, не нужно усложнять. Полный пример службы, соответствующей принципам, может быть следующим.
public class UserService { private readonly _userRepository; public UserService (UserRepository userRepository) { _userRepository = userRepository ?? throw ArgumentNullException(nameof(userRepository)); } // Query public Address CreateAddress(string street, int number, string city, int zipCode) { return Address.Create(street, number, city, zipCode); } // Query public async Task<User> GetUser(Guid Id) { return await _userRepository.GetUserById(Id); } // Command public async Task CreateUser(string name, int age, Address) { await _userRepository.CreateUser(name, age); } }
Заключение
Вообще говоря, принцип CQS представляет собой хорошее разделение ответственности на функциональном уровне и приносит пользу общей структуре системы.
Просто чтобы внести ясность, мы должны помнить, что CQS — это не то же самое, что CQRS. Я часто вижу эту путаницу. CQRS(Разделение ответственности за запросы команд.) — это шаблон, разделяющий модели, обновляющие данные, и модели, считывающие их. Напишу об этом в ближайшее время, а пока.
С наилучшими пожеланиями.