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.
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.
For some time I am dealing with Domain-Driven Design. Unfortunately I have some problems regarding the Aggregate.
Say, I like to model the structure of an university. The university has some departments (faculties) and every department has some classes. There is a rule that every department needs to be unique and so every class in it. For instance the names of the classes needs to be unique. If I understand it right, then "University" seems to be my aggregate root and "department" and "class" are entities within this aggregate.
There is another aggregate root "Professor", because they are globally accessible. They will be assigned to a class. I´m unsure if it is allowed because an aggregate root should only point to another aggregate root and not to its content.
How to handle this?
Appreciate your help,
thanks in advance!
Say, I like to model the structure of an university. The university has some departments (faculties) and every department has some classes. There is a rule that every department needs to be unique and so every class in it. For instance the names of the classes needs to be unique.
Really? why? What's the business value of that rule? What does it cost the business (the university) if there happen to be two classes with the same name. Does that mean the same name across all time, or just during a given semester?
Part of the point of DDD is that the design of the solution requires exploration of the "ubiquitous language" to get a full understanding of the requirement.
In other words, you may be having trouble finding a good fit for this requirement in the design because you haven't yet discovered all of the entities that you need to make it work the way the business experts expect.
Udi Dahan points out that the uniqueness rule may not belong in the domain at all:
Rules that are not part of genuine domain logic do not have to be implemented in the domain model, suggested he, because they do not model the domain.
So if you have a constraint like this, but the constraint isn't a consequence of the domain itself, then the constraint can be correctly implemented elsewhere.
Greg Young has also written about set validation, specifically addressing concerns about eventual consistency.
But broadly, yes -- if you really have a collection of entities, and a domain rules that span multiple elements in the collection, then you need some aggregate that maintains the integrity of the boundary that the collection lives in.
The entities aren't necessarily what you think. For instance, if you need names to be unique, and the rest of the class entity is just along for the ride, then you may be able to simplify the rules by creating a name registry aggregate; Professors reserve names for their classes, and if the reservation is available, then the reserved name can be applied to the class entity.
If your core business really were naming things, with lots of special invariants to consider, you might build out a big model around this. But that's not particularly likely; perhaps you can just slap a table or two into a relational database -- that's a good solution for a set validation problem -- and get on with the valuable part of the project.
There is another aggregate root "Professor", because they are globally accessible. They will be assigned to a class. I´m unsure if it is allowed because an aggregate root should only point to another aggregate root and not to its content.
class.assign(professorId);
is the usual sort of answer here -- you pass around the surrogate key that identifies the aggregate root. Every entity in your domain should have one.
A couple of cautions here: I have found that real world entities (people, in particular) aren't a useful starting point for figuring out what aggregates are for. Primarily, because they end up being representations, primarily, of data where the invariant is enforced outside the domain model.
Also, I've found that starting from the nouns - class, department, professor - tends to put the focus on CRUD, which generally isn't a very interesting problem.
Instead, I recommend thinking about doing something useful -- a use case where there are business rules to enforce, when the business model gets to say "no, the business won't let you do that right now".
Ask yourself these questions:
How many universities will be in your system? If this is only one, it is not your aggregate root.
If you have multiple universities in your system, would be someone working across universities? May be universities are your system tenants?
What happens with a class if some department is dissolved? Will it immediately disappear? I doubt it.
The same as above with university to department relationship
It is not a problem with a Department to hold reference to its classes as a list of value objects that will contain the Class aggregate root id and the class name. The same is valid for departments dealing with their classes.
Vernon's Effective Aggregate Design might help too.
I'm not very experienced in DDD either but here some tips I use to use:
Is it possible to have a Class without a Department assigned? If that is the case then the Department is the aggregate root and Class is another aggregate with a reference to the root, the Department. You can even define a factory method "addClass()" within your Department with the info that a Class needs to be created, so nobody should be allowed to create a Class without a Department.
Why defining a Class a an Aggregate instead of a Value Object? Because Value Objects are distinguished by their properties' value rather than an ID. I would say that even having two Classes with the same name, same students, same info, etc, etc. the business would still want to differentiate each one. It is not the same with a 1 cent coin which with you only care about the value (given by the color, size, weight,...) but you can always replace it with another one with same attributes' value, that is 1 cent. Also assigning another Professor to the class, the class remains the same, it is not immutable as a Value Object should be.
I guess a Professor must be uniquely identified, and he can maybe be assigned to different Classes or even Departments. So to me it is another Aggregate root separated from the department.
I've read countless posts on differences between Entities and Value objects and while I do think that at least conceptually I understand how the two differ, it appears that in some of these posts authors consider a particular domain concept to be a VO simply because it is immutable ( thus its state will never change, at least within that particular domain model ).
Do you agree that if the state of an object will never change within particular domain model, then this object should never be an entity? Why?
thank you
Do you agree that if the state of an object will never change within
particular domain model, then this object should never be an entity?
Why?
I'd say 90+% of entities will change at some point in their lifetime. But some entities might be unchangeable because of their nature in the domain - a PrepaidPhoneCard, a TransferOrder in a banking system for instance.
Some also like to make their Entities immutable by default because it helps shaping a design that preserves invariants and makes domain operations explicit : http://www.jefclaes.be/2013/04/designing-entities-immutability-first.html
The object could be an entity if you need to identify it.
According to the DDD book, if an object has identity and lifecycle but will not change over time, you could also consider the object as an event.
In two words: yes, they can.
Eric Evans in his book tells about a "thread of continuity" inherent to entities. In layman terms, an entity can be POSTed by a front-end as JSON, get converted into a DTO by a framework, then into a domain object, then into a DTO again and then finally get stored in a database table. During all these transformations the entity will be easily distinguishable because it possesses one or more unique business ids.
With this in mind, aren't some forms of immutability a form of another thread of continuity? Imagine copy-on-write: all of the immutable object's copies are formally different objects representing it at different points of its lifetime. Yet, there is a unique id allowing us to say it's the same entity.
Now, let's talk about the "extreme" form of immutability: read-only objects. Can an entity be a read-only object? Sure, a good example is a credit card statement.
Summing up:
One entity can exist in many forms. In fact, you will almost always have multiple representations of your entity in a program without being aware about it.
A true requirement an entity is an existence of a unique business identity (not a surrogate id that is used for technical purposes) that makes it distinguishable from other entities.
Entities can be immutable, whether we talk about COW or read-only objects.
I have some big Entity. Entity has propertis "Id", "Status" and others.
I have Repository for this Entity.
I want to change status in one entity.
Should I get whole Entity, change property Status and use save method in Repository or should I use method ChangeStatus(id, newStatus) in Repository?
Probably you don't need a domain model. You could try a transaction script that directly use SQL to update the database.
You need a domain model if and only if you need to hire an expert to understand the business.
Otherwise, it's just expensive buzzwords driven development.
And btw, if you have big entity classes containing data that you don't need during most of operations, then you know that you haven't properly defined context boundaries.
The best definition of bounded context is the one of Evans:
The delimited applicability of a particular model. BOUNDING CONTEXTS gives team members a clear and shared understanding of what has to be consistent and what can develop independently.
That is: you have to split the domain expert knowledge in contexts where each term has an unambiguous meaning and a restricted set of responsibility. If you do so, you'll obtain small types and modules with high cohesion an
I need to clarify something.
Have Person Aggreagate , 2 VOs (Country, StateProvince).
I want to load all country in my presentation layer (i am using mvc)
Evan says you only use repository (IPersonRepository) to work with root entity (it should always return just a reference to the Aggregate Root)
public interface IPersonRepository()
{
void savePerson(Person p);
void removePerson(Person p);
Ilist<Person> getPerson();
}
what i usually do to solve this :
Add in IPersonRepository this method
IList<Country> LookupCountrysOfPerson();
In Infra layer implement the Domain interfaces like this:
public IList<Person> LookupCountrysOfPerson()
{
return Session.CreateQuery("from Countrys").List<Person>());
}
My partner says im wrong.
Sometimes you have to sacrifice your domain model in order to accomplish some task
What is the best way to do this?
with code please! :)
I would say it's unlikely that you need country to be an entity. I suspect that country is nothing more than reference data, much like a person's title would be. Is there any behavior associated to country in your domain? I suspect it's just what's printed onto letters/envelops.
This question is somewhat similar to this one which I answered a while back:
Simple aggregate root and repository question
My suggestion is that you implement a Lookup service that your client can make use of and which is cached. Ignore the rules of DDD and anything to do with aggregates or repositories for this. As someone else has mentioned, this is where CQRS's ideology comes into play; the client shouldn't have to go through the domain in order to get data. The domain is purely transactional, not designed for queries.
This article explains how to build a generic lookup service for reference data for things that typically fill dropdowns in the UI (i.e. Title, Country etc)
http://wtfperminute.blogspot.com/2011/02/working-with-reference-data-lookups.html
Evans also says (pg 170) "An entity as basic as Location may be used by many objects for many reasons..."
I would also consider making Country an entity for the reasons given above. Perhaps more importantly, it is a low level object. You probably are also even supplying Country by configuration rather than through any actual domain activities. Therefore I would remove it from the Person and make it a standalone entity.
Also for this type of object you may not really need a dedicated repository, consider creating a single lookup service that provides query access for a group of similar objects of this nature.
If in your domain country is actually a VO (you don't want to maintain a thread of identity in the country name was changed etc.) which is the most common scenario, I would add a specialized class in the data access layer to return a list of all countries as VOs. I would also add caching (2nd level cache in NHibernate) to the country entity and list all countries query so that I don't have to hit the DB each time.
Actually, this is where CQRS really shines. CQRS acknowledges that you don't have to go through the domain layer in order to get some data for presentation purposes. In CQRS you just grab some data.
It sounds like countries are not in fact value objects here; they have distinct identities and are important for business purposes outside of your Person objects. They should become entities, and be treated in the fashion appropriate to them.
Think of it this way: let's say some volatile country had their current dictator overthrown and got a name change. The Person object's reference to a Country should still be valid, because the Country is not defined by its attributes (i.e. the string denoting its name), but by its identity.