Enterprise Software Patterns: Part 1

Jacob Taylor
CodeX
Published in
6 min readApr 23, 2021
Photo by heylagostechie on Unsplash

There is so much nuance in the world of software these days. If you’re a new developer, it can be overwhelming to understand how to fit things together when you get your first job. Especially with so many people going through boot camps and other rapid training courses, some of the most important things are left out. In this series, we will explore some of the most basic & common enterprise patterns and practices in an effort to make them approachable for software developers, new and old. In this first edition, we will explore what an N-Tier architecture is and what components it might be composed of. In future articles, we will break some of those components down and see how to best use them.

What is N-Tier Archicture?

N-Tier Architecture, or more commonly just 3-tier architecture, is one of the most common software design patterns out there. It is composed of, you guessed it, typically 3 tiers: presentation, business, and data. In addition to those layers, you will often find cross-cutting sections that don’t count against the number of layers since they are shared by one or more layers. As the name implies, these systems can often have more than the 3 common layers, although in general the additional layers are just various forms of advanced business logic. We will break these down further as we go, but for starters, let’s discuss what cross-cutting layers typically consist of.

Cross-Cutting? More Like Confusing!

Cross-cutting layers can sometimes be confusing, especially when first starting out. Rest assured, however, they aren’t that intimidating and really exist to make life easier (well, at least usually). Typical examples of cross-cutting type layers are:

  • Utility projects
  • Shared “core” functionality
  • DTOs (Data Transfer Objects) & Other Models
  • Services*

*Services are almost always business-logic focused and don’t exist here, but in some cases might align more closely with a cross-cutting style layer.

Now that we’ve identified what the layers might be, we’ll explore what each of the specific items above might consist of.

Utility & shared “core” layers are often quite similar to each other, depending on the application so we’ll discuss them together. These types of projects are generally where you’ll want to put all your generic shared code including things like extension methods; common interfaces for things like logging, response factories, etc.; and other base-level code that might be accessed by multiple layers. You will generally find other system-wide abstractions in these kinds of layers.

Data Transfer Object & Model projects consist of simple objects, contracts and models and generally do not contain business logic (though this will vary based on your application and other design choices). Depending on your language of choice, you might hear these referred to as POCOs (plain-old C# objects) or POJOs (plain-old Java objects) as well. These types of classes will almost always get passed around between various layers to simplify things. As these DTOs start to specialize, sometimes they might be better off in others layers i.e. database entities might make more sense aligned closely with your data layer projects as opposed to a general purpose project.

Is It Pronounced Data or Data?

Starting from the bottom up, the data layer is the abstraction wrapped around your data source(s). Typically following a repository pattern (we’ll explore this in a future article), particularly if directly utilizing a database as the underlying data store, these project obfuscate any specific logic around how data is stored and retrieved in order to simplify your business logic. It’s a best practice to isolate data storage and retrieval logic from the rest of your application so that data stores can be swapped easily, as well as for general scalability & maintainability purposes. Depending on the system, a data layer might return a shared model or it might return a database entity directly. An entity in this case would generally map very closely, if not exactly, to the underlying data construct. These are particularly useful (and common) if the expected or desired data format is consistent across possible data sources.

Now you might be wondering too, if my data layer doesn’t directly interface with a database, what might it be doing? In an increasingly microservice-focused world, a data layer might simply be another service-style layer that interacts and aggregates data together for more specialized business logic needs by making API calls to other services. You might also find things like this if you are consuming a PaaS or Storage-as-a-Service offering such as Azure Blob Storage or AWS S3 or other similar technologies.

To recap, the focus of your data layer projects is really to abstract away and obfuscate and data store-specific logic from the rest of your application.

We’re In Business!

So now that we’ve got the data, what are we going to do with it? That’s where your business layers come into play. Business logic, also often called application or domain logic, is the bulk of most every application. This is where developers spend the most time because it is often the most complicated piece of any system, generally out of necessity. Let’s use a very simple example to illustrate: there is an API that allows you to provide an ID and a format string and, in response, it returns a customer’s formatted full name. In the database, each customer is stored separately, with all of their attributes stored separately i.e. CustomerFirstName, CustomerLastName, CustomerCity, etc. Here, the data layer would know how to retrieve this entity from the database based on the supplied ID. You might be asking “How do I get the API to return a customer’s full name if I’ve got these separate fields?” — this is where the application logic comes in. Your business layer understands how to consume the above Customer entity and how to convert the individual fields into a full name by concatenating the CustomerFirstName and CustomerLastName fields based on the supplied format. Granted, this is a contrived example, but it demonstrates what the role of the business layer is in the larger application.

Some of the other types of things you might find in a business layer include: services, factories, commands, queries, validators, managers, orchestrators and many more. Learn more about those here in the next article.

What’s Left to Present?

The data has been fetched and manipulated by the underlying layers, but now it needs to be shown somewhere, somehow. This is where the presentation layer(s) come into play. This is often where systems vary the most, and also where they get the most creative. You might be working with a microservice where the “presentation” is nothing more than API controllers and endpoints. Alternatively, you might be working with a single page application (SPA), a .NET MVC/Razor app, a desktop application, or a combination of all of the above. In particularly large (monolithic) applications, it is fairly common to see multiple projects in the application layer as these often host both an API and another UI-type project, even if they are deployed separately.

The complexity of projects in this layer often scales alongside the complexity of the business logic. As more rules exist within that layer, the UI or the API generally gets more complicated. However, if some of the concepts that we’ve explored in this article, alongside some future concepts, are followed — just because the UI is more complex, it doesn’t necessarily mean it is less scalable or maintainable in the long run.

What’s next?

Up next, we will dig into some of the concepts we’ve highlighted here as well as dig into other, more advanced topics.

Want to see something specific? Leave a comment!

--

--

Jacob Taylor
CodeX
Writer for

Passionate Agile leader. Innovative developer. Creative software architect.