In this article, I’d like to clarify the differences in DTO vs Value Object vs POCO where DTO stands for Data Transfer Object, and POCO is Plain Old CLR Object, also known as POJO in Java environment.
DTO vs Value Object vs POCO: definitions
First of all, I want to make a note regarding Value Object. There’s a similar concept in C#, namely Value Type. It’s just an implementation detail of how objects are being stored in memory and I’m not going to touch this. Value Object, which I’m going to discuss is a DDD concept. Check out this article to read more about it.
Alright, let’s start.
You might have noticed that such notions as DTO, Value Object and POCO are often used interchangeably. But are they really synonyms?
DTO is a class representing some data with no logic in it. DTO’s are usually used for transferring data between different applications or different layers within a single application. You can look at them as dumb bags of information the sole purpose of which is to just get this information to a recipient.
On the other hand, Value Object is a full member of your domain model. It conforms to the same rules as Entity. The only difference between Value Object and Entity is that Value Object doesn’t have its own identity. It means that two Value Objects with the same property set should be considered the same whereas two Entities differ even if their properties match.
Value Objects do contain logic and, typically, they are not used for transferring data between application boundaries.
POCO (Plain Old CLR Object) is a term created as an analogy for POJO only because “POJO” itself can’t be used in .NET as the letter “J” in it stands for “Java”. Thus, POCO has the same semantics as POJO.
POJO was introduced by Martin Fowler and others to oppose JavaBeans and other heavy-weight enterprise constructions that gained a lot of popularity back in early 2000’s.
The primary goal of POJO is to show that domain can be successfully modeled without bringing to the table complexity related to the execution environment (and JavaBeans brought a lot of it in its early versions). Moreover, the execution environment shouldn’t have anything to do with domain modeling at all.
There’s no direct analogy for JavaBeans in .NET because Microsoft has never introduced the same concept, but we can come up with some made up parallel to help express this concept.
You can think of Component class from System.ComponentModel namespace as an opposite for POCO. There are a lot of classes in .NET that inherit from Component, for example, DBCommand from System.Data and EventLog from System.Diagnostics.
Of course, in most cases, you wouldn’t create a domain class inheriting from Component. It just doesn’t make any sense, because such approach brings a lot of unnecessary complexity, thus contradicting the YAGNI principle.
Another good example of non-POCO approach is Entity Framework before 4.0 version. Every class EF generated inherited from EntityObject base class and thus brought a lot of complexity specific to Entity Framework. Since version 4.0, Entity Framework introduced POCO data model which allows for use of classes that don’t inherit from EntityObject.
That said, POCO stands for use of as simple classes as possible for domain objects. This notion helps conform to YAGNI, KISS and other best practices. POCO classes can contain logic.
DTO vs Value Object vs POCO: correlations
Are there any connections between these terms? There are a few.
First of all, DTO and Value Object represent different concepts and can’t be used interchangeably. On the other hand, POCO is a superset for DTO and Value Object:
In other words, Value Object and DTO shouldn’t inherit any heavy-weight enterprise components and thus they are POCO. At the same time, POCO is a wider set: it can be Value Object, Entity, DTO or any other class you might create as long as it doesn’t inherit complexity accidental to your domain.
Here are properties for each of them:
Note that POCO may both have and not have its own identity. It depends on what type of POCO it is: Value Object or Entity. Also, POCO may or may not contain logic in it. It depends on weather or not POCO is DTO.
Alright, I hope I made it at least a little bit clearer. I’d like to summarize this topic with the following:
- DTO != Value Object
- DTO ⊂ POCO
- Value Object ⊂ POCO