[c#] Plain Old CLR Object vs Data Transfer Object

TL;DR:

A DTO describes the pattern of state transfer. A POCO doesn't describe anything. It's another way of saying "object" in OOP. It comes from POJO (Java), coined by Martin Fowler who literally just describes it as a fancier name for 'object' because 'object' isn't very sexy.

A DTO is an object pattern used to transfer state between layers of concern. They can have behavior (i.e. can technically be a poco) so long as that behavior doesn't mutate the state. For example, it may have a method that serializes itself.

A POCO is a plain object, but what is meant by 'plain' is that it is not special. It just means it's a CLR object with no implied pattern to it. A generic term. It isn't made to work with some other framework. So if your POCO has [JsonProperty] or EF decorations all over it's properties, for example, then it I'd argue that it isn't a POCO.

Here some examples of different kinds of object patterns to compare:

  • View Model: used to model data for a view. Usually has data annotations to assist binding and validation. In MVVM, it also acts as a controller. It's more than a DTO
  • Value Object: used to represent values
  • Aggregate Root: used to manage state and invariants
  • Handlers: used to respond to an event/message
  • Attributes: used as decorations to deal with cross-cutting concerns
  • Service: used to perform complex tasks
  • Controller: used to control flow of requests and responses
  • Factory: used to configure and/or assemble complex objects for use when a constructor isn't good enough. Also used to make decisions on which objects need to be created at runtime.
  • Repository/DAO: used to access data

These are all just objects, but notice that most of them are generally tied to a pattern. So you could call them "objects" or you could be more specific about its intent and call it by what it is. This is also why we have design patterns; to describe complex concepts in a few works. DTO is a pattern. Aggregate root is a pattern, View Model is a pattern (e.g. MVC & MVVM). POCO is not a pattern.

A POCO doesn't describe a pattern. It is just a different way of referring to classes/objects in OOP. Think of it as an abstract concept; they can be referring to anything. IMO, there's a one-way relationship though because once an object reaches the point where it can only serve one purpose cleanly, it is no longer a POCO. For example, once you mark up your class with decorations to make it work with some framework, it is no longer a POCO. Therefore:

  • A DTO is a POCO
  • A POCO is not a DTO
  • A View Model is a POCO
  • A POCO is not a View Model

The point in making a distinction between the two is about keeping patterns clear and consistent in effort to not cross concerns and lead to tight coupling. For example if you have a business object that has methods to mutate state, but is also decorated to hell with EF decorations for saving to SQL Server AND JsonProperty so that it can be sent back over an API endpoint. That object would be intolerant to change, and would likely be littered with variants of properties (e.g. UserId, UserPk, UserKey, UserGuid, where some of them are marked up to not be saved to the DB and others marked up to not be serialized to JSON at the API endpoint).

So if you were to tell me something was a DTO, then I'd probably make sure it was never used for anything other than moving state around. If you told me something was a view model, then I'd probably make sure it wasn't getting saved to a database. If you told me something was a Domain Model, then I'd probably make sure it had no dependencies on anything outside of the domain. But if you told me something was a POCO, you wouldn't really be telling me much at all.

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to poco

What is POCO in Entity Framework? Using JsonConvert.DeserializeObject to deserialize Json to a C# POCO class Code-first vs Model/Database-first Plain Old CLR Object vs Data Transfer Object 'POCO' definition

Examples related to dto

Difference between DTO, VO, POJO, JavaBeans? any tool for java object to object mapping? What is a Data Transfer Object (DTO)? Plain Old CLR Object vs Data Transfer Object