top of page
Application Layers

When I talk about application layers I am talking about how you separate your solution into multiple projects. These individual projects references one another such that the libraries that they expose can be accessed by the projects that need them. Typically we do this to segregate out functionality of one kind or another, i.e., the data access, business, and UI layers. Or, in the case of preferring composition over inheritance, we use interfaces to achieve similar goals.

Regardless of what architectural pattern you use to segregate your code your ultimate goal is to write cleaner, more manageable, code that reduces dependencies and the tight coupling of your code. Unfortunately, if you just take off writing code without thinking and re-thinking your approach you are likely to fall into any of a number of traps that will make your code brittle and difficult to modify. How you layer your code is only one of these, another is your approach to dependencies in the code you write.

 

These days there is a big push away from coding to an implementation. In coding to an implementation, one object "news" another to get a desired capability, or acquires a desired functionality through inheritance, or simply codes it out on the spot. Rather than doing any of these bloat worthy, inflexible, or inefficient things, today we often code to an interface where appropriate. For example, when we come across a need for expandable functionality like printing to the screen, and to a printer, and perhaps later to a file, we can create objects to carry out each of these things and link them using a common interface, avoiding many of the previously mentioned coding pitfalls.

 

In the above mentioned scenario, each of these "printing" tasks or objects can implement a "print" method declared in a common interface. It is through each of these objects' distinct implementation of the interface that they provide the required printing functionality. More germane to  the conversation at hand however, is that it is their common interface that allows any of the printing objects to be passed into some other method (like doPrint(IPrint printTarget) for printing--finding a common "print" method across all implementers of the interface.

 

By approaching the situation in this way we avoid the lack of flexibility in inheritance, avoid coupling, and make the code more modular and easy to maintain. To add another print target, it is as simple as creating a new object with the required functionality with a method called "print" and implementing the IPrint interface.

The previously mentioned move away from coding to an implementation is what is called a S-O-L-I-D principal and is also part of the Onion Architecture. The Onion Architecture combines a way to both strategically layer and code your application in such a way the you minimize dependencies that will make your code difficult to modify down the road.

bottom of page