Front-end architecture: Facade Patterns and restricting libraries
6 months ago
Front-end projects are growing larger and larger. Today almost every new application is created in browsers with JavaScript technologies. Unfortunately, good architecture and well structured code were always considered less important in front-end projects. As a result, creating an application without following good practices and restrictions can lead to significant technical debt, which makes it difficult or impossible to extend the project in the long run.
Not implementing an appropriate structure can cost a lot in terms of time and money. Therefore, starting blindly on development work and prioritising time over quality might not always be the best approach.
In this article, I'd like to talk about using a Facade Pattern [2] because this is one of the best and easiest ways of simplifying most front-end projects. What is a Facade Pattern? In short, it's a way of reducing the complexity of an external dependency down to only the elements that are required in our current code base. Most examples refer to using this approach when creating interfaces, but it’s also possible to use this approach when working with React Components.
What does a project look like when we don’t take care of the front-end architecture from the beginning? It is easy to extend simple applications or proofs of concept by just adding more functionalities. In these cases, one small feature is usually added to an application one at a time over a period of years. This process can lead to unmaintainable projects or what is sometimes called a “Spaghetti Monster”. Unfortunately, this is the result of a naive approach that is based on little or no planning. Being in this position can be tough. It’s the result of just quickly adding new features one after the other. When the speed of delivery matters most, there is little time for overall improvements. This behaviour can lead to the project having more and more technical debt. Unfortunately, technical debt doesn't stay hidden in the background forever, but shows itself in increasingly slower delivery times and constant regressions that then result in almost infinite maintenance bug-repair loops.
Example 1. No real architecture or restrictions
Example no. 1 above shows how a project can look when you don't follow any good practices or implement any restrictions.
Common mistakes made by developers:
- Inadvertently introducing multiple libraries (Material UI, Ant Design etc.) that do the same thing.
- Implementing components on the spot with large configurations.
Why should we reduce complexity by using a Facade Pattern? In front-end applications, it’s common to use external UI libraries like Ant Design to implement components, and its typical for this type of library to be generic. This makes sense because these libraries need to be able to meet most use cases that it will be applied to, whilst also making it possible for the programmer to customize certain elements, for example, styling.
The downside of using these pre-prepared solutions is that they can require a lot of configuration just to fit into our application. It’s not a mystery that applications can grow rapidly and, as a result, it will get harder and harder to maintain common views using similar components. And this is especially true when it comes to dealing with changes and bugs. I believe that small, one line differences in the configuration of similar components are the most common bugs that can eat into a developer's valuable time. Another disadavantage is readability because, if you have to go through the multiple configuration lines of similar components, then this can be a nightmare. The next issue can arise when updating the libraries because some configuration parameters can change and break our application, which then forces the developer to update every component where the breaking change occurred. All this leads to having a business code base that is too dependent on an external library. This adds risk to the continuing existence of the project and also to your ability to extend the project. In Software Architecture terminology, this phenomenon is commonly known as 'getting married to an external dependency', which is something that might later hit the project in negative terms [1]. You should therefore create your applications on solid foundations instead of foundations based on the 'latest thing', hype or poorly supported libraries. Try to rely only on solid technology, such as .Net and React.
Example 2. Architecture with a Facade Pattern restricted to a single library
Example no. 2 shows a simple example of facade pattern implementation. In this case, we first create a common implementation in a single, shared place for Ant Design Table and Form Components. These common components will hide the complex configuration for the external Ant Design Library. Most of the other functionality won’t even be used, but we do wish to have the same user experience for similar looking components in our application. Using these common components we can create individual instances of Tables and Forms in our application code base, but now we can do this in one place without pulling in a whole lot of complexity. Compare this approach to the architecture shown in example 1, where you have to change something like pagination in every Table in the application. What a nightmare that would be!
Why should we restrict the usage of external libraries? Introducing a whole new library just to make a single element in a project can lead to weird mixes. Instead, adding a new dependency should be part of a well-thought process. I find it common for developers to introduce another big library to the project just to implement some solution in order to avoid the task of first reviewing the existing tech stack for similar tools. Typically, developers take such action without consulting others, which is a bad practice. Every technical decision should be discussed with the development team that is working together on the same project. Why wouldn't you do that anyway? And there is nothing worse than having to deal with multiple tables or button components that come from different libraries, and then trying to make them work in a similar way for the user.
Conclusions
It's a fact that front-end technologies are growing faster and faster. Everyone is now used to working in browsers and wants to be able to use all applications inside a browser. Having a good, readable and well-structured front-end project is therefore a necessity these days. Prioritising time over quality is a poor practice that can lead to unmaintainable and unreadable projects. It’s important to plan and forecast future needs in order to be able to smoothly implement the next set of changes or extensions when this becomes necessary. Implementing a simple Facade Pattern and restricting ourselves to a single tech stack can be an easy way of improving the project for the future. I encourage you to research and use the correct patterns when needed. As a result, you can avoid unnecessary overheads that come from automatically generating redundant boilerplate code.
Sources:
[1] Robert C. Martin, Clean Architecture: A Craftsman’s Guide to Software Architecture and Design, 978-83-283-4225-5, Helion 2018
[2] Refactoring Guru, Structural Pattern Facade https://refactoring.guru/design-patterns/facade/