The right way to implement associations in DDD? - oop

We are trying to adopt Domain-Driven Design in our project for the first time. The problem I have is with associations between entities. How do you do them right?
Say, I've got entities Employee and Contract, a simple one-to-many association. How do I model it?
Option 1: Aggregate.
Problem: The problem here is that, if I understand it correctly, all entities in an aggregate must be loaded when an aggregate object is created. I can't lazy-load entities when they are needed because it would require referencing a repository from an entity, which apparently is bad. But fetching all of an employee's contracts from the database every time would be a big performance issue.
Option 2: Fetching an employee's contracts by using a repository (e.g. ContractRepository.GetContractsForEmployee()) and adding EmployeeId property to Contract class.
Problem: it makes hard to put any business logic into entities. I would like to have a method, say, Employee.Dismiss(), but it would also need to update the employee's contract. This means I would need to put this logic in a service. The problem is, I can't think of much logic operating only on an Employee and thus the model would become somewhat anemic, with most logic inside services.
How do you deal with these issues in DDD?

This is just my take on it... without knowing your domain.
First, here is a good resource to read (part about Aggregates and Roots).
In DDD terminology, Employee and Contract are both entities (because they both have an identity).
"Aggregates draw a boundary around one or more Entities. and also: Each Aggregate has a Root Entity, which is the only member of the Aggregate that any object outside the Aggregate is allowed to hold a reference to."
The question is: do Employee and Contract form an aggregate, with Employee being the root entity? Obviously not, because other domain entities could also have a reference to a contract, and the contract id's are globally unique, not only within a Customer.
So, taking into account these rules, Employee and Contract are both aggregate roots.
Then: "Only aggregate roots can be obtained directly with queries; so this means that we should have a repository per aggregate root."
So in this case, we have an EmployeeRepository and a ContractRepository.
Taking all of this into account, I would not add a relation between employees and contracts in the domain model; but treat them separately. After all, if you need an Employee, you don't necessarily need his contracts too, they are both different aspects.
Option 2 is what I would choose: use the ContractRepository to get the contracts you are interested in. And if needed you could add a domain service that is responsible for aggregating employees and contracts if needed.
If you also define a Company entity, then dismissing an employee could be the job of that entity.

We recently got into the DDD approach as well. If I were to do it, I would have the following (attributes are simplified for brevity):
public class Employee() {
String name;
Set<ContractNumber> contracts;
public void addContract(ContractNumber contractNumber) {
this.contracts.add(contractNumber);
}
}
public class Contract() {
ContractNumber contractNumber;
Date effectiveDate;
}
public class ContractNumber() {
String contractNumber;
}
ContractNumber is a Value Object that is referred to from within Employee. In this example, Employee is within a BoundedContext that deals with Employees and their respective contracts. There may be other representations of Employee in other bounded contexts.
As discussed in other answers, there will be repositories for both Employee and Contract.

You need to find your true invariants.
Here you could have an invariant such as: you cannot dismiss an Employee that has already been dismissed.
If this is the only real invariant, then you could make one Employee aggregate, which would only have the IDs of the associated contracts.
Contract would be another aggregate (if needed).
If the dismiss() method succeeds, you could load the needed contracts and make the necessary changes.

Related

Repository Pattern Dilemma: Redundant Queries vs. Database Round Trips

This is the situation:
Say I have an application in which two entity types exist:
Company
Person
Moreover, Person has a reference to Company via Person.employer, which denotes the company a person is employed at.
In my application I am using repositories to separate the database operations from my business-model related services: I have a PersonRepository.findOne(id) method to retrieve a Person entity and a CompanyRepository.findOne(id) method to retrieve a Company. So far so good.
This is the dilemma:
Now if I make a call to PersonRepository.findOne(id) to fetch a Person entity, I also need to have a fully resolved Company included inline via the Person.employer property – and this is where I am facing the dilemma of having two implementation options that are both suboptimal:
Option A) Redundant queries throughout my repositories but less database round trips:
Within the PersonRepository I can build a query which selects the user and also selects the company in a single query – however, the select expression for the company is difficult and includes some joins in order to assemble the company correctly. The CompanyRepository already contains this logic to select the company and rewriting it in the UserRepository is redundant. Hence, ideally I only want the CompanyRepository to take care of the company selection logic in order to avoid having to code the same query expression redundantly in two repositories.
Option B): Separation of concerns without query-code redundancy but at the price of additional db roundtrips and repo-dependencies:
Within the PersonRepository I could reference the CompanyRepository to take care of fetching the Company object and then I would add this entity to the Person.employer property in the PersonRepository. This way, I kept the logic to query the company encapsulated inside the CompanyRepository by which a clean separation of concerns is achieved. The downside of this is that I make additional round trips to the database as two separate queries are executed by two repositories.
So generally speaking, what is the preferred way to deal with this dilemma?
Also, what is the preferred way to handle this situation in ASP.NET Core and EF Core?
Edit: To avoid opinion based answers I want to stress: I am not looking for a pros and cons of the two options presented above but rather striving for a solution that integrates the good parts of both options – because maybe I am just on the wrong track here with my two listed options. I am also fine with an answer that explains why there is no such integrative solution, so I can sleep better and move on.
In order to retrieve a company by ID you need to read Person's data, and fetch company ID from it. Hence if you would like to keep company-querying logic in a single place, you would end up with two round-trips - one to get company ID (along with whatever other attributes a Person has) and one more to get the company itself.
You could reuse the code that makes a company from DbDataReader, but the person+company query would presumably require joining to "forward" person's companyId to the Company query, so the text of these queries would have to be different.
You could have it both ways (one roundtrip, no repeated queries) if you move querying logic into stored procedures. This way your person_sp would execute company_sp, and return you all the relevant data. If necessary, your C# code would be able to harvest multi-part result set using reader.NextResult(). Now the "hand-off" of the company ID would happen on RDBMS side, eliminating the second round-trip. However, this approach would require maintaining stored procedures on RDBMS side, effectively shipping some repository logic out of your C# code base.

