Saturday, February 7, 2009

What Is Encapsulation? Part I: Private Fields Does Not Encapsulation Make

Ever since hibernate came onto the scene a few years ago, I have been seeing more domain entities that contain nothing but getters and setters. This seems to go against the core principle of object oriented programming: data and behavior should be encapsulated into a cohesive object that exposes a well-defined interface.

Making fields private does not make the class encapsulated. If a domain entity contains nothing but data, then it is closer to a data structure then to an object. Such a design has a definite procedural under tone to it.

Procedural programming may fit your problem better then OO, but usually it is a mistake, and therefore an anti-pattern. It has even been given a name: Anemic Domain Model. See Martin Fowler’s explanation: http://www.martinfowler.com/bliki/AnemicDomainModel.html.

There are other benefits then the one Fowler mentions. First it is easier to share core business logic when it is encapsulated in a domain model. Take a company that sells custom T-shirts and hats. The core logic around an order is unlikely to change between the web application for customers and the in house order taking application. Encapsulating it behind an Order object makes it much easier to share between the applications.

This is in theory only. In practice the in house system is likely to be on a different platform then the web application, making it difficult to share the domain model. This is the core problem SOA is trying to solve.

The second problem is that business rules are often different between applications. You may need more strict validation on an order placed over the web by a customer then you would on an order placed by a trained staff member.

Patio Building As Software Design


I’m hiring a contractor to build a patio at my house. It’s going to have a concrete floor and two stonewalls. The contractor is handling the details of how the patio is built. I don’t need to know where to get the materials, how to get them on site, how to build the walls, or how to pour the concrete.

The contractor will delegate to the suppliers who will ship the materials, the workers to lay the stones for the walls, and the concrete guys to pour the floor. The contractor will need to coordinate between them as well. The workers will need the correct materials before they can start, and the concrete can’t be poured before the walls are built.

The contractor is encapsulating me from the details of the patio building process, and is coordinating the different domain experts in order to bring them together to successfully build my patio. He doesn’t need to know the details of how to make or ship the materials, how to build the walls, or how to pour the concrete. The experts in those respective steps are encapsulating him from the details.

If this was a software system, below might be a model for it:



I make a request (build a patio) to the contractor (the service layer). The contractor delegates to several experts (domain entities) such as supplier, workers, and concrete guys. The contractor coordinates the work as the experts perform their respective steps.

Since the contractor delegates’ the responsibility to create the materials, the supplier can make changes to their manufacturing process (by upgrading equipment for example) without the contractor needing to know. This allows the supplier to easily use the same or similar (subclassed if you will) manufacturing process to create materials for other contractors, which may or may not be building something completely different (a new multi-story building perhaps). The supplier can make any change necessary in order to better accommodate the needs of all of its customers.

Multi-Tier Architecutre


I’ve seen the anemic data model anti-pattern recently in multi-tier architectures. A client and remote server run in different contexts. It is difficult to share any behavior in that scenario. This is the reason why DTO (Data Transfer Objects) were invented. The Anemic Domain Model anti-pattern comes from applying the DTO pattern to hibernate persisted entities.

Usually the hibernate objects are themselves passed to the client. This makes putting logic in them difficult to do, since most of it can’t run on the client. Under these circumstances, keeping most of the logic in the DAO (Data Access Object) layer becomes the path of least resistance. The DAO is a subset of the service layer, and is exactly the kind of problem Fowler warns against. It forces a more procedural design on your architecture. Fowler and many other OO advocates strongly advise against multi-tier architectures for this very reason.

Don’t go overboard!


A perfectly encapsulated class would not allow any access to any data it contains, nor would it send the data to any other objects it collaborates with. This is neigh impossible in the real world, unless you have one object that does everything. I, however, wouldn’t recommend that kind of design.

OO is a theory. Applying that theory in the real world means compromising. It is important to understand the theory, the benefits it brings, and how those benefits are derived. When compromising on the principles of OO, it is important to know what you are giving up. Don’t stick to dogma of any particular paradigm if the consequences out weight the benefits.

Java is built to be an OO language. That doesn’t mean procedural concepts can’t or shouldn’t be applied. The consequences will be higher however. OO should be the first choice. The consequences of any deviation should be weighed carefully.

Conclusion


You may have noticed that i didn't give a solution to the anemic domain model anti-pattern in multi-tier environments. I'm more curious about what you think. Is there a good way of avoiding this problem? What is it?

Also leave your rating for this post: +1 Ted Neward (brilliant) or +1 Britney Spears (stupid)

Blog Directory Listing

No comments:

Post a Comment