There's nothing worse than jumping into a software project where the lead architect has just completed a five day designs pattern course, or has just made it through a comprehensive service oriented architecture (SOA) workshop. From that point on, every problem the architect encounters ends up getting shoehorned into one of the Gang of Four (GoF) patterns, and every request-response cycle ends up traversing through more logical layers than a celebrity wedding cake.
The scourge of needless layering
One project I worked on a few years back required every interaction with the server to first go through a servlet, a validation interface which then hit a required Business Delegate class, a Session Facade EJB that used Spring, and then a Data Access interface that used Hibernate. A class implementing a set of genericized interfaces was required. More often than not, there was little or no code in anything but the Session Facade, code which could have quite easily have been written within the Servlet class itself, a process that would have greatly simplified the project, collapsing the layers into something very tight and cohesive.
Servlet - the touch-point component with the application server, often used for front-line security and data cleansing
Business Delegate - mitigates access to business services, often hiding low-level interaction complexities such as transport protocol switches and remote access
Session Facade - orchestrates the use of data components, often combining access to multiple data sources into a single transaction
Data Access Layer (DAL) - often implemented as data access object (DAOs), the DAL hides complicated and potentially proprietary database access procedures from the application
Of course, tight and cohesive doesn't win anyone the SOA Architect of the Year award. SOA specialists want software applications need to be loosely coupled, and loose coupling means adding in layers. Moving away from Java EE patterns and into the world of SOA, it's not uncommon to see SOAP based and RESTful web services developed using the same excessive enthusiasm, where layers exist not for pragmatic reasons, but more for philosophical reasons that make the solution architect feel useful.
Not everyone is doing SOA right, especially when it comes to exposing functionality at a fine grained level.
Stealing from today to support an uncertain future
In a modern, service based architecture, the idea is that solutions can be built by assembling together a number of fine-grained services. This means using web services to expose various process services, functional services, entity services and sometimes even more coarse grained composite or facade services. The big push in the industry towards micro-services has been driven by the fact that when small grained functionality is exposed through components that are easily integrated into a solution, then developers and application designers can create new services by reusing these small grained services in ways that had never previously been imagined, brining the promise of reduced application development time through reuse to fruition.
Of course, not everyone is doing SOA right, especially when it comes to exposing functionality at a fine grained level. Many organizations simply expose coarse grained services, and then push the request through a number of Java classes and components that look like process services, functional services, entity services and facade services, but in fact, these services aren't services at all - they're simply just Java classes that do little more than bloat the codebase and make troubleshooting code a confusing trip through unnecessary layers.
Loose coupling of components is always a great idea, except for the times when it isn't, and when it isn't a good idea, it introduces needless complexity into an application. Quite often the layering of a non-distributed application is done with the idea that one day a given piece of functionality might need to be delivered as a micro-service, and creating the requisite layers today might make distribution in the future easier. Such thinking is rarely correct.
SOA best practices
The old YAGNI principle, You Ain't Gonna Need It, applies here. It is a common anti-pattern to needlessly design for the future. The fact is, when a given piece of functionality is needed in the future, there will be enough differences in what is required, be it security or validation or even data composition, that what exists now will not port seamlessly into tomorrow's requirements. The future service will require enough changes that what exists now will still require a significant re-write or additional coding, making the effort to layer today's non-distributed application a big waste of time.
Simplicity is the key when it comes to developing enterprise applications. For distributed applications, ensuring the interactions between remote components are done in a loosely coupled way is important. But for the parts of an application that will not be distributed, needless layering only slows down development and makes long term maintenance more problematic. Keep your applications simple, and let those needless layers collapse upon themselves. Future developers will thank you for it.
Have you been victim to excessive application layering? Let us know your stories.