Комуникация между ограничени контексти

Имам приложение WinForms, което се надявам да преработя, за да използвам DDD архитектура. Първо, опитвам се наистина да обмисля самата архитектура, имам книгата на Евънс и книгата на Върнън и намирам, че се боря с три сценария, с които бих се сблъскал по-скоро веднага в кандидатурата си. Страхувам се, че може да прекаля с мисленето или да бъда твърде стриктен в моя концептуален процес на проектиране.

1.) Използвайки пример, предоставен в урока на Pluralsight за DDD, лекторът отбеляза, че различните ограничени контексти трябва да бъдат представени чрез собствено решение. Въпреки това, ако имам приложение winforms, което не е ориентирано към услуги (това в крайна сметка ще се промени и голяма част от този въпрос става спорен), това не изглежда осъществимо. Следователно работя при предположението, че ще ги разделя на различни проекти/пространства от имена, като внимавам, че няма взаимозависимости. Това ли е правилният начин да мислим за това или пропускам нещо очевидно?

2.) Имам потребителски интерфейс за навигация, който стартира други модули/прозорци, които биха принадлежали към отделни презентационни слоеве на различни ограничени контексти. Помислете за първия прозорец, който ще бъде отворен, когато стартирате ERP приложение. Тъй като това не се вписва точно в нито един конкретен BC, как нещо подобно ще бъде правилно приложено. Това трябва ли да попада в споделено ядро?

3.) Имам ограничен контекст за Управление на длъжности и ограничен контекст за рейтинг/разходи. Част от бизнес процеса е, че когато се създава задание, неговите детайли се оценяват. Това има свой собствен потребителски интерфейс и т.н., което ми се струва доста добре, че тази презентация все още адекватно попада в контекста на управлението на работата. Въпреки това, действителният процес на оценка на тези подробности определено не трябва. Не съм напълно сигурен как да комуникирам с контекста на рейтинг/цена, тъй като bc трябва да се държат отделно един от друг. Осъзнавам, че мога да изпращам съобщения, но това изглежда прекалено много за неразпространено приложение. Всеки BC би могъл да хоства самостоятелно някакъв вид API, но това отново изглежда прекалено, въпреки че това би подготвило екипа добре за мигриране към разпределена архитектура по-късно. И накрая, последната ми идея е да имам някаква споделена зависимост, която е нещо като магазин за събития. Не знам дали това е същото като събитията в домейна, тъй като те изглежда имат отделна грижа сами по себе си. И така, това означава ли, че това също ще попадне под споделено ядро ​​или някакъв друг тип решение?

Благодаря ви предварително.


person joshlrogers    schedule 24.05.2013    source източник


Отговори (3)


1) Указанията относно BC, съответстващи на решението, са само насоки, а не строго правило. Въпреки това, той осигурява така необходимата изолация. Все още можете да имате това с проект WinForms. Да предположим например, че имате BC, наречен Клиенти. Създайте решение за него и в него създайте допълнителен проект, наречен Customers.Contracts. Този проект ефективно съдържа обществения договор на BC, който се състои от DTO, команди и събития. Външните BC трябва да могат да комуникират с BC на клиенти, като използват само съобщенията, дефинирани в този проект за договори. Накарайте решението WinForms да препраща към Customers.Contracts, а не към проекта Customers.

2) Потребителският интерфейс често изпълнява съставяща роля, организирайки много BC - съставен потребителски интерфейс. Стереотипен пример е продуктовата страница на Amazon. За изобразяването на страницата са необходими стотици услуги от различни BC.

3) Отново това изглежда като сценарий, изискващ съставен потребителски интерфейс. Презентационният слой може да посредничи между различни BC. BC са слабо свързани, но все още има връзки между BC. Някои са надолу по течението от други, някои са нагоре по течението или дори и двете. Всеки има антикорупционен слой, порт, за интегриране със свързани BC.

person eulerfx    schedule 24.05.2013

Усещането, което получавам от тези въпроси, може да се обобщи като: „Какъв е разумният подход към границите на BC от гледна точка на артефакт на код? и Как да създам потребителски интерфейс, който едновременно запитва и командва няколко BC?“. Зависи ...

