2016-08-13 12 views
1

В нашей эры у меня есть следующие правила:Wrap роли домена вокруг совокупности корневых операций представляют вездесущий язык

A project can be defined by an employer. 
An approver should approve the project. 
Then an employee can bid that project. 
A project can be directed by a member (= an employer or an employee) to another member. 

Проект является независимым агрегатный от работодателя, работника и утверждающего.

И все работодатели, работники и утверждающие - все пользователи, и все, что мне нужно знать от пользователей в этом BC, - это их Тождества.

Я разработал проект, включая методы:

static Define(){...} 
ApprovedBy(approderId){...} 
Bid(bidderId){...} 
Direct(directorId,directeeId){...} 

Как следует применять остальные вездесущего языка в контексте?

Должен ли я пропустить Users в этом контексте или создавать классы для работника, работодателя и утверждающими и сделать, например, в Approve методе внутренних, так что ограничить приложение слой только смогут одобрить проект через Approver класса, как следующее ?

class Approver{ 
    approverId _id 
    public Approver(approverId id){ 
     _id = id 
    } 
    public Approve(project){ 
     project.ApprovedBy(_id); 
    } 
} 

Update:

Вот некоторые комментарии Iv'e написанные на ответы, которые могут сделать вопрос яснее:

Approver является роль, которую определяется в Identity and Access BC, и единственное, что должно это имя роли. Bidder должен был заполнить некоторые дополнительные данные, чем обычный член, чтобы иметь возможность bid a project. Я хотел использовать saga и выслушать events, чтобы проверить, удовлетворено ли участником правило, затем saga отправляет AddRole() или RemoveRole() по I & A BC. Я думал, что таким образом у меня есть более сплоченной I&A озабоченность, которая отделена от остальной части системы, но когда я проектирования Project BC я подумал, почему бы не назвать что-то вроде factories.Employer(‌​employerId).DefinePro‌​ject(..)

НО

Я беспокоиться о будущих функции, которые будут расти после первоначального выпуска. Они могут ожидать, например, больше правил для Employer, и, когда я начал добавлять их в BC, мне придется разбить мои тесты, чтобы избежать утечки Project обязанности Employer, например, я больше не мог бы звонить DefineProject() как static factory (или constructor), и единственный способ определить project должен быть вызван Employer.DefineProj‌​ect();, и я чувствую естественное место, которое должно быть у Approvement, это класс Approver. Вы думаете, что я над инженерией?

Одна из причин, по которой мы инкапсулируем все, даже идентификаторы в другом объекте в ddd, самостоятельно заботится об изменении требований, определяя явные контракты между объектами и позволяя им изменять свои внутренние реализации в другом контексте. ПО не заботится много о тождествах, но он явно говорит о ролях и их правилах. Это может повлиять на мои тесты и коды уровня сервиса позже. Разве я не должен заботиться о ролях, по крайней мере, столько же, сколько личности? Или я неправильно понял что-то о границах и контрактах?

Может явно абстрактный role contracts выступать в качестве потенциального anti corruption layerinterface, который может держать меня подальше от взлома OCP?

+0

Может ли какая-либо другая логика иметь классы Approver, Director и Bidder? – tomliversidge

+0

@tomliversidge: Еще в этом до н.э. – Mohsen

+0

Тогда я бы не стал беспокоиться, просто придерживайтесь первого примера кода – tomliversidge

ответ

1

Если нет бизнес-логики, которая была бы лучше представлена ​​отдельными классами, я бы не стал создавать классы Approver, Director и Bidder. Похоже, этот контекст не должен знать ничего, кроме идентификаторов, связанных с ними. Поэтому просто держите его просто с моделью, которую вы в настоящее время имеете.

