Since the introduction of NHibernate and WCF, .NET developers have been moving closer and closer to the concept of unified entity-models. The end game here is that the same class can be act as your ORM entity, your WCF DTO, and your model for a MVC, MVP, or MVVM framework. Mark Seemann, author of Dependency Injection in .NET, argues this isn’t necessarily a good thing.
The crux of his argument is that “At the Boundaries, Applications are Not Object-Oriented”. As you are undoubtedly aware, most serialization technologies require public, default constructors and writable properties. These requirements essentially force you to break encapsulation and the principals of data hiding when designing your DTOs. Even basic invariants such as requiring fields to be non-null/non-empty are impossible to enforce because the DTO could literally omit anything. He goes on to justify these two tenants:
- Services share schema and contract, not class.
- DTOs don’t break encapsulation because they aren’t objects at all.
Given this situation, Mark offers three options for moving forward:
One option is to stick with what we already have. To bridge the gap we must then develop translation layers that can translate the DTOs to properly encapsulated domain objects. This is the route I take with the samples in my book. However, this is a solution that more and more I’m beginning to think may not be the best. It has issues with maintainability. (Incidentally, that’s the problem with writing a book: at the time you’re done, you know so much more than you did when you started out… Not that I’m denouncing the book – it’s just not perfect…)
Another option is to stop treating data as objects and start treating it as the structured data that it really is. It would be really nice if our programming language had a separate concept of structured data… Interestingly, while C# has nothing of the kind, F# has tons of ways to model data structures without behavior. Perhaps that’s a more honest approach to dealing with data… I will need to experiment more with this…
A third option is to look towards dynamic types. In his article Cutting Edge: Expando Objects in C# 4.0, Dino Esposito outlines a dynamic approach towards consuming structured data that shortcuts auto-generated code and provides a lightweight API to structured data. This also looks like a promising approach… It doesn’t provide compile-time feedback, but that’s only a false sense of security anyway. We must resort to unit tests to get rapid feedback, but we’re all using TDD already, right?
If you are interesting in Object Oriented Design and Encapsulation don’t miss his series titled Poka-yoke Design: From Smell to Fragrance.