I’m in the job of establishing partnerships with different stakeholders (authors, readers, vendors, colleagues, etc.) in order to consolidate the vision depicted in my last post about the editorial line I’d like to promote thru this magazine.
In order to defend my ideas about column lineup, editorial style, bill of materials, etc., I need to start from a common ground and that ground is the goal to make this magazine an indispensable reference for success on professional, world-class application development.
This post won’t talk too much about the magazine but about such kind of applications, mainly for those who are not familiar.
Let’s start by checking back the diagram I showed in that post on editorial mindsets:
Figure 1. A typical N-tier, layered architecture.
This diagram shows a typical, modular multichannel architecture at a very high level. With more or less degree of similarity, real-world application architectures look like this one.
Let’s start by saying that these are N-tier applications, in the sense that the application doesn’t comprises a single executable file with its set of libraries but different tiers are executing different parts of a distributed application, each part consisting in an executable process with its associated libraries. This subdivision obeys to the goal of making the application maintainable by keeping cohesion high and coupling low, in a way that components can be easily reused and the impact of later changes is narrowed to a small portion of the application and not the whole.
From a user perspective, the application is accessed through different channels (see Fig. 1). Channels, at a technical level, are typically web (browser-based channels), desktop (fully deployed applications), mobile, embedded devices, etc., or even third party applications, which access our application by consuming services offered by this latter. From a business perspective, channels are better known as “home banking”, “retail”, “branch”, “POS”, “ATM” and other business-related terms but any of those, at an implementation level, falls under some of the technical categories.
Users typically see the channel they use as "the entire application", but beyond that front-end we may find a series of one or more physical tiers, running other parts of the application. Some of those tiers could be out of our scope. Typical examples are the database or a service offered by a third party that will be consumed from our application as a black box.
I’m not including those external tiers in this diagram but just (at the bottom layer in Fig. 1) the bound of our application that is responsible to deal with them.
Tiers show the distribution of an entire application at a process-level. In other words, different tiers run in isolated processes that may or may not be in a single physical equipment.
Tiers, at once, are composed by layers. Layers show modular, logical distribution of the components. Classes and interfaces in a given layer are supposed to work for an overall responsibility (i.e. user input, presentation, data-access, service delivery and several other ends).
That said, while tiers are defined based on expected workloads, required capacity (both attributes based on the application during runtime), layers are chosen for the sake of application comprehensibility from a development-time (not runtime) perspective.
Layers may depend on external APIs to perform their tasks. For instance, a data-access layer could be based on ADO.NET components while a presentation layer could rely on WPF or ASP.NET MVC. However, there is a sacred layer that should not depend on any external API in particular and is the one in the middle, known as domain logic layer. That is the layer that backs the abstract model of our business goal. Its components are typically Customer, Invoice, Product, Address and other real-world nouns; and it’s expected to remain invariable as long as domain rules don’t change. Particularly, it’s expected to remain invariable if tomorrow we modify a data source from XML to ADO.NET, or replace the user interface by adding a RIA channel (i.e. Silverlight, Adobe Air, etc.)
Layers and its contained sublayers are like namespaces that one could explore deeper and deeper. At some point, you’ll find classes, interfaces, structures and other .NET elements. Layers may occasionally span across tiers. For instance, we could find at both margins, server-side and client-side, some domain logic layer. It’s not necessarily that the client-side only contains presentation logic, especially if we want to allow some minimal level of offline capability. You may find other examples in your distributed applications.
All this organization of responsibilities pay off when new end-user functionality (i.e. use cases) needs to be added: it’s easier to determine whether new UI components must be developed, whether the data schema must be updated, new domain logic must be added, etc). It’s also easier to assign the resulting components to be created or recoded to different matter experts, in a way similar than the way graphic designers prototype UI components whose behaviors are coded, asynchronously by software developers. And last but not least, when organized this way, applications are more easy to be tested, as we could test the domain logic without having to set a database for data retrieval, and so forth.
Depending on your experience, a blueprint like this one is possibly not new for you. Whether that is the case or not, if you want to get more details on implementations aspects, I strongly suggest you to take a look to the guide published by Patterns & Practices on Application Architecture in January 2009. For the moment, let’s just say a couple of more things:
This model completes with some cross-cutting concerns. Those are aspects that will be present at any level (tier, layer, etc.) For instance, we cannot restrict Security constraints to a lost, final layer in a back-end tier because that way any single request must traverse the whole architecture to confirm that the user was not, actually, authorized to perform certain task. We are certainly applying security measures in the UI when we avoid to show the password that is being typed. We are also applying security measures in the data-access layer when we “purify” input parameters prior to call a stored procedure. We still apply security measures when we confirm, at any tier, that a sensitive request is coming from a trusted source that is also authorized for that kind of operations, and so on.
Like security, there are several other cross-cutting concerns to care about. Performance, fault-tolerance, manageability, health checking, etc., are just some few examples of those.
The other thing not shown in Fig. 1 is related with the development process. While the center of gravity won’t move from the development phase, it’s not bad to consider other stakeholders in the value chain and our relationship with them. How do we make components that are easy to test in an automated, repeatable way; how do we design our low-level libraries to maximize reusability while decreasing the complexity of the components that will use those; how do we estimate timescales; etc. The process is as important as the outcome that is expected as a result of it because brings predictability to the rest of stakeholders (particularly users and sponsors like the IT management or other non-IT managers).
In that sense, there exist tools that help manage the overall application lifecycle process, while enabling different stakeholders perform their core activities along the different lifecycle instances.
In this post, we have surfaced a blueprint that it has been for a while a comprehensive base for professional development. The way it was presented is a least common denominator as you’ll find variations in real-world implementations (either in the way layers were assigned to tiers, or how tiers were chosen, etc.)
This common denominator set a ground in which the content plan for the magazine (monthly themes, column lineup, etc.) will be stood up.