Question

I hope you can help settle a slight disagreement I am having with a colleague.

I always assumed it was a principle of object-oriented design that objects should protect their internal state and only expose publicly what the outside world needs to access or change. In the context of a rich domain model, this means that domain objects should enforce the validity of the model they represent, and that they should not allow their state to be made invalid by external callers, even if they are core domain objects and not directly exposed to the outside world.

Take as an example an object of type Thing, which has a collection of properties. My colleague has proposed the following.

public class Thing 
{
    public List<ThingProperty> Properties { get; set; }
}

I dislike this, because it allows external callers to set the Properties reference to null. His defence is that without this mutable reference, it is difficult to load data into the model from data access, or to map from the presentation layer to the core model.

My solution is as follows...

public class Thing
{
    private readonly List<ThingProperty> properties;
    public Thing() { properties = new List<ThingProperty>(); }
    public ReadOnlyCollection<ThingProperty> { get { return properties.AsReadOnly(); } }

    public void AddProperty(ThingProperty add) { (validate) properties.Add(add); }
}

This means that any validation that may be required when adding properties to a Thing can be validated inside the model (say if only 1 instance of a given property type may be added) and the model always ensures a valid state. The downside is that it's difficult to map from data access or the presentation model into this form, but I think that's a price worth paying.

Any thoughts? Thanks.

Was it helpful?

Solution

You've got it right, and this is what DDD invariants are all about. By making entities enforce their own integrity (or an Aggregate root enforce invariants for its aggregate), you ensure that your domain objects are always valid.

The argument of "loading data into the model" is a strange one since there's little value IMO in loading an invalid entity - a "cyclops with 2 eyes" or a Thing with null Properties in your example.

Sure, if your properties are readonly, you won't have access to an inline object initializer but there are other convenient ways of instantiating an entity (that is, a valid one) in one go : constructors, Factories, custom Builder pattern, etc. Besides, if you're talking about rehydrating domain objects from a persistent data store, most ORM's have the ability to manipulate private or protected fields so there's nothing to worry about.

Also note that functional programming techniques might make this easier to implement : immutability by default, non-nullable types...

OTHER TIPS

The downside is that it's difficult to map from data access or the presentation model into this form

But you have some options that simplifies mapping from data access to domain entity:

There is more detailed answer on How to retrieve Domain Object from Repositories

Your implementation of Properties collection is close to best practices for read-only lists implementation when domain objects enforce the validity of the model they represent.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top