When to create a new table?

I have an application with employees and their work contracts.
Each work contract has a Vacation. We keep track of how many days the company owes the employee ("VacationOwe") and how many he has taken ("VacationTaken").
Should I make this "VacationOwe" and "VacationTaken" a property of the Contract, or should I create a class (table) called Vacaction with the properties "VacationOwe", "VacationTaken" and "ContractId" and join the two tables?
What are the advantange of both methods?
Is there any rule when you should create a new class or table or keep the data in one.
If the two properties are truly only related to an employee, there's no benefit of creating a separate table. Performance will be worse and you'll constantly have to join on those tables.
For this specific example, it seems like the vacation days may also be linked to a year. If that's the case, a separate table would make sense so you can track vacation days taken/owed by employee and year.
should I make this "VacationOwe" and "VacationTaken" a propertie o the employee
Most probably...No. Because this defeats normalization. Also, it does not provide information about when the vacations were taken (in case you care about that). In addition to that, you have to do this calculation for every employee, every year.
Use a class (table) Call Vacaction with properties "VacationOwe" and "VacationTaken" and "EmployeeId" and cross the two tables?
It is not good to have a singleton class in this case. In general you should avoid singletons in most cases.
So what to do? Well, if you system does not care about vacation details, you could go with the first solution. Maybe you want to consider option (A) below or If you would like to have a more generic approach you could do something similar to option (B). It all depends on your detailed requirements.

Is it acceptable to have multiple aggregation that can theoretically be inconsistent?

I have a question about the modelling of classes and the underlying database design.
Simply put, the situation is as follows: at the moment we have Positions and Accounts objects and tables and the relationship between them is that a Position 'has an' Account (an Account can have multiple Positions). This is simple aggregation and is handled in the DB by the Position table holding an Account ID as a foreign key.
We now need to extend this 'downwards' with Trades and Portfolios. One or more Trades make up a Position (but a Trade is not a Position in itself) and one or more Portfolios make up an Account (but a Portfolio is not an Account in itself). Trades are associated with Portfolios just like Positions are associated with Accounts ('has a'). Note that it is still possible to have a Position without Trades and an Account without Portfolios (i.e. it is not mandatory to have all the existing objects broken down in subcomponents).
My first idea was to go simply for the following (the first two classes already exist):
class Account;
class Position {
Account account;
}
class Portfolio {
Account account;
}
class Trade {
Position position;
Portfolio portfolio;
}
I think the (potential) problem is clear: starting from Trade, you might end up in different Accounts depending if you take the Position route or the Portfolio route. Of course this is never supposed to happen and the code that creates and stores the objects should never be able create such an inconsistency. I wonder though whether the fact that it is theoretically possible to have an inconsistent database implies a flawed design?
Looking forward to your feedback.
The design is not flawed just because there are two ways to get from class A to class D, one way over B and one over C. Such "squares" will appear often in OOP class models, sometimes not so obvious, especially if more classes lie in the paths. But as Dan mentioned, always the business semantics determine if such a square must commute or not (in the mathematic sense).
Personally I draw a = sign inside such a square in the UML diagram to indicate that it must commute. Also I note the precise formula in an UML comment, in my example it would be
For every object a of class A: a.B.D = a.C.D
If such a predicate holds, then you have basically two options:
Trust all programmers to not break the rule in any code, since it is very well documented
Implement some error handling (like Dan and algirdas mentioned) or, if you don't want to have such code in your model, create a Checker controller, which checks all conditions in a given model instance.

Member "Is-A" Person or Person "Has-A" Enrollment

