Выполните команду CQRS, когда у меня нет идентификатора - PullRequest
0 голосов
/ 06 октября 2019

В настоящее время я занимаюсь разработкой приложения CQRS со страницей входа. В LoginCommand один пользователь выбирается из базы данных, и если он может войти в систему (зашифрованный пароль соответствует заданному зашифрованному паролю), пользователю назначается токен.

В CQRS команда обычно получает идентификатор элемента, для которого предназначена команда, для того, чтобы получить агрегат домена, который он идентифицирует, и выполнить на нем логику. Тем не менее, в этом случае, что я имею от пользователя, это электронная почта. Несмотря на то, что это уникальное поле, я не уверен, что неправильно использовать это поле для извлечения совокупности, несмотря на то, что это уникальное поле. идентифицировать Post по заданному семантическому URL, который не содержит идентификатор сообщения.

Поскольку выполнение запросов внутри Команды запрещено, а присоединение идентификатора пользователя из формы входа в систему маловероятно, какие варианты у меня есть, чтобы выбрать пользователя в данной ситуации? Должен ли я запросить модель чтения вне команды (например, контроллера)?

Ответы [ 4 ]

2 голосов
/ 07 октября 2019

Я не думаю, что CQRS повлияет на ваш дизайн в данном конкретном случае. Хотя, возможно, может использоваться источник событий.

Если у вас есть естественный ключ , то у вас есть несколько вариантов. Во-первых, он должен быть уникальным. Ваш UserRepository может иметь метод, использующий адрес электронной почты для получения пользователя в дополнение к идентификатору:

public interface IUserRepository
{
    User Get(Guid id);
    User Find(string email);
}

Я склонен использовать Find методы, когда я могу вернуть null какGet указывает на то, что объект должен существовать и будет выдавать исключение, когда не найден.

Если вы хотите найти только по id, то вам нужно поискать id, используя email из какого-то магазина. В зависимости от ваших требований согласованности может оказаться достаточным согласованное хранилище запросов / чтений, но ничто не мешает вам получить доступ к 100% согласованному хранилищу, в котором есть сопоставление электронной почты и идентификатора.

1 голос
/ 09 октября 2019

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

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

1 голос
/ 07 октября 2019

Говоря с точки зрения домена, ID, связанный с User записью, является просто суррогатным ключом . Он не имеет соответствующего представления в реальном мире и предназначен только для того, чтобы помочь вам сохранить и извлечь данные.

Так что, если email является уникальным полем для ваших User записей, во что бы то ни стало, используйтеэто как если бы вы использовали идентификатор в вашей команде.

Это не обязательно означает, что вы можете избавиться от своего поля id.

Вы все равно хотели бы иметь суррогатный ключкак поле id в вашей записи User, потому что вы можете дать своим пользователям возможность изменить свой адрес электронной почты. Даже с измененным адресом электронной почты вы должны иметь возможность однозначно идентифицировать пользователя во всей системе, и здесь вам пригодится суррогатный ключ. Вы также хотели бы суррогатный ключ по причинам производительности;почти всегда лучше использовать поле Integer или UUID вместо String адреса электронной почты в качестве первичного ключа или в ссылочных полях.

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

A Command Handler (который по своей природе аналогичен службе приложений, но имеет фоновое представление) потребляет данные в команде. Там вы можете запросить свой репозиторий и получить записи. Фактически, это будет необходимо для проверки дубликатов или ссылочных ключей любого типа.

0 голосов
/ 08 октября 2019

Я бы настоятельно предположил, что это не «команда», а чтение из модели чтения. И вот почему:

Вы просто проверяете, совпадают ли предоставленные учетные данные с моделью чтения. Это действие не меняет состояние домена и поэтому не согласуется с использованием команды.

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

И это еще не все ...

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

Я признаю, однако вы можете записать тот факт, что кто-то вошел в систему или не смогавторизоваться. Для этого рассмотрите возможность ввода команд, таких как 'RecordSuccessfullLoggin' или 'RecordFailedLoginAttempt', если это то, что нужно вашему домену.

...