Этот совет, вероятно, изменился бы, если бы у вас была ситуация, скажем, где у утверждающего или директора были другие детали, которые определяли их разрешение на выполнение определенных действий. Например, возьмите StackOverflow - возможно, пользователю нужна определенная репутация, чтобы быть Подтверждающим, или, может быть, Directing между двумя членами нуждались в других бизнес-правилах, применимых к действительной передаче. Такие сценарии могут быть лучше смоделированы как классы.

+0

«Утверждение» - это роль, определенная в Identity и Access BC, и единственное, что должно соответствовать, это имя роли. Бидер должен был заполнить некоторые дополнительные данные, чем обычный член, чтобы иметь возможность предлагать проект. Я хотел использовать сагу и прислушиваться к событиям, чтобы проверить, удовлетворен ли участник торгов правилом, затем 'saga' отправляет' AddRole() 'или' RemoveRole() 'в I & A BC. Я думал, что у меня есть более сплоченная проблема с I & A, которая отделена от остальной части системы, но когда я разрабатывал «Project BC», я подумал, почему бы не назвать что-то вроде 'factories.Employer (employerId) .DefineProject (..) ' – Mohsen

+0

Я полностью в праве ехал? Thanx. – Mohsen

1

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

  1. Все ваши требования имеют <ROLE> быть в состоянии сделать что-то.

  2. Это говорит мне, что вам нужно <ROLE> агрегат для кода, чтобы он соответствовал языку в ваших требований (для вас, чтобы создать правильный вездесущий язык)

  3. Мои ответы предположить совокупность для ролей.

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

Давайте ваши требования к одной точке а время:

проект может быть определен работодателем

Это звучит как проект может ONLY определяется работодателем. В этом случае вам нужно указать, является ли ваш текущий пользователь работодателем или нет. Здесь есть несколько вопросов, но один из более крупных:

Где вы подтверждаете, что пользователь является работодателем? Ваш завод метод. Итак:

ProjectFactory.Create(User: Employer)

Я вообще предпочитаю использовать фабричный метод, который является частью агрегата.

Что-то вроде:

Employer.createProject(someProject: Project) Это хорошо подходит для вездесущих языка, потому что работодатель Создание проекта.

class Employer{ 
    Project[] projects{get; private set;} 
    //you can also pass primitives as parameters so the consumer doesn't 
    //need to bother with knowing how to create a project. 
    //furthermore, you could use a factory to get just the project 
    Project createProject(someProject: Project) 
} 

Утверждающий должен утвердить проект

Approver.approve(someProject: Project) Это также хорошо подходит для повсеместного языка. Интересно, как вы сохраните это состояние? В предыдущем примере о создании проектов легко прийти к выводу, что у Employer будет свод проектов, а createProject добавит в эту коллекцию. В этом случае, что будет делать ваш метод на самом деле? Я думаю, что имеет смысл, чтобы ваш метод изменял состояние в конкретном проекте. Утверждающий будет служить агрегатом, а проекты - это члены ценности.

Тогда работник может предложить этот проект.

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

Проект может быть направлен членом (= работодателем или сотрудником) другому члену.

Это звучит как услуга для меня.

TransferService(proj: Project, User1: User, User2: User) Это подходит лучше, потому что во многих случаях существуют сложные правила, регулирующие такие вещи, как передача, которую агрегаты пользователей не знают и не заботятся.

+0

Пожалуйста, взгляните на комментарии, которые я добавил под ответом @ tomliversidge. Это похоже на получение дополнительной информации о моем домене. – Mohsen

+0

Я прочитал. Независимо от того, вы можете применить все или все, что я сказал, к вашей конкретной учетной записи. ;) – Louis

+0

Почему я должен хранить 'approver.ApprovedProjects' в памяти? Утверждающий может одобрить большее количество сущностей из нескольких контекстов, и я пытался удержать его от того, чтобы загрязнять другие БК. Я хочу, чтобы предпочтительная модель агрегатов, считываемая NoSql, должна была быть одобрена, и когда утверждающий одобрит их, отправив запрос на базовый БК. – Mohsen

2

