Ever see a company going out of business because it couldn't afford a complete redesign of a big application?
Ever wanted to switch a large application to a new technology stack in short, well defined steps?
Ever struggled understanding or changing an existing web application because its structure is complicated or not well defined at all?
Ever had trouble because the scalability of a web application is too limited as site traffic grows?
I have faced all these problems way too many times already. That is why I think its time to not change so much the tools (as this has never helped) but the way they are used.
In this series of posts I would like to introduce an architectural pattern for web applications that is largely independent of any concrete implementation. I will be looking for an implementation for the Java world in a future post.
This work is by no means complete but an ongoing task. So I am very thankful for any kind of feedback.
On one hand applications in general have the tendency to lose structure over time. Its just too nice and easy to use a little bit of nice functionality at one end of the application in a totally different part without factoring it out into a clean horizontal component. Especially if there isn't even a mechanism for such components established at all. So this feels like an endless fight against natural forces, like fighting against gravity and at the and you always have a 'big ball of mud' without any decoupling at all.
On the other hand the web itself is very loosely coupled and its technologies support decoupling very well. It is even possible to reuse parts of it that were never specially made for reusage. I will try to use the principles that make the web so successful to decouple the various parts of a typical web application.
Vertical components are the ones that are visible to the user. They carry the user perceived functionality. A booking system is a vertical component and a user management system is another one.
Here we try to find a way to split the overall web application into much smaller components that can be implemented and maintained independently from each other.
Since HTTP requests are fully independent of each other this is the nice part. Theoretically, every HTTP request could be handled by a totally different technology stack.
All programming language of importance (on servers) can be used to implement a web application. Even Fortran could be used for this.
Of course it makes sense to keep some requests together. The implementation for handling the HTTP methods (GET, POST, PUT, DELETE or HEAD) for a URL should all be in the same component.
Another case for multiple requests for a single component are form wizards (forms that have to be completed in multiple steps with already collected data usually transfered in hidden fields from step to step).
It certainly wouldn't make sense to rip these pages into different components. Later on, an implementation could easily put all steps on a single page.
Anything else should usually be a new vertical component. The smaller they are the more useful they will be!
The session is traditionally the rope that web application developers use to hang themself.
Of course some session data is necessary but it can be (almost) always be reduced to a couple of IDs. If you think performance will go down than please use a cache but never misuse the session as a cache.
A large session will severely damage scalability and all 'components' that use the session are coupled together. This is usually the fastest way towards a big ball of mud. It doesn't look like a big deal first but real independence is lost.
Instead it makes sense to reduce the session to a few IDs and to store these in a portable format (e.g. JSON) on the client side. A cookie seems the best solution for now but new standards for HTML and HTTP will bring better solutions.
The data should be signed using a standardized signature algorithm and information, the user must not see, can be encrypted using a standardized algorithm.
All vertical components have to use the same algorithms and private key of course.
This makes it possible to really decouple the vertical components from each other.
Authorization and User Data
Authentication, authorization and user data is needed by almost every vertical component. Because of this it makes sense to put it into a component of its own.
Next to a RESTful web service for retrieving authentication, authorization and user data, a user interface for changing that data makes sense. So this component is in fact a vertical and a horizontal component at the same time. The user interface could contain the following parts:
- Login page.
- A page where every user can see and edit his own data.
- Pages for managing authorization data for administrators.
- Pages for managing user data for administrators.
Other services needed by many vertical components can be extracted into own components in a similar way.
One such service needed by every vertical component is the umbrella application. It usually contains the layout for the whole application including header, footer and navigation bar.
The navigation bar can be configured according to the available vertical components.
The vertical components are called by the umbrella application and don't return full HTML pages but just the part for that component (usually the real body part plus additional header stuff).
This makes it possible to reuse a vertical component in a different context.
The umbrella application is a great place for global CSS stuff too. Different umbrella applications can be used for different user groups:
- An umbrella application offering all vertical components without ads and with a simple style could be used for internal users.
- An umbrella application offering only the public components with ads and special styling could be used for the public.
- Additional umbrella applications could exist for logged in users, paying customers, partner companies, ...
- Umbrella applications could be made for normal browsers, smartphones, ...
So this separation alone gives a lot of freedom. But it costs a bit of performance because for every request there has to be made a second one for the right vertical component. This could be optimized if necessary by constructing the 'umbrella content' while waiting for the content of the vertical component.
Vertical decoupling brings the opportunity to exchange the whole technology stack including programming language, runtime environment, operating system or whatever.
Since the vertical components are very small it is easy to write one using virtually any technology stack. So a migration can be done in nice little steps without the customer noticing it.
Who knows what technology stack we would like to use in ten years? Honestly I have never seen a ten year old application that I wouldn't want to rewrite as soon as possible.
Ten years might sound like a long time but most applications that aren't specially made for a special time frame or event will have to last much longer than ten years.
Many should last virtually forever but have to be rewritten in a big redesign project that often lasts so long that the whole application or company behind it struggles to survive.
Furthermore vertical decoupling allows the independent implementation of parts of the web application and endless growth of it because nobody has to understand all components before he can start with a new functionality.
Last but not least the independence of each request is the basis for unlimited scalability.
In a future post I will describe how horizontal decoupling can be used to promote the DRY (Don't Repeat Yourself) principle and push the benefits found already to the next level.