Agile Ajax

Layered architectures & other abstractions.. revisited

Speaking in terms of abstractions can cause a peculiar kind of paralysis to occur by letting developers avoid the specifics longer than necessary.  You might have been part of a discussion in the past where your team struggled to define the names of each layer in a system or wrestled with the impedance caused by conflicts between the logical versus physical aspects of layers in an application.  These are symptoms of what I am referring to.

Suppose, for example, you have the following system-- business logic contained in a service layer, and a less well-defined set of classes that communicate with some external system(s).  The fact that the classes in this latter group serve a common function may let you talk about these classes as comprising a distinct layer in the system-- but it is just as likely that concerns such as transaction management, persistence or packaging considerations drive the need to make exceptions to an otherwise clear-cut boundary between these two layers.

As the code matures, the service layer may start to know too much about specific components in the newer layer, and this new layer may start to rely on knowledge of (and code for) certain paths through the service layer.  This may sound like a recipe for disaster, but often this kind of coupling is just an unintended consequence of developers realizing that the most expedient way of working with the system runs against the grain of the layered architecture-- which itself is an odd thing to confess, since one measure of a layered architecture's worth is in how well it provides a path of least resistance to normal development.

Two camps emerge when this kind of problem surfaces.  On the side of expediency, team members begin to suspect that maintaining a strict separation between these layers requires too much overhead either during the design of new features, or in refactoring of the existing code base-- they push to allow the layers to co-mingle.  In the other camp are developers who believe such co-mingling should not happen (to take the purists perspective), or that it is inherently unsafe (future-proofing the architecture against factors they expect to change, such as transaction management, clustering strategies, security considerations, etc).  Oddly enough, the one thing everyone seems to agree on is that the distinction between these layers should still exist-- at least on paper.  So instead of changing their definition of what constitutes a "layer" proper, they either rationalize the need for exceptions to the rule, or enforce the separation of layers despite the added cost of maintenance.

Rather than discuss all the kinds of arguments that arise in these cases, I believe it suffices to use the example above as in introduction to something more fundamental.  This more fundamental issue deals with why and how developers place such a high level of importance on abstraction in the first place, even to the detriment of otherwise good design.

Abstractions reflect the way we like to think about the construction of a system once it is in place, but I don’t believe they always reflect how teams most effectively work and live within those systems once they are built.

Take object-relational mapping frameworks for example.  We like to think that a good object-relational mapping framework shields developers from having to think about the database-- and, during the inception of a project, this is normally true.  But as the application matures, the number of caveats in the system increase-- changes to the relational side occur in lockstep with changes to the object model, and quirks on one side need to be understood, even if they don't directly manifest themselves on the other end as problems. The less an object model is explicitly bound to a database implementation, the more likely the team itself needs to become well-versed in how the underlying ORM works, and must therefore retain this knowledge throughout the life of the application.  So, with this additional level of abstraction, you have effectively changed what used to be a code maintenance tax for the life of the application to a more subtle, but (in some cases) costly mental tax on the developer for the life of the application.

Don’t get me wrong-- this is not to say that abstraction itself is a bad idea, nor that layered architectures are inherently bad.  Rather, I believe these kinds of abstractions work best when the cost on the development team for the life of the project (which, unless you are lying to yourself, is never ‘zero’) is less than the hypothetical cost of maintaining a larger code base by reducing the number of abstractions.

Leave a comment

Powered by WP Hashcash

About Pathfinder

  • We design and build extraordinary applications for companies looking to make the next great idea a reality.
  • learn more

Topics

WordPress

Comments about this site: info@pathf.com