In a DDD architecture, where does a unique ID generation belong to? - oop

Let's say I have a "Project" entity in my domain, that has a to have a unique ID generated (on top of the normal numeric ID) that is 2 letters + 4 digits for every Project. This id has to be unique among all the Projects.
I am having a difficult time placing this functionality, it feels like It should almost only just be placed in the repository when the Project is being saved the first time.
I am sure it doesn't belong to Application services, I am not sure if it is any of the business layers concern to be a domain service, and it feels weird to put it as infrastructure service, but it does need to check if any other Projects exist with a randomly generated [LL]-[DDDD] like code or not.
Even if I place this code around the repository.save it still has to call something from somewhere, so the question is, where should I put a service that gives me a free random Id like that?

Ids which are part of the domain should be generated by the domain.
If the domain do not define any ids you should not expose them in the domain either (strictly speaking, but it's probably easier to include them either way).

Your question mentions a 'normal ID'. I'm assuming that this is your DB's primary key and that the ID you want to generate here is for humans (although why humans would use a 2-letter+4-digit identifier is beyond me, but I've seen worse). In this case, the generation of the key is a business function and ensuring it is unique is a business rule. Both of these things are properly the responsibility of the domain objects. Given your object name, Project, and the language you use in your question, I'd suggest that maybe the Projects object should provide this service. The reason for this is that only the Projects object would have a view over all project objects you've created to check for uniqueness.
Of course, you could have an algorithm to generate this field that ensures uniqueness without having to check all projects (a good idea, btw). In which case you'd probably allow a project to generate its own ID at an appropriate time in its lifecycle (probably when it is created).

The "free random id" or ID generation is part of the infrastructure rather than the business domain so I would add that logic to a persistence layer and call that from within my repositories. e.g ProjectRepository. Assume that the Project entity would have an 'id' field in any case. You can enforce validation in the Project entity so that the id format is 2 letters and 4 digits but only do that if Project ids are different to other entity ids in your application

The first question you need to ask yourself is - why is this constraint on Project ID necessary? Does the user need to know about Project IDs?
If it's informative to the user or if you are implying a form of catalogue of projects, this is a business rule that belongs to the domain. It might require updating your domain model, and therefore refactoring your code in accordance with the new model. Actual id generation will be done by the infrastructure layer, as a new Project is added to the system, but it will use a STRATEGY that expresses the business rule and is defined in the domain layer.
If it's merely a technological requirement, but has no semantic meaning in the domain, either remove the constraint, or place it in the infrastructure layer.
In any case, the infrastructure layer can provide an infrastructure service for id generation of new project entities, which the class responsible for Project entity creation may use (for example, a Project Factory). Project Factories belong to the domain layer, even though they may use an infrastructure service.

Unique identifier generation would normally be an application concern -- these identifiers are analogous to random numbers, or time. They are an input to the deterministic parts of the system.
If you don't consider time an input value, think about it until you do - it is an important concept -- John Carmack, 1998
Ensuring that an identifier (however it was generated) satisfies some uniqueness constraint would be a domain concern, and falls into the general category of set validation.
Note Greg Young's observation:
What is the business impact of having a failure?
If the cost of a failure is small, if failures are easily detected and remedied, then it may be most practical to lean into a "best effort" design. UUID's aren't unique (finite number of bits, we're going to use them all up eventually), but at the scales we are working at the probability of collision is really small. So often, we can just live with it.
But when the impact of a failure is high....
Ensuring that some policy applies to the entire set requires being able to lock the entire set against concurrent modification.
In the easy case - each unique identifier has its own set. One way of framing how repositories work is that they give you the set of all aggregates that match the provided key, and your domain logic is responsibly for ensuring that set has at most one element in it.
In harder cases, the set itself becomes an aggregate, with its own lock, and the domain logic ensures that the each change maintains the invariant of the set. Often, this requires doing a deep analysis of the model to understand which information is actually under the authority of the set, rather than under the authority of other aggregates.

Related

Domain Driven Design - Creating general purpose entities vs. Context specific Entities

Situation
Suppose you have Orders and Clients as entities in your application. In one aggregate, the Order entity is considered to be the root but you also want to make use of the Client entity for simple things. In another the Client is the root entity and the Order entity is touched ever so lightly.
An example:
Let's say that in the Order aggregate I use the Client only to read details like name, address, build order history and not to make the client do client specific business logic. (like persistence, passwords resets and back flips..).
On the other hand, in the Client aggregate I use the Order entity to report on the client's buying habbits, order totals, order counting, without requiring advanced order functionality like order processing, updating, status changes, etc.
Possible solution
I believe the better solution is to create the entities for each aggregate specific to the aggregate context, because making them full featured (general purpose) and ready for any situation and usage seems like overkill and could potentially become a maintenance nightmare. (and potentially memory intensive)
Question
What is the DDD recommended way of handling this situation?
What is your take on the matter?
The basic driver for these decisions should be the ubiquitous language, and consequently the real world domain you're modeling. If both works in a specific domain, I'd favor separation over god-classes for maintainability reasons.
Apart from separating behavior into different aggregates, you should also take care that you don't mix different bounded contexts. Depending on the requirements of your domain, it could make sense to separate the Purchase Context from the Reporting Context (to extend on your example).
To decide on a context design, context maps are a helpful tool.
You are one the right track. In DDD, entities are not merely containers encapsulating all attributes related to a "subject" (for example: a customer, or an order). This is a very important concept that eludes a lot of people. An entity in DDD represents an operation boundary, thus only the data necessary to perform the operation is considered to be a part of the entity. Exactly which data to include in an entity can be difficult to consider because some data is relevant in a different use-cases. Here are some tips when analyzing data:
Analyze invariants, things that must be considered when applying validation rules and that can not be out of sync should be in the same aggregate.
Drop the database-thinking, normalization is not a concern of DDD
Just because things look the same, it doesn't mean that they are. For example: the current shipping address registered on a customer is different from the shipping address which a specific order was shipped to.
Don't look at reads. Reading, like creating a report or populating av viewmodel/dto/whatever has nothing to do with operation boundaries and can typically be a 360 deg view of the data. In fact don't event use your domain model when returning reads, use a different architectural stack.

Aggregate - Correct Usage (DDD)

I have been trying to get started on Domain Driven Design (DDD) and therefore I've been studying it for a while now. I have a problem and I seek help around how I can solve it in a DDD fashion.
I have a Client class, which contains a hell lot of attributes - some of them are simple attributes, such as string contactName whereas others are complex ones, such as list addresses, list websites, etc.
DDD advocates that Client should be an Entity and it should also be an Aggregate root - ie, the client code should manipulate only the Client object itself and it's down to the Client object to perform operations on its inner objects (addresses, websites, names, etc.).
Here's the point where I get confused:
There are tons of business rules in the application that depend on the Client's inner objects - for instance:
Depending on the Client's country of birth or resident and her address, some FATCA (an US regulation) restrictions may be applicable.
I need to enrich some inner objects with data that comes from other systems, both internal to my organisation as well as external.
The application has to decide whether a Client is allowed to perform an operation and to that end, the app needs to scrutinize a lot of client details and make a decision - also, as the app scrutinizes the Client it needs to update many of its attributes to keep track of what led the application to that decision.
I could list hundreds of rules here - but you get the idea. My point is that I need to update many of the Client's inner attributes. From the domain perspective, the root is the Client - it's the Client that the user searches for in the GUI. The user cares only about the Client as a whole. Say, an isolated address is meaningless - it only exists if it's part of a Client.
Having said all that, my question is:
Eric Evans says it's OK for the root to return transient references to inner objects, preferably VOs (keyword here: VO) - but any manipulation on the inner objects should be performed by the root itself.
I have hundreds of manipulations that I need to perform on my clients - if I move all of them to the root, the root is going to become huge - it will have at least 10K lines of code!
According to Eric, a VO should be immutable - so if my root returns VOs, the client code won't be allowed to change them. So doing something like this would be unacceptable in a service: client.getExternalInfo().update(getDataFromExternalSystem())
So my question boils down to how on Earth I should update the inner objects without breaking the DDD rules?
I don't see any easy way out.
UPDATE I:
I've just come across Specifications, which seems to be the ideal DDD concept to my problem.
I'm still reading about it but I have decided to post this update anyway.
I have been studying DDD for awhile myself and am struggling to master it.
First, you're right: Specification is a fine pattern to use for validation or business rules in general, assuming the rules you are applying fit well with a predicate tree.
Of course, I don't know the specifics of your design, but I do wonder about the model itself. You mention that your Client class has "a hell lot of attributes". Are you sure your model is not somewhat anemic? Could your design benefit from some more analysis, perhaps breaking it out into other Aggregates? Is this a single Bounded Context? Should it be?
Specifications is definitely the way to go for complex business logic.
One question though - are you modeling the inner entities like addresses and names as ValueObjects? The best rule of thumb I can think of for those is if you can say they're equal, without an ID, they're likely value objects. Does your domain consider names to have a state?
If you're looking at a problem where few entities take in many types of change AND need an audit trail, you might want to also explore EventSourcing. Ideally the entity declares its reaction to an event, but you can also have the mutating code be held in the event for easy extensibility. There's pros and cons in that approach, of course.

Should the rule "one transaction per aggregate" be taken into consideration when modeling the domain?

Taking into consideration the domain events pattern and this post , why do people recomend keeping one aggregate per transaction model ? There are good cases when one aggregate could change the state of another one . Even by removing an aggregate (or altering it's identity) will lead to altering the state of other aggregates that reference it. Some people say that keeping one transaction per aggregates help scalability (keeping one aggregate per server) . But doesn't this type of thinking break the fundamental characteristic about DDD : technology agnostic ?
So based on the statements above and on your experience, is it bad to design aggregates, domain events, that lead to changes in other aggregates and this will lead to having 2 or more aggregates per transaction (ex. : when a new order is placed with 100 items change the customer's state from normal to V.I.P. )?
There are several things at play here and even more trade-offs to be made.
First and foremost, you are right, you should think about the model first. Afterall, the interplay of language, model and domain is what we're doing this all for: coming up with carefully designed abstractions as a solution to a problem.
The tactical patterns - from the DDD book - are a means to an end. In that respect we shouldn't overemphasize them, eventhough they have served us well (and caused major headaches for others). They help us find "units of consistency" in the model, things that change together, a transactional boundary. And therein lies the problem, I'm afraid. When something happens and when the side effects of it happening should be visible are two different things. Yet all too often they are treated as one, and thus cause this uncomfortable feeling, to which we respond by trying to squeeze everything within the boundary, without questioning. Still, we're left with that uncomfortable feeling. There are a lot of things that logically can be treated as a "whole change", whereas physically there are multiple small changes. It takes skill and experience, or even blunt trying to know when that is the case. Not everything can be solved this way mind you.
To scale or not to scale, that is often the question. If you don't need to scale, keep things on one box, be content with a certain backup/restore strategy, you can bend the rules and affect multiple aggregates in one go. But you have to be aware you're doing just that and not take it as a given, because inevitably change is going to come and it might mess with this particular way of handling things. So, fair warning. More subtle is the question as to why you're changing multiple aggregates in one go. People often respond to that with the "your aggregate boundaries are wrong" answer. In reality it means you have more domain and model exploration to do, to uncover the true motivation for those synchronous, multi-aggregate changes. Often a UI or service is the one that has this "unreasonable" expectation. But there might be other reasons and all it might take is a different set of abstractions to solve the same problem. This is a pretty essential aspect of DDD.
The example you gave seems like something I could handle as two separate transactions: an order was placed, and as a reaction to that, because the order was placed with a 100 items, the customer was made a VIP. As MikeSW hinted at in his answer (I started writing mine after he posted his), the question is when, who, how, and why should this customer status change be observed. Basically it's the "next" behavior that dictates the consistency requirements of the previous behavior(s).
An aggregate groups related business objects while an aggregate root (AR) is the 'representative' of that aggregate. Th AR itself is an entity modeling a (bigger, more complex) domain concept. In DDD a model is always relative to a context (the bounded context - BC) i.e that model is valid only in that BC.
This allows you to define a model representative of the specific business context and you don't need to shove everything in one model only. An Order is an AR in one context, while in another is just an id.
Since an AR pretty much encapsulates all the lower concepts and business rules, it acts as a whole i.e as a transaction/unit of work. A repository always works with AR because 1) a repo always deals with business objects and 2) the AR represents the business object for a given context.
When you have a use case involving 2 or more AR the business workflow and the correct modelling of that use case is paramount. In a lot of cases those AR can be modified independently (one doesn't care about other) or an AR changes as a result of other AR behaviour.
In your example, it's pretty trivial: when the customer places an order for 100 items, a domain event is generated and published. Then you have a handler which will check if the order complies with the customer promotions rules and if it does, a command is issued which will have the result of changing the client state to VIP.
Domain events are very powerful and allows you to implement transactions but in an eventual consistent environment. The old db transaction is an implementation detail and it's usually used when persisting one AR (remember AR are treated as a logical unit but persisting one may involve multiple tables hence db transaction).
Eventual consistency is a 'feature' of domain events which fits naturally a rich domain (and the real world actually). For some cases you might need instant consistency however those are particular cases and they are related to UI rather than how Domain works. Of course, it really depends from one domain to another. In your example, the customer won't mind it became a VIP 2 seconds or 2 minutes after the order was placed instead of the same milisecond.

Should an aggregate root's behaviour be dependent on other aggregate root's attributes?

I'm reading a book about DDD and i see an example domain that involves cars, engines, wheels and tires .
Above is the model as it is in the book . Customer is also aggregate root .
Having that model , there might be a case where the engine could have height, width and length attributes.
What happens when you need to attach a big engine on a small car ? The engine could not fit .
Is it a problem if the car checks for the engine attributes and allows it or not to be a part of the car ?
The engine has global identity (like you know each engine has a serial/manufacturer number). Maybe the engines need to be tracked by the manufacturer .
So I'm asking again , is it a problem if the car is using the engine's attributes to fit it inside (to allow it or not to be part of it) ?
Is it a problem if the car checks for the engine attributes and allows it or not to be a part of the car?
No.
That being said, your validation may be complex enough to introduce a domain service. Since two aggregates are involved you could have this:
car.Fit(engine)
Or this:
engine.Fit(car)
However, you probably want to be checking against a car model anyway :)
Since the rules are going to be somewhat more advanced and involve some data you probably want to introduce a domain service and possibly use double-dispatch on the objects:
So rather than car.Fit(engine) you could have this:
car.Fit(engine, IModelServiceImplementation)
And in the Fit method call:
if (!IModelServiceImplementation.CanFit(car, engine)) { throw new Exception(); }
The service could possibly load the correct model and rather check that against the engine. Depending on the domain one may even have modification levels and other rules to deal with.
Since a Car instance would not contain the actual Engine instance but only the EngineId or possibly some value object there would be no real assignment of engine to car. You could still pass the engine instance to the car and have it create the association however it sees fit.
The solution proposed by 'Enrico S.' is possibly more relevant to scenarios where changes are effected on the aggregate roots where one may not have all the aggregate roots available or even where aggregate roots live in separate bounded contexts. Even if Car and Engine were in separate BCs one would probably be able to query the validity somehow. Some things are fine for eventual consistency but others may not be.
As usual there are many things to consider :)
From DDD book, p128:
Any rule that spans AGGREGATES will not be expected to be up-to-date at all times. Through event processing, batch processing, or other update mechanisms, other dependencies can be resolved within some specific time.
So, it really depend on what Car aggregate is deigned for: if it requires strong consistency with the Engine, then the Engine should be part of the Car aggregate.
Other way, if it require only "eventual consistency", you might put that validation logic inside a Domain Event.
See this Udi Dahan's post

Service Design (WCF, ASMX, SOA)

Soliciting feedback/thoughts on a pattern or best practice to address a situation that I have seen a few times over the years, yet I haven't found any one solution that addresses it the way I'd like.
Here is the background.
Company has 3 applications supporting 3 separate "lines of business" that are very much related to each other. Two of the applications are literally copy/paste from the original. The applications need to be able to grow at different rates and have slightly different functionality. The main differences in functionality come from the data entry fields. The differences essentially fall into one of the following categories:
One instance has a few fields
that the other does not.
String field has a max length of 200 in one
instance, but 50 in another.
Lookup/Reference fields have
different underlying values (i.e.
same table structures, but coming
from different databases).
A field is defined as a user supplied,
free text, value in one instance,
but a lookup/reference in another.
The problem is that there are other applications within the company that need to consume data from these three separate applications, but ideally, talk to them in a core/centralized manner (i.e. through a central service rather than 3 separate services). My question is how to handle, in particular, item D above. I am thinking a "lowest common denominator" approach might be the only way. For example:
<SomeFieldName>
<Code></Code> <!-- would store a FK ref value if instance used lookup, otherwise would be empty or nonexistent-->
<Text></Text> <!-- would store the text from the lookup if instance used lookup, would store user supplied text if not-->
</SomeFieldName>
Other thoughts/ideas on this?
TIA!
So are the differences strictly from a Datamodel view or are there functional business / behavioral differences at the application level.
If the later is the case then I would definetly go down the path you appear to be heading down with SOA. Now how you impliment your SOA just depends upon your architecture needs. What I would look at for design would be into some various patterns. Its hard to say for sure which one(s) would meet the needs with out more information / example on how the behavioral / functional differences are being used. From off of the top of my head tho with what you have described I would probably start off looking at a Strategy pattern in my initial design.
Definetly prototype this using TDD so that you can determine if your heading down the right path.
How about: extend your LCD approach, put a facade in front of these systems. devise a normalised form of the data which (if populated with enough data) can be transformed to any of the specific instances. [Heading towards an ESB here.]
Then you have the problem, how does a client know what "enough" is? Some kind of meta-data may be needed so that you can present a suiatble UI. So extend the services to provide an operation to deliver the meta data.