POCOs! = Domain objects?

When I was working on my first major project with ORM, I began to realize that ORM would be a big obstacle to creating domain objects that are expressive and convey intent.

That is, I understand that we do not want domain objects to be just bags of public getters and setters. In addition, I am starting to realize that just having IList <T> all over the place does not convey intentions and may suggest abuse to developers using these objects. For example, it might be better to have ReadOnlyCollection <T> exposed. (By the way, I use .NET and the Entity Framework.) And instead of IList <MyDomainObject>, I found that I want to show a list of objects from from MyDomainObject. (None of this is easy to do in EF. Maybe I need to use NHibernate or ADO.Net.)

My questions are: have I really gone too far trying to create domain objects this way? Should these problems be part of any other application component? Or should I have a "real" domain object (which has expressive material) and a "dumb" POCO object that is moistened with ORM?


(Editing: The system ate a bunch of my angle brackets.)

+6
design-patterns architecture orm domain-driven-design
source share
5 answers

My opinion is that you let EF do this and create freebox POCOs. You can also call them DTO - their role should be a bridge from memory to perseverance and vice versa. As for your "domain", I never bought the idea that your database schema reflects a consistent domain model. As a result, I always created a Domain layer on top of the Persistence layer (or repository), which is a business domain, preserving the sausage factory, which is the Persistence from the composition. This domain level can crush your DTOs as required to make a developer-centric model make sense. Use the factory template to create domain objects from the DTO and vice versa - keep the DTO outside the client code so that you can isolate schema changes from consumers.

It works more, more matching code, etc., but it's worth it - EF is already shortening your code, and I would say that you actually need time to code the logic and representation of the domain, this is what makes you better code generation tool :)

Good luck.

+2
source share

(None of this is easy to do in EF. Maybe I need to use NHibernate or ADO.Net.)

Bingo. EF does not support the same level of independence between your domain and persistence infrastructure as NHibernate, or a custom built solution can.

Regarding public types, I stick with IEnumerable and use the Add and Remove methods for the parent, usually .. sometimes user collections, but never IList.

+1
source share

This is a really good question - and something that I realized when trying to use ORM for domain objects. My domain objects expose public properties of type IEnumerable that return ReadOnlyCollection, so the only way to add to the collection is to call the custom Add method on the parent.

In my opinion, no, you don’t go too far to create your objects this way.

I fully justify attempts to encapsulate your objects as much as possible, while maintaining private fields and providing public methods that are atomic, clearly show intent and ensure that objects can only exist in an acceptable state. If this means using raw ADO.NET, then so be it. For me, so that domain objects are strictly built, I should not violate the choice of DAL technology.

However, I HATE writing DAL code for the boiler plate and writing raw ADO.NET with sprocs will make my head these days. I realized that the DAL record for encapsulated domain objects becomes MUCH MUCH MUCH easier if you use Event Sourcing as a mechanism to save your domain objects. All you need is an event table that stores all your events as serialized data. Since the domain objects themselves are not saved, it does not matter that the repositories do not have access to the List property on the domain object. Then your unit of work "raises" those events that the query component can handle, which fills / updates any tables that you need to use simple DTO and ORM.

Here is an example of an event source

CQRS and event sources are actually designed to provide high scalability and, by definition, include many asynchronous operations based on a β€œconsistent” paradigm. However, even when working on projects that do not require such a level of scalability, I believe that these templates synchronously provide a mechanism for my domain objects to be fully encapsulated, at the same time without having to write one line of DAL code with manual processing, while preserving MASSIVE the amount of time and providing a complete audit trail (events) for each action taken, thrown for free. It is also an invaluable tool if your system needs to communicate with third-party systems through messaging.

+1
source share

I tried to use POCOs in several projects as domain objects, and, frankly, it only works for simple / small projects.

I love ORM and will not dwell on their use. But I always create a domain layer on top of the orm / repository layer. And I create specific domain objects that are used in my application. I use a mapping structure such as automapper to convert domain objects to / from data objects.

My recommendation to you is to stop using POCOs if you use an entity infrastructure and allow EF to generate data objects for you. Then create the domain objects and let automapper handle the mappings in your domain layer.

This is a bit more, but it is more flexible and easier to work with.

+1
source share

There is nothing that says POCO cannot contain your own complex objects. What makes POCO POCO is that it is not related to the state of the data, and not that it can only contain lists as objects.

0
source share

All Articles