1

We are porting an old monolith application and we are trying to apply the DDD concepts, we started looking for what we think are the Bounding Contexts of the application.

We have what we thought would be a bounding context which is what we call Location, it has a country, which has a collection of provinces where each province has a collection of cities.

The Locations are used in many parts of the application and can be added, updated and removed.

So what I thought was that we would have the Country entity as an aggregate root with Province and City as a simple entity.

The problem is what my coworker told me, in the old monolith application if you wanted to remove a location, you will only select the location and deleted, but with my approach we will have to get the Country Entity with the provinces and the cities just to delete a city an this approach will be way slower.

He says that each one should be an Aggregate and if there is a case where we delete a Country it should generate a domain event of country deleted, so we can handle the event and delete all the provinces associated and the same with the relation between provinces and cities.

So my question is which approach is the best?

We aren't really knowledgeable in DDD so it might be all wrong.

Thanks!

4 Answers 4

1

Assuming that you have these entities in the first place the choice of Aggregate is decided by what sets of data the functions you expose need to work.

So for example, if Order.Cost is calculated by the sum of Items.Price then they are in the same aggregate.

If you have something like country.GDP = sum(province.GDP) then you have your answer.

If you have a looser coupling like provice.ParentCountry then you can choose to have province.ParentCountryId instead and put them in separate aggregates with the danger of getting orphaned provinces.

This is fine as long as the Province doesn't have any direct dependency on the Country or vice versa

1
  • The reality is that they do not have functions that depend on each other, apart of the deletion, so probably the best case will be to have separate aggregates.
    – mmas
    Apr 7 at 12:18
2

He says that each one should be an Aggregate and if there is a case where we delete a Country it should generate a domain event of country deleted, so we can handle the event and delete all the provinces associated and the same with the relation between provinces and cities.

Did the split of Czechslovakia cause Prague to cease to exist?

There's two problems here:

  • "to get the Country Entity with the provinces and the cities just to delete a city an this approach will be way slower" is a performance consideration, which should not be allowed to drive domain considerations if you're really doing DDD. There are often ways to work around this in practice once you've got the data model sorted, such as database indexes.

  • Everyone likes to have hard constraints and strict aggregate roots, but real objects don't necessarily conform to simplifications.

3
  • "Did the split of Czechoslovakia cause Prague to cease to exist?" This statement does in fact make a lot of sense, it's true that the provinces or countries will not stop existing if a country is deleted, so it makes sense to make it as separate aggregates, but if even if they still exists our business rule says they should be deleted.
    – mmas
    Apr 7 at 12:36
  • 1
    I should have explained that more: I was questioning whether a Location should really be deleted when its country is deleted, or whether in the rare circumstances of deleting a country there should be rules that migrate the locations to a different country first.
    – pjc50
    Apr 7 at 12:40
  • You are right, if a country is ever deleted what we should do is check if it have provinces related to them and don't allow to delete it if it does. But in this case i think we should still have to check in some way that the country does have provinces?
    – mmas
    Apr 7 at 14:24
2

The Locations are used in many parts of the application and can be added, updated and removed.

Your locations sound to me like "reference data"; your business probably doesn't derive a lot of competitive advantage from the sophisticated policies you have when adding and updating location information?

For example: Eric Evans uses a "Cargo Shipping" domain as one of his original examples of domain modeling. In that domain, you care a lot about ports of entry - so you are likely to be using UN/LOCODE data when describing the legs of a shipping itinerary.

UNECE publishes "editions" of the UN/LOCODE code list once or twice a year.

What you are probably going to do, as a business, is copy information from the latest edition into your database for use. But there's not a lot of "logic" to it, no more than there is logic to "days of the week" or "bank holidays".

Therefore: AGGREGATES, as a pattern, are probably overkill; you don't need state machines with business policy logic, and all the ceremony that comes with that.

If you look at ddsample-core (a project put together by Eric Evans and Citerus), you'll see that they didn't follow the usual AGGREGATE pattern for Locations. There's a repository... but the repository doesn't support a store method. Locations are ENTITIES, but don't actually include any methods that modify the entity.


On the other hand, if you were creating a domain model for UNECE (to help them with the processes of maintaining and publishing the code list), then it is your data, and you are going to care about the lifecycle of UN/LOCODE identifiers, and the policies you need to enforce about when identifiers can be recycled with new semantics, and so on.

In that case, having a Location AGGREGATE (and the related ceremony) would make more sense.

A big difference here is that we are managing the authoritative copy of the information, where as in the Cargo Shipping example we're just maintaining a local cache of information published by an authority. Context matters, and the patterns that make sense in one context don't necessarily make sense in all contexts.

Horses for courses.

1

So my question is which approach is the best?

You mention Locations are used in many placed, but what are they used for?

If you want to follow the rules for aggregate roots and sub-entities correctly, then your design has the consequence that you cannot refer to a City without also specifying the Country aggregate that the City belongs to. Sub-entities of an aggregate do not have their own globally-unique identification.

It can be that this consequence is entirely fine for how your system deals with Locations.

On the other hand, if your current system typically refers to Cities directly and the Country (and Province) information is only used when needed for disambiguation in the user interface, then the design proposed by your colleague would be much better.

4
  • Yes, it's exactly like that, we use the others as disambiguation, but it's still difficult for me to understand how if a country should know which provinces has to delete them before deleting the country, then why are they not the same aggregate?
    – mmas
    Apr 7 at 12:25
  • 1
    @mmas, let me challenge you a bit more. Why are you modelling Country as an entity and not as a value object? How big of a problem would it be if you have the cities "Los Angeles, Unites States" and "Washington, DC, USA"? Apr 7 at 12:47
  • 1
    @mmas, is there actually a use case for deleting Counties that still have provinces and/or cities under them? Apr 7 at 12:48
  • I can't see why it should be a value object since they do have an identity, but that might be my poor understanding of DDD. Also you are right that there is no use case to delete the country if it still haves provinces or cities.
    – mmas
    Apr 7 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.