Search code examples
c#wpfdomain-driven-designpresentationbusiness-logic-layer

How to keep correspondence between Domain and Presentation objects


I have a question about keeping track of objects in different layers of a software application. In my application, I have objects in the domain layer (e.g. LineShape) that are used to represent business entities, and I have corresponding objects in the presentation layer (e.g. System.Windows.Shapes.Line) that are used to display these entities on the screen.

My question is, how do I keep the correspondence between the domain objects and the presentation objects, so that I can identify which domain object is represented by a given presentation object?

For example, if the user clicks on a System.Windows.Shapes.Line in the user interface, how can I determine which LineShape in the domain layer this object represents?

I have thought of a few potential solutions, but none of them seem ideal, especially for larger and more complex object models.

  1. One solution is to use a dictionary that maps presentation objects to domain objects. In this case, when the user clicks on a System.Windows.Shapes.Line, I could look up the corresponding LineShape in the dictionary.
  2. Another solution is to use an ID for both the presentation and domain objects. This approach has the advantage of being simple, but it seems strange to me to use IDs for every object in a domain-driven design, as IDs are typically used only for entities.

Are there any best practices or established patterns for solving this problem?

enter image description here


Solution

  • Use an Id for objects both in Presentations and Domain. This sounds a bit strange to me, because as far as I am aware, we are not supposed to use Id for every object in DDD, just for entities.

    Perhaps you would be looking at an address rather than an ID. Even values must somehow be addressed so they can be replaced. Such an address may be a class property's name, an array's index, etc.

    If you see the whole drawing as a collection of shape values then you could always use the shape's index as the address allowing to replace that specific shape value in the collection.

    However, note that the address is only valid as long as you are working against the expected drawing's version.

    Furthermore, you could also use the combination of all shape's properties to identify a given shape to modify. If you have two identical shapes (same shape, position, layer, etc.), does it matter which one you re-shape? The final drawing would look exactly the same.

    In the end if it makes your life easier to model shapes as entities and given them an ID then perhaps that's the right model too even though you may not care about the specific shape's entire lifecycle.

    Finally, note that if shapes are values then you can't possibly keep a reference to them in view models since values are immutable. Also, if shapes are entities, but the drawing is the Aggregate Root then shape entities shouldn't be accessible outside the root. Therefore it most likely only makes sense to reference a domain's Shape in the view model if it's an AR (unless you violate the visibility rule, but still enforce invariants through root-handled events). Also note that address/ID references may be the only option if your domain model lives on another tier.