Keith Watanabe * NET 2.0

The Anemic Domain Layer Or A Better Business Layer
By: Keith Watanabe
Published On: 11-22-2007

I haven't yet checked out Martin Fowler's Enterprise Design Patterns book, but he has a small article online regarding the Domain/Model layer.  Or rather he talks about the "Anemic" domain layer, which in short are simply model objects that has getters/setters without any methods for business logic.  He then criticizes the notion of a business/service layer that places all the business logic into place.  What he doesn't do (at least in the online article) is demonstrate examples of this anti-pattern both in practice and in resolution.

I do think he supports frameworks like Hibernate, which are pojos that perform some object-relational mapping duty with the support of a service layer.  I decided to check out his book on Amazon and read some reviews.  It seems that some of this theory is older, maybe geared towards the old EJB model, especially for the earlier versions of EJBs where people would pass around value objects to avoid the overhead associated with setting/getting each attribute (because of the whole remote invocation issue). 

That said, it would be nice for him to update that section.  It's hard to say if his beliefs still apply to ORMs like Hibernate, ActiveRecord, etc.

I have my own homegrown ORM with some operations that might seem like "business logic."  But what I can't stand is this ephmeral phrase of "business logic."  What is it?  The way I structured my application is to use a business layer similar to how Session beans would act as a facade for managing entity beans and keeping all "business logic" at this level.  So I would do things like use the business layer as an interface to the domain layer.  I've found this methodology to be very effective.  If I put the same logic in my controllers, the controllers become difficult to test and are almost always throwaway objects.   If I put that logic in the domain layer, then I get tightly coupled model objects.

However, the business layer ensures reusability of operations that are not very object oriented.  I read some criticism that this notion isn't very "object oriented" and that it's more procedural.  I don't see a problem with this idea.  You do lose to some degree the object oriented nature of a business layer.  I've found that the business layer has minimal properties except for some injected services (like logging, the models and some utilities).  But the business layer is the magical component that truly decouples each layer, allows for a significant amount of reuse, provides the critical area for easy unit testing, allows tremendous reuse because of the lack of coupling and is damn easy to code.  How this notion is problematic in software engineering, except for some OOP purist, is beyond me.

Sadly enough, I rarely find good examples on the net for handling this.  Here's how I handle it:

My business layer truly is the real "middle" layer as it sits between my controllers and model layer.  It's a 4th layer that provides more complex functions of organizing things.  It's the glue between your controller and model layer.  In coding practice, I use statically instatiated objects.  All methods are static because there's no reason to keep state at this level (similar to a stateless session bean).  The methods are very operation based; that is, more functional than anything.

My method signatures are composed of associative arrays, other model objects, or a few set parameters that are typed.  I tend to avoid having large numbers of parameters since signature changes make the interface very inflexible.  If I anticipate a large number of optional parameters, I'll pass in either an object to enforce the types of parameters that I want passed in, or I'll pass in an assocative array that contains a more flexible data structure to mimic what I want being passed around to this layer.

I try to keep my functions/methods simple.  Only one operation per method.  I try to restrict my methods to be about 5-7 lines per method.  That keeps the code very readable.  At most, these functions should not exceed a page.  You want to ensure that your code is readable and understandable.  The more it does, the more you want to split your operations into smaller methods, even if you don't anticipate reusing those functions.  Moving them into private methods is a good idea since you can test the operations one-by-one; or it's best to just make them into public methods since obviously you won't be able to call those private methods from the unit test.

It might seem silly to write a facade that might seem to only delegate a call to another function.  However, having this interface is a good idea.  As it's been stated many times, doing it in this manner ensures that your implementation details are kept well hidden.  For instance, if indeed you move your call from one ORM to another (like say I get rid of my ORM for something like Plone), then I still don't have to change the code at the controller layer or whatever calls the code.  The code stays the same at those levels, only forcing me to switch out the calls inside the business layer, not outside of it.

The other thing about this is you are insulated by providing only what's needed.  You don't have to write CRUD for every single operation that you anticipate.  Only the ones that matter.  You can trust your ORM layer that it will do the heavy lifting while your business layer manages the high level calls.  For instance, imagine create a new project.  You might have to do some complex tasks like creating a new user, add tasks, add people to the project, etc. all in one operation.  If you did this at a controller level where the controller had direct access to your ORM layer, you might be looking at numerous set and save operations that'll bulk up your controller layer.  What happens if next you want to expose similar operations to a web service layer that can return formats like JSON, XML, or HTML fragments?  You'd have to copy and paste that code three more times.  Now, you have those operations in four different places.  Trust me, I've done this and found it nearly impossible to modify the code after a while because I'd end up search and replacing the code, rather than strategically adding a single call to a controller.

In short, I don't think it's a sin for this type of layer to exist.  In fact, I think it's a sin that people are still thinking in 1999 and haven't made a lot of progress to focus their efforts on developing the notion of a business layer.  I've seen some new enterprise components like rules engines to do bits and pieces of what we're talking about here.  However, I don't think they do all that great of a job.  All they do is introduce more hardware, software licenses and complexity in a truly easy-to-solve type of problem.

Either way, I really hope that someone who's far more experienced in the field give an appropriate and lengthy explanation on the proper way of dealing with this solution.  I think my way is better and I challenge people out there to provide better examples to show me where my thinking can be improved.  If that's the case, please sign up an account here, and add your comments freely.

AddThis Social Bookmark Button Sphere: Related Content

Trackbacks: (Trackback URL)

No Comments Posted Yet
December [January] February
Sun Mon Tue Wed Thu Fri Sat
28 29 30 31 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31