Layering Software Design

This is a quick-ish article about layering software design, and how to achieve layering in ways which are consistent and useful for the maintainability of your source code. I have seen it done badly I have also seen it done very well, but I thought it was worth covering. Throughout my career I have seen lots of software designs, great. Flow charts and diagrammatic representations of software designs. At this point I think “Great, I can follow this!” – and then I see the code, and the layering is impossible to decipher, and is seemingly only existent in the designer/architect’s head.

Consequently, I thought I would do a quick article on layering your software. I appreciate there are lots of articles around the SOLID principles, and various other related topics, and I urge you to read about spaghetti code and lasagne before reading this article.

This article is aimed at people who have a decent understanding of Object Oriented Programming, but who are in the process of learning about software design and separation of concerns. Alternatively, it may also help those who have large, unorganised code bases to manage, or large projects to design and build.

Quick notice: I’ll keep code samples to a minimum and as concise as possible for the purposes of readability, but said code will be in PHP

The Problem

What we are trying to do, when creating layers of software, is create manageable code, the concerns of which are as separated as possible. Often we are trying to achieve this by defining parts of our application, usually referred to as layers.

Then a professional of some description (software engineer, web developer, systems architect, etc) creates a drawing of the different components to the software and how they should interact with one another. “Excellent!” they exclaim, and off the various developers go to work on their layers. Unless you’re in a strict environment quite often the developers work in isolation, and agree on integration points (or these are predetermined, or predefined).

In my experience, what normally happens at this point is that we have a load of principles designed, and off the team go to carry out the development on the product itself begins. Let’s make the assumption we’re talking about a content management system.

Then the code happens, bug fixes, amendments, changes in specification, and then, eventually… The product is finished! And by this point the design and architecture are forgotten, balls! Nowhere to be seen throughout the codebase.

The Solution

If you’re already in this situation you have a slightly harder job, because you need to understand the intended layering first, and then where you need to get it to. In its simplest form, given these kinds of problems I would be creating layers as they’re required (ones that do not exist) or modifying all code within them, and its usages, to fit into layering practice.

An Example

Let us say that we have a CMS, which currently has a whole bunch of mail() (for non PHP-readers the mail function is documented here), PHP function calls; and we need to enhance the emailing functionality. The specification at the time of creation:

  • CMS must be able to send emails at appropriate times (fulfilled, it does send emails when it needs to)

The new specification:

  • CMS must be able to send emails at appropriate times (fulfilled)
  • We must take new GDPR regulations into account and only send emails to the users which they have approved
  • We must categorise emails at high or medium priority, medium priority messages must not be sent outside of 8pm and 7am, whereas high priority messages must be sent immediately

Likely future specification:

  • In the same instances, we may wish, based on user requirement, to send SMS instead

The way I would look to solve this problem:

  1. Create a Notifications layer through which all systems notifications are sent (end user code sample below), this notification will understand context, so that decisions can be made with regards to type of delivery
  2. Find every instance of mail() in the codebase, and replace it to use my new notifications layer

Userland Code Example

// Create an instance of the notification
$notification = new MessageReceivedNotification($currentUser);

// Set the message which the user has received
$notification->setMessage($theMessage);

// I would normally chain this on, but have not done so for the purposes of readability for those who do not write PHP 
$notification->send();

The Outcome

Now I have a layer in place for all notifications, the next thing to do is make sure that all developers working on the system are aware of this layer, that it is well documented, and everybody knows not to use the mail() function. All notifications now go through the new layer, and injecting new functionality into that section of functionality is a much easier process.

The Prevention

Ideally, you don’t want to end up in that situation in the first place. What you need for this is not only a design of how the layering works, but also a set of rules or standards which ensure that the layering is used in a way which prevents this issue in the first place.

We’ll take the example of a CMS again, with some examples of layers which are required:

  • Notification Service
  • Data Layer
  • Permissions Layer
  • Controllers

And here are some ways that you might introduce that layering, so that functionality can be easily implemented throughout your design.

Interface Facading

