Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Domain Driven Design: Handling complex entities with many states and relations (Real Estate)

So I'm fairly new to DDD and am trying to build a scalable and flexible system for my current employer (Real Estate Agency) that will help us speed up internal company procedures.

As stated, we're in Real Estate. I'm trying to define our UL and am having problems conceptualising certain complex entities.

For example: in Real Estate, a 'Property Consultant' will visit a potential 'Client's home and provide an 'Appraisal' on their 'Property'. When listed, this 'Appraisal' becomes a 'Listing' which can also become a 'Sold Property' or a 'Withdrawn Property'. There are so many different states in which a 'Property' can be. Should I be defining a 'Property' as an entity or should each separate state (Appraisal, Listing, Sold, Withdrawn) be defined as a separate entity?

The problem gets more complex though, when we add 'Clients' into the mix. A client can be a 'Property Owner', 'Purchaser', 'Buyer', 'Tennant', 'Investor', 'Developer' and many, many more. On top of that, a client can be a combination of more than one of these! Again, should 'Client' be the entity and all these states be represented just as properties of the 'Client' entity or should they be separate entities?

On top of that, what about the relationship of 'Client' entities to 'Property' entities. Its a many-to-many relationship and I see no easy way of combining it. DDD seems to state that an entity should be unique in its existence, therefore meaning that I can't have a 'Property' entity with a list of attached 'Client' entities without making my 'Client' entity behave like a VO. Vice versa when considering 'Client' entities with a list of their associated 'Property' entities.

I've been reading for 8 hours a day for the last 2 weeks on this subject. Its very confusing and I'm yet to untangle the mess. Any help and pointers in the right direction would be greatly appreciated!

like image 364
Socceroos Avatar asked Nov 29 '10 00:11

Socceroos


3 Answers

I don't do PHP, but I can suggest how to model your classes:


Clients and Roles

  1. Create an interface (or abstract class) called Role. Role has a reference back to a Client

  2. Inherit the following classes from Role: Owner, Purchaser, Buyer, Tennant, Investor

  3. For each of these concrete Role classes, extend the members as necessary (e.g. a Tennant may have MonthlyRent)

  4. Add a list of Roles to your Client. Whenever a new Role is added to Client.Roles, the Role should reference the Client

The important part: Most of your classes should reference the individual Role object, instead of the Client. You can access the Client via the Role.


Property states and transitions

  1. Create an interface (or abstract class) called PropertyEvent. Add a timestamp property to it called OccurredAt.

  2. Inherit the following classes from PropertyEvent: Appraisal, Listing, Sold, Withdrawn

  3. For each of these concrete PropertyEvent classes, extend the members as necessary (e.g. an Appraisal will have an associated AppraisedBy?)

  4. Add a list of PropertyEvents to your Property. Whenever the state changes, create the appropriate Event and add it to Propery.History.

The important part: This is the notion of a Domain Event. This technique will automatically provide a history of the state changes for the Property.


Note that I haven't focused on entities, or Aggregates, or Value Objects. You can work those out as you get a better feel for your model.

Hope that helps!

like image 121
Vijay Patel Avatar answered Nov 07 '22 14:11

Vijay Patel


First of all don't make yourself too crazy. One of the reasons object oriented programming is generally considered a good idea is you can try something and then refactor as your understanding of the problem domain increases.

For the entities you've identified that have various "states" study the State Design Pattern - with the wrinkle in your situation that an entity can have more than one State. Determine what entities are Aggregate Roots - sounds like Property and Client - and due to the complex relationship treat each in a separate Bounded Context. Then I think your instinct is correct, pass the outsider as a Value Object into the Bounded Context of the other to get results out (most likely through a Service Object).

like image 23
orangepips Avatar answered Nov 07 '22 14:11

orangepips


For the Clients, consider giving them roles. The roles can be separate entities and a Client entity can have many of these roles.

like image 1
Dave Avatar answered Nov 07 '22 16:11

Dave