September 15, 2007
Layering - too simplistic to actually work
After seeing Mark's post on Reasons for Isolation describing the ways Layered Architectures break down, and the ways making it more testable can change it, I've got to wonder -- is Layering just too simplistic to actually work?
Just the other day I was doing a design review for a fairly simple Smart Client whose design was layered. In order to stay away from interfaces that accepted dozens of ints, strings, and dates, they wanted to have each layer talk to the other using "entities". So where are these entities defined - oh, in a "vertical layer" that all the horizontal layers talk to.
OK, so we've taken the simplistic one-dimensional layered architecture and added a dimension. What now?
Well, it seems that having the business logic and the entities in separate layers goes against one of the most basic Object Oriented principles - encapsulation. So, let's put the entities back in the Business Logic Layer. But then how will the Data Access Layer accept those objects as parameters?
So, that is solved by keeping Entity Interfaces in the "vertical" shared "layer", and having the entities in the business logic layer implement those interfaces. That way, the data access layer can still accept parameters corresponding to those interfaces:
void InsertCustomer(Shared.Entities.ICustomer customer);
So far so good. Now, we want more testable UI layer code - so we use Model-View-Controller (MVC) - of whichever flavor suits your fancy. I'd say that Supervising Controller is a must. You could also add another presenter for more complex screens as in Passive View, but I'd be less strict on that. So, in which layer do these Controllers/Presenters sit? And is the Business Logic Layer the Model? Or is the Model just part of it?
Well, our Supervising Controllers are those who decide what action to do and when, where to get the data from, etc. That sounds like business logic to me. So let's put them in the BLL. Presenters for the Passive View are much more UI centered, so let's put them in the Presentation Layer. But we don't want them tied to the implementation of the view, so we'll put them in a separate package, and have them depend only on the view's interface. So we'll put the view interfaces in a package separate from the view implementation as well.
If it wasn't clear up to this point, all the questions raised in this post are architectural in nature - as in they have a substantial impact on the structure and flow of the system, and will definitely have a profound effect on its maintainability. In other words, if you think that Layer Diagram covers your design - you're probably deluding yourself. Personally, I think that's why many developers consider architects to be "out of touch with the real world".
When you have a design that answers these, and other architectural concerns, you'll find that layering is of little importance. The specific constraints on each package are what counts. The fact that the Presentation Layer can talk to the Business Logic Layer doesn't mean that the classes in your Views Implementation Package can. A large part of an architects work is to specify these constraints, and communicate them to the team. Tools like FxCop may help in terms of enforcing these constraints, but I believe that getting the team to actually "buy-in" is more effective.
Single-dimensional layered architectures don't work. They violate Einstein's maxim:
Make everything as simple as possible, but not simpler.
Layering - "simpler" to the point of simplistic.
Posted by Udi Dahan at 08:35 AM Permalink
|