Particularly on the Permissions Layer you might want to use the facade design pattern to give a simple interface to interact with the Permissions Layer, this could be further facaded to use helper functions (code samples below). This means that all functionality relying on the facaded layer only ever need to worry about the facade, with no knowledge of how it works, but also that in order to check the permission status you will always use the layer, preventing the problem described above. You may decide that, for the purpose of this shared functionality, you want to make this layer interface through a singleton, particularly if the class itself is doing very little besides providing anaemic functionality to other classes.

class PermissionChecker
{
    public function checkPermission(string $permissionName) : bool
    {
        //  Return true/false based on whether or not this user can carry out this permission
    }
}

function checkPermission(string $permissionName) : bool
{
    $checker = new PermissionChecker();
    return $checker->checkPermission(string $permissionName);
}

Inheritance

Another common way of managing this layering is to ensure that all appropriate functionality extends a base class (inheritance), which encapsulates all the layers shared functionality, again this could facade through to a library of classes. A good example of this would be a Notification Service or Data Layer.

abstract class Model
{
    public static function find($recordId)
    {
        // At this point I am going to fetch a record based on its ID, I can choose to implement caching or other functionality here
    }
}

class Post extends Model
{
    // This class specifically represents the post records, if we're assuming the active record design pattern
}

Data layering is the most obvious to introduce, particularly as most frameworks will have already included this. The important part of the layering process is to understand what else needs to be layered, and consequently how this should occur.

How do I know what I need to layer?

This is impossible to answer really, as you could be programming a blog, or the software behind the next space shuttle launch! The following are not hard and fast rules, but a guideline which you could choose to follow. I personally would consider layering if:

Don’t forget, layers can exist within layers. Your data layer may have layers for caching and database transactions, for example.

  1. When the functionality is reusable (like models)
  2. When the functionality could require modification, which would need to affect everything within its remit (like notifications and adding user preference functionality)
  3. When the functionality is grouped, and might need modification or replacement later (like cart calculations functionality in a commerce system)

How should I invoke my layering?

That very much depends on your use case, personally I tend to consider it like this:

  1. I use inheritance when each instance makes sense to be its own entity (such as a notification, or a record in the model)
  2. I use facading when I am hiding a library of functionality (access permissions works in this case, as you may have a number of functionalities in here, such as super-admin-detection, permissions grid management, IP whitelisting, and infinite possibilities in terms of security management)

Hard Fast Rules (which don’t exist)

Of course, hard fast rules do not exist and every use case has the potential to need to not follow these guides. However, I follow these rules to layer my code properly and ensure it is truly layered/modular.

  1. Do not directly interface with any class which is part of the package/library, that is not the interface or Facade itself
  2. If working within a modular system, never use code which belongs to one module within another (unless it is predefined that this module is dependent on the other)
  3. Particularly within modular systems, having code in separate repositories and IDE projects can help ensure you don’t accidentally use code which is within another module
  4. The moment you think “Gosh, I hope I don’t have to change this later!” you either need to reconsider your base design, or you need to introduce layering there
  5. Follow DRY (don’t repeat yourself) – if you’re copy and pasting code you could almost definitely do with encapsulation, at the very least, but potentially your code should be in its own layer with an interface to allow your modification

Summarised Points to Take Away

  1. If you draw a design, and you have a layer, ensure some kind of physical representation (base class, interface, facade, etc) of that layer exists
  2. Ensure if you’re using layers they’re well documented, and everybody knows they need to use your layer, and how
  3. Layers are important for injecting new functionality later, and preventing the duplication of code

Thank you for reading!

About Facading and Dependency Injection

Good evening everyone.

I’ve been meaning to write a post about this for a little while, it’s a common discussion point within developers working on enterprise level software. The argument regarding dependency injection vs. facades; how they’re applied and how they relate to most software systems you work with.

The first point I would like to make on this particular topic is that they are both useful, they both have their place.

For those of you who are not exactly aware of what these concepts are I have broken it down a little bit below; but if you’re not comfortable or familiar with the topic it probably is worth doing some research on before you make your mind up.

In essence, dependency injection is where you declare your class usages in a single place as a dependency, those dependencies are injected into where they are used. The concept behind this is that should you wish to swap out your dependency it should be easy. Take the following example;

