Входни параметри на DDD хранилище

Кой е предложен начин за внедряване на _customRoleRepository в следните примери? Следният код се изпълнява в услугата на приложението.

var user = _userRepository.GetById(1);
var customRole = _customRoleRepository.GetById(user.CustomRoleId);

or

var user = _userRepository.GetById(1);
var customRole = _customRoleRepository.GetForUser(user);

person Robert    schedule 25.08.2016    source източник
comment
за какво се зареждат потребителят и неговата роля?   -  person tomliversidge    schedule 25.08.2016
comment
@tomliversidege За да създадете токен за удостоверяване и да вземете разрешения за роли, за да го свържете с този токен   -  person Robert    schedule 25.08.2016


Отговори (3)


Имайки предвид двете опции, вероятно бих избрал първата, която запазва последователността на достъпа чрез ID.

Ако е възможно, може да е за предпочитане да заредите персонализираната роля, когато зареждате потребителя, за да избегнете повторно отиване и връщане към базата данни, особено ако това е обичайна операция. Това може да се приложи като модел за четене.

Това предполага, че сте моделирали вашите агрегати правилно... :)

person tomliversidge    schedule 25.08.2016
comment
Нещо като CQRS? - person Robert; 25.08.2016
comment
Терминологията може да зависи от това с кого говорите :) Но аз често използвам термина CQRS (Command Query Responsibility Segregation), когато има отделно хранилище за данни за четене, което е предварително проектирано върху точно моделите за четене, изисквани от отговорите. Той се поддържа асинхронно актуален въз основа на поток от събития. Въпреки това, друга еднакво валидна техника е CQS (Command Query Separation), когато имате набор от заявки, които изпълняват стандартни заявки срещу хранилището за постоянство на модела за запис. Заявките са разделени в приложението, но моделът за четене не е напълно сегрегиран. - person Chris Simon; 26.08.2016
comment
Така че за мен прилагането на заявка за модел за четене, която просто присъединява таблица Users към таблица CustomRoles и връща модел за четене dto, ще бъде CQS. Но също така мисля, че е добра идея само ако данните отиват направо към данните за отговор на UI или API. Ако възнамерявате да използвате върнатите данни, за да взаимодействате с агрегатите/обектите на домейна, това, което правите с хранилища, е по-добро, защото използвате модели на домейни с модели на домейни и поддържате техните стратегии за достъп независими. - person Chris Simon; 26.08.2016
comment
Благодаря за обяснението на разликата между CQS и CQRS. Винаги съм имал впечатление, че е едно и също. - person Robert; 26.08.2016

Мразя да го кажа, но в среда на DDD отговорът ми би бил нито едното, нито другото.

В първия ви пример хранилището на ролите може да не знае потребителския домейн, което е добре, но това означава, че приложението трябва да знае, че за да получи ролята, трябва да изтегли идентификатор от потребителя и след това да направи запитване към друго хранилище. С други думи, приложението действа като картограф между потребител и роля.

Във втория пример хранилището на ролите вече трябва да знае за потребителския домейн. Не е страхотно, но от друга страна приложението вече не трябва да знае за roleId. Така че това е добре. Класически вид компромис между двата подхода.

Но и в двата случая приложението все още се нуждае от две хранилища, за да получи информацията си. Какво се случва, когато са необходими повече отношения? Броят на хранилищата може бързо да нарасне и нещата да станат бъркотия.

При проектиране, управлявано от домейн, трябва да се опитате да мислите от гледна точка на съвкупни корени (AR) и контекст на домейн. За вашия примерен контекст потребителят е AR и ролята става дете. Така че може да имате:

var user = _userFinder.GetById(1);
var customRole = user.CustomRole;

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

person Cerad    schedule 25.08.2016
comment
CustomRole представлява друг AggregateRoot в рамките на BC. Има свои обекти (разрешения) и т.н. Множество потребители могат да споделят една и съща CustomRole. Това, което предлагате, е CustomRole да се третира като стойностен обект и когато CustomRole се актуализира, ще трябва да разпространявам тази промяна към всички потребители в тази роля? - person Robert; 25.08.2016
comment
Два ars в рамките на една и съща bc звучи като проблем. Във вашия пример бих считал ролята за ценностен обект. Бих имал различен bc за актуализиране на ролята и да изпратя известие, за да кажа на потребителите, че ролята е променена. Разбира се, голяма част от това зависи от това дали наистина имате сложна бизнес логика, с която трябва да се справите. Трудно е да се направят конкретни препоръки, без да се знае голямата картина. - person Cerad; 25.08.2016
comment
Между другото, мисля, че този тип въпроси получават по-добър отговор на programmers.stackexchange.com - person Cerad; 25.08.2016
comment
Не бих стигнал толкова далеч и да кажа, че AgrRoots в рамките на една и съща BC звучи като проблем. Вон Върнън в своята книга Implementing DD Design даде пример за Контекст на идентичността и достъпа и той имаше 4 общи корена в контекста. Нямам контексти на потребители или роли. Имам контекст, ограничен от самоличност и разрешения. IMO AR служи като граница на последователност, докато контекстът описва модела на моя проблем. - person Robert; 25.08.2016
comment
@Cerad Два ars в рамките на една и съща bc звучат като проблем. Това е абсолютно неправилно. AR не са поддомейни. В идеалния случай трябва да има един BC на поддомейн и е много вероятно да има няколко AR на BC. Ако всичките ви BC имат обобщени имена, тогава го правите неправилно. BC са автономни компоненти, но има цена, свързана с тази дисоциация (напр. наличие на антикорупционен слой, евентуална последователност и т.н.). - person plalx; 27.08.2016

И двете са еднакво валидни, в зависимост от вашите нужди. GetForUser би било добре, ако искате да се уверите, че извикващият код има валиден потребителски агрегат, преди да се опитате да извлечете ролите - въпреки че свързва customRoleRepository със знанието на потребителския агрегат, ако искате да изисквате извикващият код да има валиден Потребителски агрегат, тогава това свързване има цел.

GetByUserId е по-съвместим с GetById и има по-малко свързване, така че ако във вашия контекст няма значение да извикате GetByUserId дори ако клиентът няма валиден потребителски агрегат, това също е добре.

Ако зареждате ById, открих също, че използването на въведени обекти със стойност на идентичност може да бъде доста полезно за осигуряване на допълнително ниво на безопасност на типа - малко разговор за плюсовете и минусите тук https://stackoverflow.com/a/5377460/6720449 и тук https://groups.google.com/forum/#!topic/dddcqrs/WQ9zRtW3Gbg

person Chris Simon    schedule 25.08.2016