Search code examples
c#data-access-layerdomain-model

Who should create business objects?


Since business/domain objects should be unaware of their persistence they obviously must not contain code that loads data from a database to initialize themselves.

On the other hand not all of the properties of business object have public setters to aid encapsulation and to avoid setting them to invalid values.

That means that no other class can fully initialize a business object, when it its data is fetched from a database.

Since all of the above are common best practices, there has to be some solution to that problem. So who should be responsible of constructing business objects and filling them with data from the database?

Note: The only option that comes to my mind is adding all the properties to the constructor, which would be highly impractical in my opinion.


Solution

  • There are quite few solutions to this problem. But neither of are "perfect".

    1. Use reflection to set private fields or properties. Most ORMs use this solution. The problem might be when ORM sets property, that has some logic on it, leading to illogical state of the entity (I got burned by this quite a few times).
    2. Abstract away "data persistence" as key/value map. This way, the entity can persist itself and is still independent of specific persistence technology. But you still need to explicitly code this.
    3. Builder pattern. Have separate class with same properties, that can access the private fields of the entity, but is only used in construction. Major disadvantage is need to have builder for each entity.
    4. Create a DTO, that mirrors the state of the entity, but not it's behavior. The entity can then read/create this DTO to load or persist itself. Same disadvantage as above.

    I personally don't see any good answer to your question, unless you can manage to do one of the previous solutions automatically. Either by code generation or by having language support. For example, having language support for "builder pattern" would help a lot.