I am trynig to create a set of Models for our Enterprise App. It has never had them being tied very tightly to the Databases. At this point I am trynig to simply answer the "Is-A" or "Has-A" questions. I am basing this off the DB structure but I do not want to, neccesarily, be tied to that.
For starters I have the, very, obvious Person model with the typical "Has-A" Phone and Address. Almost everything works off of that Person model and is a "Has-A".
However, we have Members. In our DB/Current System a Member is a Person who has an Enrollment. To be specific an Enrollment of a certain type that is Dis-Enrolled(by Date).
On one hand I feel that Member would Inherit form Person as a "Is-A" relationship. However I am very new to this type of thing and I wonder if I am over thinking it. Does my Person "Has-A" Enrollment or does that imply something else?
It makes me wonder, if I do have a Member should I have different "Is-A" models for Pre-Enrollments, Enrollments, Former Enrollments? It seems that is more a question of State but again, I am new at this. If it is a question of state am I back to just having a Person model that "Has-A" Enrollment?
I understand this is, somewhat, opinion based and I welcome each persons opinion on this.
It makes more sense that Person be higher up in the heirarchy. From the group of all People, you have some members, some ex-members, and some members-to-be.
If you try to look at it the other way and say From the group of all Members, all are people...but some are Dis-Enrolled? It makes less sense that way since if they are Dis-Enrolled, then they are no longer members.
Unless being a Member and Enrollment are not connected (ie. if you can be dis-enrolled and still be a member).
Well, I'll try to answer you question though I don't fully understand what is "Enrollment" (I'm not native english speaker) I guess it some kind of Membership.
Suppose you will decide to use IS-A relationship, so you would end up with:
Member:Person, VIPMember:Member, ExMember:Member, etc. What would you do if you Person object changes to Member or anything else? You will have to convert you object to this type, create a Member object copy values from Person object... thats lots of boilerplate work.
If Object changes it Type after it's creation better use some property to distinguish it's type. Cosider Apple : Fruit (Apple is always Fruit, it can't become Tomato), and CanceledOrder : Order (Order can become CancledOrder so I would prefer Order.State). This is especially true for languages when once the object is created you can't change it's type (like C#).
As for your case from what I understood I would create:
public class Person
{
public IEnumerable<Membership> Memberships {get;}
public bool IsMember
{
get
{
return Memberships.Any();
//Or what ever logic you imply
}
}
}

In which class "should" the responsiblity lie in fetching the data from the Data access layer (RDD)

Lets say I have a class representing a course.The course has its own attributes like subject name, descriprion, start- and an ending date and so on.
Then, the course has attributes like a list of participants. In the database this is obviously represented in two classes; the course and a participant table in a one-to-may relationship.
My question is about how to set the list of participant in the course class: Should it be the course class itself that is fetching the data (through a data access layer, or a layer above), or should one delegate the fetching and the setting of the participants to some kind of helper class, making the course class it's self more or less a dumb object, only holding data?
In RDD(Resopnsible driven design) it tells us to make smart object and abstract away the differentce between data and behaviours. In this regards it sounds obvious that the course class should handle the fetching of the participants. Doing this howerver, is creating a direct dependence on a data access object (or a level above), making it more couple up.
Any thought on this would be helpful.
Should it be the course class itself that is fetching the data
This is a pattern known as Active Record. Be aware that many feel that active record is an anti-pattern.
or should one delegate the fetching and the setting of the participants to some kind of helper class
This is a pattern known as Repository.
making the course class it's self more or less a dumb object, only holding data?
Removing the responsibility of saving and retrieving data from the entity doesn't make that entity a dumb object, only holding data. The entity can still hold domain logic, which is a common practice when practicing Domain-Driven Design. In DDD, entities as simple data containers without behavior are called anemic domain model.
The Course class shouldn't be responsible for fetching the participants, in fact, it shouldn't be responsible for fetching the Courses. You bring up the correct point of data access layers, but the course class itself should not work with this layer, it must just represent a course.
You create a class which has the responsibility of fetching the data, i.e the data access layer. You can name this something similar to CourseDao, but the important part is; that it simply gets the data from the database, and returns it to the client as Courses.
This class has methods like Create, Read, Update and Delete.
Now, you want to do the same for participants, with one small difference. Since your Participant table has a foreign key to Course, your ParticipantDao will have an overloaded Read.
Example:
public class ParticipantDao{
public void create(Participant participant){
//Insert participant in db
}
public Participant read(int id){
//read participant from db
}
public List<Participant> read(){
//read all participants from db
}
public List<Participant> read(Course course){
//read all participants in this course from the db
}
public void Update(Participant participant){
//update and so on.
}
}
And your CourseDao can use this ParticipantDao by going something like:
foreach(Course course in read()){
course.setParticipants(this.participantDao.read(course));
}
In short, you have an object to access the data in the database, which is not the same object that represents said data. When you have a One-To-Many relation, these access objects can work together to retrieve the correct data.