Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to model entities that exists in all bounded contexts and that are a central part of the app?

I'm making an application using DDD principles. After thinking everything through as much as I can I'm down to start making my Bounded Contexts. I haven't set the final structure yet, but as of now my application will consist of the following bounded contexts:

  1. Employee managment
  2. Purchasing
  3. Archive
  4. Reporting

I want this to be as pluggable as possible, so I can for example develop and maintain them seperately. Probably they will expose either WCF or Web API to interact with them.

I will use Udi Dahans implementation of a simple CQRS pattern. I'd prefer not to go all the way with event sourcing, message busses and so on because this wil not be a highly collaborative app (less than 1000 users, and they are not likely to edit the same small dataset), and this would add a lot of unneeded complexity.

So to the questions:

The employee and department entities are common for all BC, how to model that?

Department is a part of the organizational structure, so in the employee managment BC the employees work in a department, they can manage an department and they have a history of departments they've worked on.

In the purchasing BC goods are purchased from a department, and delivered to a department. Suplliers have different contracts with different departments.

In archive some information will be archived and tied to a department, and so on.

The same pretty much applies to Employees.

How to persist the data from the bounded contexts?

They can be mapped to the same database or each have their own.

Some thoughts I've made so far

How to model
Should I make one more BC called "Company" or "Organization" and manage departments there?

Acoording to Udi Dahans article referenced above, I should make a department entity and a employee entity for each BC with just the fields and behavior I need for that BC. This sounds reasonable but then I'm thinking of how to actually use this and I can't figure that out. I need to access the departments managed somwhere else, but how exactly do i do this and not mix my BC's?

How to use?
Let's say that I get my list of departments from somwhere by querying. In the UI i get a list of departments that I want to make a purchase too. This is the first purchase for this department so the Purchasing BC does not know about this department yet... So the Department Object in Purchasing BC will be filled with data maintained from anoher BC - so how do I persist this? I would need to add some information like delivery address, and invoice address if that doesn't exist?

In the "register department UI" should I then call "RegisterDepartment" service on all BC and then make shure that these are in sync with all changes made through the UI (MVC controller)?

The same with employees. I want to know which employee made a purchase or put something in the archive. So somehow I would need an employee-object in these BC's too but manage them from a different BC.

Persisting
Some of the challanges above could be solved by mapping the different employee-objects to the same table in a database. Purchasing BC and Archive BC cannot register new employees, but append information to those who are there and tie them to other objects in the same database. Then the database would make shure that all the BC's still live in the same world...

I need advice so I don't end up making something that will be very hard to maintain later on.

like image 569
cfs Avatar asked Nov 23 '12 13:11

cfs


People also ask

What is a way to handle relationships between bounded contexts?

Relationships between bounded contexts pose the problem of how the development of one context influences the other over time. The safest way of dealing with related contexts is by creating an anticorruption layer (ACL).

What is bounded context model?

A bounded context is simply the boundary within a domain where a particular domain model applies. Looking at the previous diagram, we can group functionality according to whether various functions will share a single domain model. Bounded contexts are not necessarily isolated from one another.

How do you identify bounded contexts?

To identify bounded contexts, you can use a DDD pattern called the Context Mapping pattern. With Context Mapping, you identify the various contexts in the application and their boundaries. It's common to have a different context and boundary for each small subsystem, for instance.


1 Answers

It seems that most of your doubts circle around: "How are single real-life objects shared by different Bounded Contexts?"

The thing is, though the entities are the same, they are treated differently by every BC. In Employee Management BC, the whole weight is centred on Employee and Department entities - you should be able to add them, modify, assign to each other, keep history and take care of all business logic regarding management. You could implement some policies of keeping employees personal data, maintaining proper official structure or maintaining certain responsibilities.

On the other hand, the department entity in the Purchase context would mean only, for example, invoice address and maybe person from the department responsible, and the centre of interest would be constructing the order. All data that is not directly connected to the procedure of making the purchase should be given to a different context. If, for example, the domain requires that every order has to be connected to the department and the invoice details are missing, purchase context should not try to fill them by itself. Instead, a notification to Employee Management could be made to fill the missing parts.

Note that it may very well happen in the same application or even the same window. But you must ensure it will happen through Employee Management context, i.e by invoking context public API.

As a side note, I do not know your domain, but you may want to reconsider your context boundaries, for example by separating deliveries from purchase.

Moving on to usage and following your example, if you want to make a purchase, I would consider following path:

  • Read necessary department data (let's wait till later with "how"), you may want to check if every data are present at this point
  • Read goods that can be purchased, depending on your domain it might be worth to introduce another BC, such as Suppliers. These all above are the "Query" part of CQRS
  • Construct order or any other necessary purchase context entity, perform validation or any other logic
  • Commit changes, persist purchase context entities (the "Command" part)
  • Create and publish some domain events (for example to notify Archive or Reports)

Last but not least, you should not be concerned with global persistence in the domain layer. Every BC should be connected to some Data Access or Infrastructure layer supplying necessary objects and taking care of such details as from where to take them.

Especially, entities do not necessarily need to mirror database layout, and the question whether to store in one or multiple databases should be only a performance issue. For example, some entities will refer to the same object (for example employee Name), but can take other details from totally different tables or db (i.e. purchase history or elements sent to archive). You may use something like NHibernate to make this easily manageable.

like image 88
Jeremy Avatar answered Oct 02 '22 14:10

Jeremy