Domain seedwork is a separated project with common domain logic: bases for entity, VO, Repository and UoW contracts, Specifications etc.
But I can't decide where to place following:
Validators.
I want to keep Validation Rules separated from Entities. Validation Rule base must be in Domain seedwork as well as Validator contract, but what about Validator implementation?
Business Rules Evaluators.
Same situation but with Business Rules and Business Rules Evaluators.
I'd avoid trying to do validation in one place. The notion of one size fits all is generally nonsense, particularly in DDD. You can add the most basic validation into your entities, to ensure your entities are never in an invalid state. Apart from that, your validation logic should probably go where you are validating, i.e. UI validation logic, should go in the UI/presentation layer.
Business rules should go in your domain model.
While I was formulating the question, answer came. Please, correct me if I missed something.
Domain seedwork must contain common logic used only by Domain. Logic that can be used in multiple layers, must be in Cross-cutting.
Therefore, Validator contract and implementation must be in Cross-cutting as well as Business Rules Evaluator. Validation Rule base and Business Rule base is used only by Domain and must be in Domain seedwork.
UPDATE.
There is another option: Validator and Business Rules Evaluator is bases living in Domain seedwork and used for specific implementations like CustomerCanPersistedValidator.
Related
I thinking about modeling aggregates, invariants, data etc. There is common advice to design aggregates to be small. I have problem a with correct splitting domain and simple CRUD.
Let's assume that we have application where we are able to create project and join to it collaborators. There are a lot of informations related with project at the stage of creating (name, description, project_aims, notes, creation date, modified date, collaborators). How to correct design aggregate where there is a rule which check that we can only add 5 collaborators. Taking into consideration that fields name, description, project_aims, notes doesn't really take part in any business rule and there is only requirements that this fields should'nt be empty (those are really invariants?) should those fields really be a part of aggregate?
Is'nt that our real Domain (aggregates, entities, value objects, policies) should hold only data which take part with protecting invariants or help making business decisions?
If so, how to (create) project described above? Should class with all that nonsignificant (from a business point of view) fields be implemented as anemic model outside the Domain and Aggregate root should just have method addCollaborator which protect quantity of collaborators? Is it good idea to save anemic class object using Dao (operates on db table) and for Domain implementation of aggregate, create Repository?
How to add first collaborator during creating project as at the beggining we create anemic class object outside Domain?
Thank you for any help and advice
Papub
"How to correct design aggregate where there is a rule which check that we can only add 5 collaborators"
Project AR most likely maintains a set of collaborators and throws whenever it's size would exceed 5.
"there is only requirements that this fields should'nt be empty (those are really invariants?)"
Yes, these may be simple rules, but are still are invariants.
"should hold only data which take part with protecting invariants or help making business decisions"
This can be done when modeling ARs with EventSourcing, where you'd only materialize the properties needed to check invariants on the AR, while having all data in the full set of events.
"implemented as anemic model outside the Domain and Aggregate root should just have method addCollaborator which protect quantity of collaborators".
You could always attempt to mix CRUD-driven anemia with rich always-valid models, but the anemic/rich model decision is usually consistent for a given Bounded Context (BC), meaning you may have CRUDDy BCs and rich domain model BCs, but rarely both strategies in the same BC.
For instance, perhaps "Project Definition" is a CRUD-driven BC while "Collaboration" isin't. Those BCs may not make any sense, but it's just to give an example.
Furthermore, don't forget DDD tactical patterns are there to allow manage the complexity, they aren't hard rules. If handling a part of your AR through services and another (where there's more meat) with rich behaviors then perhaps that's acceptable. Still, I'd probably prefer CRUDDy behaviors on the ARs themselves like an update method rather than giving up in the anemic direction.
Currently um working in an application and it has the following hierarchy
WEB API2 Controllers (hilds the end points)
Business Logic Layer (Dedicated for business logic handling )
Data Access Layer (Repositories)
If we want to impose a validation which does not related to a business logic as for an example a character count validation for a specific field in an entity , what will be the ideal place to implement it?
Some says it should be on Controller it self , but I cannot agree with it .
You must not be dogmatic when using layered architecture. You may measure some abstraction to any piece of function. This measure can well be flexible.
In your concrete example you are looking at validating a string size for an entity. Now, the name entity puts this near the data layer, which is where I would place it. So your data layer may raise an access violation if someone tries to place an entity with a wrong length.
In my business domain an entity "CompanyPrefix" appears to extend a VO CompanyPrefixVO that keeps all business rules. No other class would be using this VO. As a good practice:
should I extend CompanyPrefix from CompanyPrefixVO? or
drop the VO and merge business rules into entity CompanyPrefix? or
CompanyPrefix should only be associated with CompanyPrefixVO? or
something totally different?
Inheritance can lead to many problems, first of all high coupling and strong dependencies which can hinder your domain model from evolving. I'd use composition instead. The Value Object can be part of the Entity.
That said I'd also ask a few questions: What kind of business entity would CompanyPrefix be? Is it not just part of a name or identifier? Does it have a lifecycle of its own, i.e. does it change its properties over time? Why does the prefix need an ID? Just for normalization (aka database details that don't belong in the domain model?)
I don't know your specific case but there simply might be a VO representing a company prefix as part of the company.
When you are developing an architecture in OO/DDD style and modeling some domain entity e.g. Order entity you are putting whole logic related to order into Order entity.
But when the application becomes more complicated, Order entity collects more and more logic and this class becomes really huge.
Comparing with anemic model, yes its obviously an anti-pattern, but all that huge logic is separated in different services.
Is it ok to deal with huge domain entities or i understand something wrong?
When you are trying to create rich domain models, focus entities on identity and lifecyle, and thus try to avoid them becoming bloated with either properties or behavior.
Domain services potentially are a place to put behavior, but I tend to see a lot of domain service methods with behavior that would be better assigned to value objects, so I wouldn't start refactoring by moving the behavior to domain services. Domain services tend to work best as straightforward facades/adaptors in front of connections to things outside of the current domain model (i.e. masking infrastructure concerns).
You can also put behavior in Application services, but ask yourself whether that behavior belongs outside of the domain model or not. As a general rule, try to focus application services more on orchestration-style tasks that cross entities, domain services, repositories.
When you encounter a bloated entity then the first thing to do is look for sets of cohesive set of entity properties and related behavior, and make these implicit concepts explicit by extracting them into value objects. The entity can then delegate its behavior to these value objects.
Since we all tend to be more comfortable with entities, try to be more biased towards value objects so that you get the benefits of immutability, encapsulation and composability that value objects provide - moving you towards a more supple design.
Value objects enable you to incorporate a more functional style (eg. side-effect-free functions) into your domain model and thus free up your entities from having to deal with the complexity of adding complicated behavior to the burden of managing identity and lifecycle. See the pattern summaries for entities and value objects in Eric Evan's http://domainlanguage.com/ddd/patterns/ and the Blue Book for more details.
When you are developing an architecture in OO/DDD style and modeling
some domain entity e.g. Order entity you are putting whole logic
related to order into Order entity. But when the application becomes
more complicated, Order entity collects more and more logic and this
class becomes really huge.
Classes that have a tendency to become huge, are often the classes with overlapping responsibilities. Order is a typical example of a class that could have multiple responsibilities and that could play different roles in your application.
Given the context the Order appears in, it might be an Entity with mutable state (i.e. if you're managing Order's commercial condition, during a negotiation phase) but if you're application is managing logistics, an Order might play a different role: and an immutable Value Object might be the best implementation in the logistic context.
Comparing with anemic model, yes its
obviously an anti-pattern, but all that huge logic is separated in
different services.
...and separation is a good thing. :-)
I have got a feeling that the original model is probably data-centric and data serving different purposes (order creation, payment, order fulfillment, order delivery) is piled up in the same container (the Order class). Can't really say it from here, but it's a very frequent pattern. Not all of this data is useful for the same purpose at the same time.
Often, a bloated class like the one you're describing is a smell of a missing separation between Bounded Contexts, and/or an incomplete Aggregate separation within the same bounded context. I'd have a look to:
things that change together;
things that change for the same reason;
information needed to fulfill behavior;
and try to re-define aggregate boundaries accordingly. And also to:
different purposes for the application;
different stakeholders;
different implicit models/languages;
when it comes to discover the involved contexts.
In a large application you might have more than one model, thus leading to more than a single representation of a single domain concept, at least for concepts that are playing many roles.
This is complementary to Paul's approach.
It's fine to use services in DDD. You will commonly see services at the Domain, Application or Infrastructure layers.
Eric uses these guidelines in his book for spotting when to use services:
The operation relates to a domain concept that is not a natural part of an ENTITY or VALUE OBJECT.
The interface is defined in terms of other elements in the domain model
The operation is stateless
I'm novice in DDD and CQRS patters and I want to have your opinion how a domain entity can be validated.
I'm going to use the common example Order->OrderLine, where Order is the AR.
The validation of business rules in an Aggregate is through the AR for consistency matters.
How can I validate a business rule that need data outside the Aggregate of Order?
I'm using also CQRS approach and I think that using the ReadModel to get the data that I need to make the validation of my business rules is not a bad option...What do you think?
With my experience of CQRS I associate the ReadModel as being eventually consistent, and therefore I wouldn't be 100% confident in the ReadModel representing the current state of the system. This becomes more the case when you want to distribute and replicate your ReadModels.
I would only want to use the ReadModel to limit the number of invalid commands being sent to your application.
It sounds to me that you want to start thinking about Domain Services, which can be used to encapsulate domain logic that falls outside the boundary of a single aggregate/entity/value object.
As David points out here Implement Domain Services as Extension Methods for the repository, Jimmy Bogard has a definition http://lostechies.com/jimmybogard/2008/08/21/services-in-domain-driven-design/
Yes, use the read model for command validation. I call this "command context" - the current state of the world, based on which command may be valid or invalid. In CQRS, this current state of the world is represented in your read model. User is making decisions based on it, what commands should be issued.
You may also consider various ways to guide user decisions, so that he doesn't issue invalid commands (warn in advance if username in not unique, etc).