Re: Re: separating global and country-specific logics in large DDD application
Giacomo Tesio <[email protected]>
| Newsgroups | gmane.comp.programming.domain-driven-design |
|---|---|
| Message-ID | <CAHL7psEU-CsRqyrGiRK8HVb7=T9an42gkErL12oB=DQedUU6DQ@mail.gmail.com> |
At implementation time, you can use the Strategy Pattern to cope with these
issues.
But looks like you are keeping the country concept implicit.
Let suppose that, in the context you are talking about, there's a Country
class that is able to apply the logic that differs from country to country.
Your code would be:
class Account {
...
public FlagAsFraudulent(*Country* country) {
// common stuff
this.flags.Add("FRAUD");
...
// country-specific stuff
Country.MethodWithAMeaningfulDomainNameThatIsProbablyACommand(this)
}
This is actually a strategy pattern injected via arguments. But, obviously,
this strategy should emerge from the ubiquitous language and from the
proper responsibility that each model has.
Giacomo
On Tue, Mar 12, 2013 at 3:33 PM, jlamkw <[email protected]> wrote:
> **
>
>
> Thanks Giacomo for sharing your experience.
>
> Our kernel (containing those concepts you mentioned) is definitely going
> to be shared because its very generic and stable. However it is small
> compared to our bounded contexts. If we share only the kernel then a lot of
> the similarities across countries (e.g. the concepts and basic behaviors of
> account, payment, client, ...) cannot be re-used.
>
> Let's say for a particular bounded context 60% of the concepts (e.g.
> accounts) and behaviors will be similar across all countries but each
> country has some variations in say how an account is approved and some new
> account types that are subject to local regulation.
>
> Maybe I'm starting to answer some of my own questions...it may be worth
> considering breaking down the behaviors and move those highly
> country-specific ones out into a different bounded context (e.g. Client
> Sign Up context). That might address some of my problems. But I still
> struggle with shared concepts that require mixed behaviors.
>
> For example in a shared code base one may have a bunch of if-else blocks
> controlling which part of behaviors to apply when invoked based on country
> e.g.
>
> class Account {
> ...
> public FlagAsFraudulent(string country) {
>
> // common stuff
> this.flags.Add("FRAUD");
> ...
>
> // country-specific stuff
> if (country=="UK") {
> ...
> }
> else if (country=="US") {
> ...
>
> That can get messy pretty quickly and doesn't provide any isolation
> between countries which are supposed to be deployed and operated
> independently (E.g. we don't want someone mistaking US for UK when making a
> change). But if we create a new bounded context for each country the common
> behaviors have to be duplicated and maintained separately. I'm hoping to
> find some patterns that can facilitate re-use with a cleaner structure.
>
> Regards
> Joseph
>
>
> --- In [email protected], Giacomo Tesio <giacomo@...>
> wrote:
> >
> > Hi,
> >
> > The key conceptual tool is the "bounded context".
> >
> > You probably have a shared kernel containing concepts like Currency,
> Money,
> > Time (UTC! ;-) and common identifiers (ISIN, MIC and so on...).
> >
> > Then you should isolate different bounded contexts according to the
> > different business rule sets. To take the right direction, I've explored
> > with the domain experts two of the more different regulations, to
> identify
> > common concepts and rules, and after that, I talked with experts from the
> > other 3 country to confirm/dispose the abstractions previously defined.
> >
> > In our business, similarities were few but really stable, so we have
> built
> > one single shared kernel holding them all, and one different domain model
> > for each country. Indeed we realized that the "ubiquitous language" was
> > different in the different countries (outside the common and very
> abstract
> > concepts in the kernel).
> >
> > This lead to different applications for each country (because of the
> > different domain models beyond the kernel), thus it can look expensive,
> but
> > is very flexible (as each country's regulations evolve differently) and
> > cheaper in the long run.
> >
> > On the other hand the shared kernel has had almost no evolution.
> >
> > Note however that with different projects that share part of the domain
> > model (the shared kernel, in my case), you have to set up strict policy
> for
> > versioning and to track dependencies: if you can't, it's cheaper to
> build a
> > completely different application for each country with a shared nothing
> > approach, using cut&paste when appropriate.
> >
> >
> > Some more little suggestions, from my previous experience: keep attention
> > to Exceptions from the domain experts (1) since they help to identify
> > subtle differencies and use immutable value objects widely (2) since they
> > are easier (and thus cheaper) to localize.
> >
> >
> > Hope this helps.
> >
> >
> > Giacomo
> > [1]
> >
> epic.tesio.it/2013/03/04/exceptions-are-terms-ot-the-ubiquitous-language.html
> > [2]
> >
> http://epic.tesio.it/doc/manual/epic-prelude.html#about_interpreting_values
> >
> > On Mon, Mar 11, 2013 at 4:38 PM, jlamkw <jlam@...> wrote:
> >
> > > **
>
> > >
> > >
> > > Hi everyone
> > >
> > > I'm using DDD for a global financial application (ASP.Net front-end WCF
> > > backend, NHibernate) that will be deployed to multiple countries (each
> > > having a completely separate installation and user base). All countries
> > > share some common logics and data (e.g. Account). But each country also
> > > requires some country-specific logics (e.g. extra values in enums, new
> > > properties, different logics for UK-only account types).
> > >
> > > Any suggestions on how should I go about structuring my DDD stack
> > > (entities, domain services and repositories)? I certainly don't want
> all
> > > country-specific logics to end up becoming one big ball of mud so I
> need a
> > > way of keeping the codes for each country separate.
> > >
> > > I've considered various techniques e.g. inheritance, composition,
> partial
> > > classes, complete fork...but none seems to stand out.
> > >
> > > Are there any DDD techniques/patterns for tackling this specific kind
> of
> > > complexity? Those DDD examples I've read in books seem to assume
> universal
> > > / country-agnostic system.
> > >
> > > Regards,
> > > Joseph
> > >
> > >
> > >
> >
>
>
>