Я бы не смоделировал операции над актерами, потому что естественный дом для операций является агрегатом. Тем не менее, вы можете бесплатно получить проверки безопасности ролей и иметь сильное выравнивание с вашим Ubiquitous Language, если вы произвольно моделируете роли. Явные роли станут частью уровня anti-curruption, и классы могут быть созданы с помощью службы, которая абстрагирует интеграцию с вашим Idendity & Access BC.

E.g.

Approver approver = actorService.approverOfId(userId); 
project.markAsApprovedBy(approver); 

Этот подход обсуждается в книге IDDD Vaughn Вернона и blog post.

+0

Как насчет 'approver.Approve (project)', как я упоминал в вопросе? поскольку проект ничего не знает об утвердителе, но это «Идентичность». 'project.approve (approver);' похоже, не добавляет ничего особенного, кроме накладных расходов на запрос другого БК и связывания «проекта» с моделью анестезии-подтверждения, а в связанном с ним блоге эта часть опущена; – Mohsen

+0

Я не думаю, что вы можете говорить об анемии со значениями объектов (это то, что «Утверждение» было бы. На самом деле довольно распространено иметь бессистемные значения, учитывая, что объекты значения неизменяемы, особенно если вы используете объекты ценности как средство для улучшения язык и принудительные ограничения через контракты. Ваш BC должен быть привязан к Identity & Access BC, как вы будете проверять правила безопасности в противном случае? Даже если вы делаете это в службах приложений без привлечения домена, он все еще связывается. слой, который связывает, хотя и это хорошо. – plalx

+0

Я предполагаю, что вы всегда можете использовать один и тот же подход, но вместо этого моделируйте операцию на «Approver'», но затем, следуя этой дороге, вы получите массу методов на актерских классах что в основном просто отправка в агрегаты. – plalx

1

Мое мнение:

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

Как насчет того, чтобы вместо использования «Approver» в вашем «IAM BC» вы вводили концепцию «Участник проекта» или «Член команды» в своем проекте Project BC. Элементом является роль, которую партия (работодатель, работник, и утверждающий) играет в контексте проекта:

ApprovedBy(memberId){...} 
Bid(memberId){...} 
Direct(directorId,directeeId){...} 

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

Возможно, вам потребуется интегрировать (слой с антикоррупцией?) между «Identity и Access BC» и «Project BC» в случае изменения ваших ролей, которые могут повлиять на участников проекта/проекта.

+0

Итак, вы говорите, что являетесь явным о членах, и их роли могут быть скрыты в этом 'BC', и пусть другой' BC' обрабатывает их. Это может работать идеально в ситуациях, в которых вы уверены ваши будущие требования выросли. И одна из причин, по которой мы инкапсулируем все, даже «идентичности» в другом объекте в «ddd», самостоятельно заботится об изменении требований, определяя явные контракты между объектами и позволяя им изменять свои внутренние реализации в другом контексте , ПО не заботится о личности, но он явно говорит о ролях. – Mohsen

+0

Это может повлиять на мои тесты и коды уровня сервиса позже. Разве я не должен заботиться о ролях, по крайней мере, столько же, сколько личности? Или я неправильно понял что-то о границах и абстракциях? – Mohsen

+0

Yup, сделайте UL понятным, сделав неявным явным. Термин UL имеет смысл в определенном (ограниченном) контексте: например, «Роль» в «Проекте BC» и «Роль» в «IAM BC» - это разные вещи. Если ваше ПО просто использует термин «Роль», это неоднозначно, поэтому вам нужно уточнить UL и получить согласие на предпочтительный термин, например «Участник проекта». Синонимы, такие как «Роль проекта» или «Член команды», могут быть отмечены в вашем UL (глоссарии/тезаурусе) как неприемлемые условия, которые указывают на «Член проекта» (предпочтительный термин) или даже лучше всего «Член». Возможно, вы согласитесь на другой срок с вашим бизнесом. –