2016-09-05 4 views
1

Предположим, у меня есть команда, которая сохраняет роль приложения вместе с некоторыми разрешениями приложений. Мои роли и разрешения имеют (или будут) бизнес-правила, поэтому я буду использовать объекты домена:Как и когда гидратировать объекты домена в стеке команд CQRS

class Role { 
    ... 
    IEnumerable<Permission> Permissions { ... } 
    AddPermission(...) 
    ... 
} 

class Permission { 
    ... 
    int ID { ... } 
    string Foo { ... } 
    string Bar { ... } 
    string Baz { ... } 
} 

Когда я сохранение роли, мне нужен полный объект Role и, скорее всего, получат все, что я требуется от уровня представления. Однако мне не нужны полные объекты Permission, потому что мне нужно связать их идентификатор с ролью. Мне не нужны свойства Foo, Bar и Baz.

Когда я с сохранением разрешения, мне, очевидно, нужен полный объект Permission.

Мой вопрос: Каков правильный способ обработки этого объекта Permission? Если у меня есть только один класс Permission, а затем, когда я спасаю свою роль, я буду либо:

  1. Have для запроса/гидратов объектов полного разрешения из базы данных и роль имеет законные объекты правы в своей коллекции, или
  2. Прикрепите незавершенные объекты Разрешения (только идентификаторы), чтобы избежать поездки в базу данных.

Вариант № 1 звучит как сложность команды/запроса, которую CQRS старается избегать, а # 2 звучит как недействительный объект, плавающий вокруг - я даже не хочу иметь возможность создавать недопустимые объекты, меньше использовать их.

Я мог бы также создать класс PermissionSummary и получить от него полный класс Permission. Я делал это раньше, и это неизбежно приводит к ползучести свойств от «полного» класса до «итогового» класса.

ответ

2

поэтому при использовании CQRS я считаю, что ответ не является ни тем, ни другим.

Я думаю, что важно различать DDD и CQRS.

При сохранении роли (в шаблоне CQRS) вы отправляете команду «RoleChangeRequest» на ваш сервер. Тогда это приведет к возникновению события RoleChangeRequested. (это может быть сделано службой домена, возможно, даже самим уровнем домена). Это событие будет обрабатываться ваш слой базы данных, но это событие будет выглядеть более близко к этому

class RoleChangeRequested { 
    IEnumerable<int> PermissionIds {....} 
    string name {....} 
} 

Ключевым моментом здесь является то, что в повышении событие, которое позволит сэкономить ваши данные вам нужно только знать о корочки разрешений , Нет необходимости запрашивать разрешения (хорошо, может быть, вам нужна проверка, что они на самом деле существуют, но отношение внешних ключей может справиться с этим). или для присоединения незавершенных объектов.

ПРИМЕЧАНИЕ: В этом примере CQRS сделает ваше приложение более сложным. CQRS - это оружейная архитектура, и с ней следует обращаться с особой осторожностью. Теперь, почему вы хотите использовать CQRS, это связано с тем, что ваше следующее требование - сделать полный и гарантированный след аудита всей вашей роли и/или изменений разрешения. Это просто еще один обработчик событий для тех же событий. И у вас может быть даже обработчик событий для общего пользовательского интерфейса, и тогда вам гарантируется, что вы проверяете каждое событие, возникающее в приложении. То, что вы получаете (почти) бесплатно, и почему CQRS может быть выгодным.

+0

Благодарим за отзыв, но часть моего вопроса остается: где действуют бизнес-правила в вашем решении? Для (примитивного примера) в Role.AddPermission() я мог убедиться, что я не добавляю разрешение, которого еще нет в коллекции. Но в вашем решении этот класс не существует. – Seth

+0

Да, да. По-прежнему будет класс Role с методом AddPermission. Это создаст событие PermissionAdded, если будут выполнены бизнес-правила. Посмотрите пример Simple CQRS Greg Young – tomliversidge

3

Реакция Batavia на CQRS отличная, и поскольку у меня нет опыта с этим шаблоном, я пытаюсь ответить на вопрос «что мне сохранить».

Ответ на этот вопрос сильно зависит от дизайна модели и предлагаемого поведения объектов Permission. DDD не работает без сильного знания бизнес-домена.

Сказав, что я могу думать о 3-х сценариях:

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

partial class role() { 
    public enumAccessType AccessToAction(enumAction action) { 
     foreach(var p in Permissions) 
     if p.HasFullAccess(action) return enumAccesssType.Full; 
     foreach(var p in Permissions) 
     if p.HasLimitedAccess(action) return enumAccesssType.Restricted; 
     return enumAccesssType.None; 
    } 
} 

Существует хранилище Разрешения для сохранения новых разрешений и роль Repository для поддержания функций и таблиц role_Permission

ПРИМЕЧАНИЯ : Только потому, что объект домена имеет полные объекты PERMISSION, это не означает, что для уровня сохранения требуется обновить таблицу PERMISSION для каждого добавленного разрешения. RoleRepository должен обновлять только таблицы ROLE (roleId, roleName) и ROLE_PERMISSION (roleId, permissonId).

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

class Permission { 
    Ienumerable<RoleId> Roles {get;private set;} 
    PermissionId ID { ... } 
    string Foo { ... } 
    string Bar { ... } 
} 

Снова есть хранилище Разрешения для сохранения новых разрешений и поддерживая отношения между правами и полномочиями. Репозиторий роли просто обрабатывает роли.

3) Роли и разрешения постоянно меняются - ваши требования к безопасности сложны и будут трудно понять большинству конечных пользователей. Принесите эксперту домена, чтобы объяснить, как роль и разрешения связаны и влияют на остальную систему, и ПОЧЕМУ они должны быть настолько гибкими. Посмотрите, почему, и попытайтесь определить процессы или поведение, которые могут быть неправильно введены в шаблон разрешений ролей. Вероятно, для этого потребуется собственный ограниченный контекст и службы.

Он помогает запоминать «Таблицы базы данных»! = «Объекты DDD»! = «Пользовательский интерфейс». Сначала краснеть выглядит так, как будто вы пришли к этому с точки зрения дизайна базы данных, а не с точки зрения поведения домена.

Большая проверка «Я делаю это правильно» - это проверка: если я сохраняю изменения для одного объекта, мне нужно перезагрузить любые другие объекты, которые ссылаются на этот оригинальный объект, чтобы эти другие объекты работали? Если да, то вам нужно вернуться к своей модели.

Смежные вопросы