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(Разделение ответственности за запросы команд.) — это шаблон, разделяющий модели, обновляющие данные, и модели, считывающие их. Напишу об этом в ближайшее время, а пока.

С наилучшими пожеланиями.