In the fourth part of this series, I’d like to talk about my uses of layering as it applies to architectural styles. In searching for a good explanation of the Layers pattern itself, I stumbled up on this posting which I thought was a good analysis. Although the analysis is done in the context of Visual FoxPro, it gets across the mindset I have when working with the Layers pattern.
In my experience, I find myself consistently implementing layering in my applications as they grow in scale. I try to use layering as means by which to simplify the interactions between objects in my application to somewhat, well-defined levels of abstraction. I find that layering is also a good exercise in following good practices as it applies to cohesion and coupling; without an appropriate use of both, the use of layers may appear more difficult than it should be. In reading this post, please keep in mind that these abstractions are in place to help reduce complexity from the perspective of the developer. Adherence to preserving the integrity of each layer in your architecture is left up to you. In practice, you may come to find that breaking those boundaries every once and while may be more practical, but that is decision you have to come to.
So let’s take a look at an overview diagram that I threw together:
In the diagram there are few things that I want to point out. Firstly, I chose to show what I commonly refer to as a 3-tier layering scheme: Presentation, Business, and Integration. Semantically speaking, I’ve heard a lot of variations on the naming of these layers (e.g. – Presentation = Interface, Integration = Data), but for the purpose of this series let’s stick with what written. Second, I’ve chosen to identify a few patterns in the given layers based on my previous experience with them. Please note that there are entire disciplines in software engineering devoted to pattern analysis and implementation, these are just a few that I’ve found useful and not a comprehensive or exclusive list. Third, for the purpose of this diagram, I’ve split the Presentation layer into two segments: Application and Service. Each section represents how I use the Presentation layer in the context of constructing an application with a UI or a service API. It should be assumed that the Business and Integration layers have to solve similar problems for each section, so no distinction has been made in the other layers.
With that being said, let’s look at each layer in more detail:
Presentation – The Presentation Layer is where I place all of the classes associated with assembling some type of consumable interface for either an application or a service API.
For an application, the typical interface I expose is a user interface. Web templates, view widgets, and other UI components make up the class types I place into this layer. Typically the Consumer for applications are end-users.
For service APIs, I tend to expose Service classes which encompass units of work from the API as a whole, usually as methods on an object. The Service class’ responsibility normally does not exceed aggregating functionality from the Business Layer. Based on the approach I’m taking, I may even include input validation as the responsibility of the Service class. Additionally, Facade/Adapter classes can be created to re-expose the functionality identified by the Service class but take only responsibility for the translation of messages to and from the consumer of the API. For example, I may not be able to call the service API by instantiating the Service class in shared memory, I may have to utilize RPC calls over SOAP. A Facade/Adapter class would be helpful for creating an interface to use as a basis for WSDL generation and translation of value objects to domain objects (more on this in a little bit). The Consumer for service APIs could be an application or another service API.
- Business – The Business Layer is where I place all of the classes associated with the implementation of the business rules, usually as outlined by my use cases. Based on the architectural style you choose to implement (see next post in series), domain classes can potentially play a larger role in the implementations of these rules. Other classes applicable to this layer could be Validators (for business rules not input), Managers, and Unit of Work classes aggregating interactions as they relate to the Integration Layer. Although I consider the domain classes an integral portion of the “glue” between layers, I usually associate them with the Business Layer since its goals relate more directly to the problem domain than functional aspects.
- Integration – The Integration Layer is where I place all of the classes that act as abstractions for the external resources on which my application is dependent. The responsibility of this layer usually results in classes managing connection and location information as well as domain object mapping. I typically do not find myself creating Transfer classes since most technologies (e.g. – ORM solutions) can work with my domain classes directly. In the diagram you can see some examples of the types of resources and the patterns I use to abstract them. Remember, the Integration Layer is just providing friendly abstractions; the use of those abstractions is dictated by the Business Layer. If multiple classes in the Business Layer need to send an email, both could have a common use of an EmailDelegate, for example, that exposes the basic functionality associated with sending an email. The classes in the business layer care about what’s in the email, the delegate cares about how to send that email and other functional aspects of email.
Hopefully after these brief explanations, it begins to become apparent the crucial role that a domain plays in a layered architecture. The domain pervades into each layer as a contract allowing each to focus on how it can solve the problem using the behavior, or set of behaviors, for which it is responsible. This is yet another reason that semantics play such a large role in the creation of a domain; forming semantically relevant contracts between layers allow you scale your software as the solutions needed for the problem domain scale. From my experience, this turns out to not only be true as it relates to uses cases and business requirements but as it relates to functional requirements as well (e.g. – integrating something like instant messaging into the application).
That’s about all I have on layering, but suffice it to say, I think migitating complexity is always a good thing when you know it will be an issue you have to address in the future. Hopefully I was able to make sense of my perspectives to help you reduce the complexities you encounter. In the next post of this series, we will get more into architectural styles as it relates to the Business Layer as I will try to convey ideas on what I consider light and heavy-weight architectures. I will also try to touch more on the idea of state and what it means for each of these styles.
Thanks for reading.