Tuesday, June 21, 2011

Why Your Objects Aren't Objects...

Objects…

The crux of Object-Oriented Programming, or OOP as it is commonly referred.

Odds are if you are programming in the year 2011, you have learned to build and rely on them to accomplish just about everything. It makes sense right, since we are modeling the real world, and the real world is filled with them. Its been around for quite a while, with OOP making its first major foray into the programmer vernacular back in the 1970s via the SmallTalk programming language. Terms like polymorphism, encapsulation, access modifiers, properties, methods and the like should be very familiar to you. Even the typical greenhorn developer fresh from school knows how objects are composed into classes, how to leverage an Animal base class to let other animals boast about how they eat, as well as the notion of an interface to specify contracts that classes can implement.

So the question becomes, how did they go from objects to bags of data??


A little confused by that question? Well, for sake of argument, lets consider the typical developer being a .NET developer. In the .NET space, where the pace of technology seems to go at break-neck speed, there exists a sea of developers seeking guidance on what the "best practices" are for building applications. Unfortunately, many developers, including myself at one point, looked no further than the vendor that provided their framework. While Microsoft's online documentation proves to be a valuable source of information, there is also a history of providing application guidance that has been less than savory we shall say.

The Standard Enterprise Application Architecture?

Take for instance the Three-Layered Services Application guidance, which in my experience has surfaced in every development team I have been a part of. On its surface, it appears a very reasonable approach to building an application, and I have even been a part of mainstream developer training where it was proposed as the a standard application architecture for enterprise applications. It teaches us that we should separate our presentation, business and data access logic into separate layers, in order to enforce separation of concerns, and shield higher layers from physical changes at lower levels. This architecture even proposes that there are certain cross-cutting concerns that are understood to transcend layers, which makes sense as well, as we all know that things such as logging information and exceptions are agnostic to application architecture. The following diagram comes from the guidance, which spells out much more concretely the approach.



It all looks and sounds pretty logical, and even the term business entity seems to make sense, as it seems to convey that we are dealing with entities (objects) that are related to the business (domain). Its not until you start to unravel what the terms actually represent that it starts to break down. Coming directly from the guidance, it is stated that business entities

"... are data containers. They encapsulate and hide the details of specific data representation formats."

What about this definition sounds like an object? To be honest, not much besides perhaps stretching to say that the fields/properties of the data container represent attributes of objects in your business domain. As fishy as it sounds trying to make this type of code structure fit into the definition of a true object, we find ourselves doing exactly this kind of thing all the time.

So where did the behavior go?

In the three layer architecture, we are told that the behavior is really the "business logic", and that it belongs in its own container, labeled a business component. A business component is then defined as

"...the software realization of business concepts. They are the primary units of design, implementation, deployment, maintenance, and management for the life cycle of the business application. Business components encapsulate the business logic, also called business rules. These rules constrain the behavior of a business concept to match the needs of a particular company."

This coupled with the prior definition of the business entity clearly illustrate that there is a separation of behavior and state, which clearly does not line up with the notion of an object, the representation of both. While it is representing the notion of business entities, to Martin Fowler's point on anemic domain models, it is really doing nothing more than providing Data Transfer Object instances that are populated via Transaction Scripts. (for those with the P of EAA scorecards at home...) Its not to say that there is no value in the architecture at all, but what it does seem to promote is a departure from OOP back into more procedural programming. The very nature of a Transaction Script and DTO deviate dramatically from object-oriented design.

Therefore, a true object does not a business entity make...

Evaluating the Anemic Domain Model Pattern/Anti-Pattern

Even with the prevalence of OOP in modern programming, it definitely has its share of critics. Not just your standard run of the mill bloggers, but well-known researchers such as IBM's Chris Date and developers such as Richard Stallman (RMS). Just as there is criticism of OOP, there is also criticism for OOP-centric design patterns such as Domain Driven Design (DDD) that put heavy emphasis on building a core domain model that is centered around objects in the purest sense.

Greg Young points out in a blog post concerning this subject that there are indeed cases that seem to be a perfect fit for a model devoid of the complexities of a true domain model. Among his points, Greg brings to light some of the all-too-real issues that are present in a lot of "enterprise" apps:

  • The domain we are modeling is inherently simple
  • The OOP skills of the team members are lacking or not substantial enough to support a true domain model
  • The non-functional benefits of the layered architecture are necessary

The problem I have with these points is the fact that they are pretty much true, despite what I would like to believe about development and architecture in general. As a developer who seeks to continually improve, and build applications on architectures that scale for tomorrow, it is disheartening to see a project take what may be a less valuable approach because of the risk of doing it in what might just be the "right way". However, I really can't argue the fact that introducing a greater risk into the project at the cost of benefits that may not be realized in the short term seems foolish. Especially if the only immediate benefit is developer satisfaction at implementing a more exotic architecture at a point in time when it wasn't needed/justified. We all know or are a developer that wants to do the latest and greatest things in software engineering on our own projects.

The Takeaway

At the end of the day, the answer for the use of true objects versus an anemic domain model lies within the context of the application. Sometimes the nature of the business prevents you from having the exposure to domain experts that is required to support a true domain model. Other times, you don't have that restriction and the added complexity pays dividends in the establishment of a core domain model that is then able to be leveraged outside of its original application in many meaningful ways. Either way, requirements for both the application at hand and the handling of domain-specific logic beyond that project are the key indicators for the approach that works best.

In the time I've spent doing software development, I've seen far more cases where anemic domain models were the quicker route and lead to immediate results. However, I have also been negatively impacted by the specificity of the code that a Transaction Script-based approach leads to as enhancements come down the pipeline. A lot of help comes in the form of vision on the part of project stakeholders, and unfortunately, that really is outside of the developer's role. The knowledge the customer/stakeholder has on the domain at hand is too valuable to lose sight of by asking those without vision to postulate on the future. That is about as useful as estimates on development tasks involving details you've never reviewed; its a shot in the dark at best.

Next time you go to create an object, realize that all may not be as it seems. The question you must ask yourself is, what is the impact on the application due to the way I'm implementing objects? Hopefully this post has helped to both explain why you may not be implementing objects completely, as well as what the ramifications are based on whether or not the objects you implement are considered true entities, or DTOs.

2 comments:

  1. I wrote a long reply but then your comment system said it was too long, so I paired it off to my own blog: http://bit.ly/lfvnQR

    ReplyDelete
  2. Strict OOP should really be left to the companies that develop frameworks and libraries that developers consume because its a language/patterns we all understand. But guess what ... those don't have databases attached to them with users waiting for GB/TBs of data to be processed.

    ... and I am more fond of "Util", Sean.

    ReplyDelete