Друг, все още неспоменат подход може да бъде разглеждането на потребителския интерфейс като отделен контекст. Съмнявам се, че е много популярен POV, но понякога може да бъде полезен. Потребителският интерфейс може да диктува от какво се нуждае, като напр. свои собствени интерфейси и структури от данни и всеки BC да внедри подходящите интерфейси (извършвайки вътрешен превод). Недостатъкът е, че се извършва допълнителен превод, но от друга страна има смисъл само когато има достатъчна стойност, която да се извлече. Стойността е в поддържането на нещата прости от страна на потребителския интерфейс и без да се налага да се тревожите как и откъде идват данните или как промените засягат всеки BC. Всичко това може да се справи зад проста фасада. Има няколко места, които тази фасада може да постави (на клиента или на сървъра). Не се заблуждавайте обаче, „сложността“ току-що се премести зад още един слой. Координация и упорита работа все още трябва да се направи.

Като алтернатива може също да искате да разгледате това, което наричам „подравняване“ на потребителски интерфейс със случаи на употреба, изложени от BC. Както Том спомена, внедряването на работен процес или сага може да бъде полезно, за да се осъществи това, когато се изисква координация. Поставянето под съмнение на изискванията за последователност (кога този друг BC трябва да знае за дадена информация?) може да доведе до нов поглед върху това как BC взаимодействат. Виждате ли, потребителският интерфейс е много полезна верига за обратна връзка. Когато не е в съответствие със случая на използване на BC, може би има нещо нередно в случая на използване или може би има нещо нередно в начина, по който е проектиран в потребителския интерфейс, или може би просто сме разкрили различен случай на употреба. Ето защо макетите на потребителския интерфейс са толкова чудесен инструмент за водене на дискусии. Те предлагат ДОПЪЛНИТЕЛЕН поглед върху същия проблем/решение. Допълнително като „това не е единствената визуализация, която трябва да използвате в разговори с експерт по домейн“. Изискванията за UX също са изисквания. За тях трябва да се погрижат.

Лично аз намирам, че когато обсъждам UI, нося друга шапка, отколкото когато обсъждам чиста функционалност (знаете, неща, които не изискват UI, за да обяснят какво прави/трябва да прави приложението). Може да разменя шапките по време на един и същи разговор, само за да открия несъответствие.

person Yves Reynhout    schedule 26.05.2013

Първо, тъй като видях, че говорите за автобус за съобщения, мисля, че първо трябва да поговорим за интеграцията на BC.

Не се нуждаете от шина за съобщения, за да комуникирате между BC; ето обяснение как интегрирам различни BC:

Излагам някои публични интерфейси на всеки BC (подобно на команди на домейн, - заявки и - събития) и имам междинен слой в моята инфраструктура, който превежда това повикване към другия BC.

Ето примерен интерфейс за открити команди в BC:

public interface IHandleCommands
{
    void DoSomething(Guid SomeId,string SomeName);
}

Имам и подобен за експонирани събития

public interface IPublishEvents 
{
   void SomethingHappened(Guid SomeId,string SomeName);
}

И накрая за моите изложени данни (т.е. заявките в CQ(R)S) имам друг интерфейс, моля, имайте предвид, че това ви позволява да премахнете връзката между модела на вашия домейн и кода на заявката във всеки един момент.

public interface IQueryState
{
    IEnumerable<SomeData> ActiveData(DateTime From=DateTime.Minvalue, ... );
}

И моето изпълнение изглежда така:

public class SomeAR:IHandleCommands
{
    IPublishEvents Bus;

    public SomeAr(IPublishEvents Bus) 
    {
       this.Bus = Bus;
    }

    public void DoSomething(Guid x,string y)
    {
       Bus.SomethingHappened(SomeId: x,SomeName: y);
    }
}

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

След това тези манипулатори извикват команди на други BC; те са като лепилото, което свързва различни BC (помислете за работни процеси/саги без състояние и т.н.).

Това може да е примерен манипулатор:

public class WorkFlow : IPublishEvents
{
  public void SomethingHappened(Guid SomeId,string SomeName) 
  {
     AnotherBC.DoSomething(SomeId,SomeName);
  }
}

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

За да отговорите на вашите въпроси относно потребителския интерфейс:

Мисля, че сте твърде твърд по този въпрос.

Докато моят домейн е (или може лесно да бъде) отделен от вашия потребителски интерфейс, можете лесно да започнете с един потребителски проект и след това да го разделите в момента, в който започнете да изпитвате болка някъде. Ако обаче разделите кода, трябва да го разделите на BC, така че структурите на проекта да съвпадат.

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

person Tom    schedule 25.05.2013