I have a class named PermissionChecker. This class is used throughout many Controllers in an MVC framework. Whenever I want to check if someone has a permission I simply call upon functionality within the permission checker, which returns me a true or false.

The basic problem here is when I want to change the PermissionChecker, which contains all of my permission-based logic, it is painful, because I have to go through and replace or remove every instance of the PermissionChecker and hope that it doesn’t break anything, and I test everything heavily.

This is where Dependency Injection (DI) comes in. I create an instance of my PermissionChecker (PC) within the DI container. There are various open source DI solutions out there from Pimple to the DependencyInjector by Symfony. Anyway, the long and short of it is that the declaration of the usage of PC is in a single place, so should I wish to change it for SupremePermissionChecker (SPC) then it is easy and done in a single place, assuming the interfaces through which it is accessed remain the same.

This is the perfect solution to an age old problem!

But beware! There is an issue with DI, in my experience, and that is that either you become so dependent on it that it becomes difficult to utilise functionality and you end up writing lots of code which, in practicality, does very little. Or potentially you can end up over injecting, some parts of your system will be tightly coupled to one another by design, the issue with DI here simply compounds this issue, because the tightly coupling in a lot of days makes the DI redundant; as you couldn’t swap out the dependency even if you wanted to.

Now please don’t, for a second, think that I am slating dependency injection, because I’m really not. I think it is a very useful tool, it’s not my tool of choice but it does have a lot of advantages.

Additionally; don’t think the next thing I am going to mention is mutually exclusive to Dependency Injection either, they can be used in tandem without any issues.

So a facade is where you create a class which hides more complex logic behind it. Taking the same example I might have a PermissionChecker class which facades other functionality, for example fetching a user, fetching permission records which it can cross reference against the permission we are checking into.

In essence a facade is a way of abstracting your functionality a layer further. You have your system which utilises your facade, and your facade utilises whatever it needs to.

The reason I prefer this methodology, personally, is because you end up with all of your facades talking to one another. Which makes your Controllers very readable as you end up with something not dissimilar to:

if ( $permissionChecker->hasPermission(‘make-payment’) ){

$paymentThing->makePayment( $account, $sortCode );

}

Which I feel is very “English” in that it’s quite easy to read it and understand what’s going on. Additionally the advantage, for me, is that if Developer A (DA) and Developer B (DB) are both working on functionality within the same version it is easy. DA can be modifying whatever he wants in PC whilst DB can be happily working away on changing the payment gateway PaymentThing is using, as long as the interfaces remain the same then it’s all good.

To add to the mix, remember where I said earlier the two weren’t mutually exclusive? PaymentThing and PermissionChecker could well have both been dependency injected into their current context, so they could be switched out.

My only real question there is: why? If my functionality is all hidden behind facades, which provide easy interfaces to use, if ever I want to change them or do anything with them, I do it behind the facade and I’m fine. With that in mind, does Dependency Injection become a bit overkill?

Both of these concepts, as with all concepts, methodologies and rules within web development, are designed to make maintaining my software easier, rather than having invisible dependencies and entangled tight coupling which is impossible to defuse. That’s a developer’s nightmare when someone says “can’t we just take the payment functionality from X project and put it into Y project?”.

I think we have to sometimes be careful in web development and programming in general that we’re not making more work for ourselves. If facades are working for the separation of concerns, does it matter if the dependencies are scattered through the code, because somewhere that once needed to make a payment will always need to make a payment, and if that requirement changes, the code will need to change anyway, so we cut out the bit that says make a payment. We don’t have to remove the dependency or do anything else.

When I want to include payments into a new set of functionality on the site all I have to do is utilise the use statement to bring in the Facade, which handles everything else, and use the functionality contained therein.

Maybe I am missing the point and the value. And I would rather have Dependency Injection than nothing, but I would rather have an easy-to-utilise set of Facades, than have to Dependency Inject everything I want to use, and remember to rip it out when I don’t.

I’d love to hear other developers’ opinions on this one though, as it is something of a bone of contention in the community.

Take care all!
Johno