Monolithic, consolidated applications are not bad. These are your Rails apps, your Django apps, etc. — the ones where your server sends back HTML and assets. You’ve faithfully followed the Model-View-Controller (MVC) pattern as best you can and your concerns are “separated.” This design principle is not passé. It just so happens that for a long time, it was your only option.
For some time now, there has been an alternative. An alternative. Keep calm and don’t trash your Django app just yet.
What is a Decoupled Application?
A decoupled application is one in which data is served from a REST or GraphQL API and consumed by a Single Page Application (SPA). They can live in a single codebase, or in two distinct ones (my preference). They can even be run on two entirely separate servers. You can even just plop your SPA into an S3 bucket and, with a bit of configuration, serve it directly from there. The defining feature of a decoupled application is the systemic separation of business logic from client-facing features. Your client-facing code is truly static, and your business logic never sees the light of day except through your API. Suddenly “front-end” and “back-end” can be meaningfully distinguished.
SPAs are rather trendy at the moment; however, I am here to argue that they are not simply the flavor of the week. If you’re crustily hanging on to your conviction that SPAs will go the way of other fossilized application models, you may wish to change your mindset. Here I’ll explain why you may wish to expand your toolset to include SPAs.
A tiny bit of background
It’s probably not valuable to try to pinpoint the technology that made single page applications possible, and therefore when the SPA became a thing. Some would say that Backbone.js was the first SPA library. Others might argue that the conception of the SPA began with the abstractions of jQuery. Leave those arguments to the bowels of reddit. The valuable bit of information exposed in the effort is that SPAs are, like nearly all software, an abstraction.
Decoupling is Abstraction
Abstraction is taking a complex task and turning it into a single, declarative action. We take for granted that 3 + 3 faithfully returns 6 in our python shell, but that’s only because + and 3 have been abstracted into declarative symbols. There’s something far more complicated going on underneath. But the power of abstraction is the very fact that we take that operation for granted. It allows us to perform far more complicated tasks than we ever could if we were swapping locations in memory for every action we took. It is somewhat counterintuitive to call the decoupling of an application an “abstraction.” Aren’t we creating more parts here? Is it really less complicated? “Yes” and “not necessarily,” respectively. The abstraction is this:
When I am building a SPA user interface, I can take for granted that the data will be there, serialized just the way I need it.
When I am modeling and performing CRUD on my data, I can take for granted that as long as I expose it, it will be consumed.
Another software design principle that can be applied here is “Separation of Concerns.”
This is what I mean by “focusing one’s attention upon some aspect:” it does not mean ignoring the other aspects, it is just doing justice to the fact that from this aspect’s point of view, the other is irrelevant. It is being one- and multiple-track minded simultaneously. — Edsger Dijkstra
The Model -View -Controller design principle seeks to decouple disparate logical aspects of an application, each of which is accessible to the other through some logical interface. But even under the best of circumstances, this paradigm doesn’t effectively address the separation of the business and data layers from the representation layer. If we structure our application according to MVC and religiously follow its strictures, we gain some of the benefits of separating business concerns. However, we often needlessly entangle the user interface with business logic, resulting in difficult to follow, unmaintainable HTML and Javascript. If your goal is to produce a product with a beautiful, interactive and intuitive UI, you must first overcome this hurdle. When we decouple an application, our business logic can be irrelevant to our UI, and our UI irrelevant to our business logic. Decoupling abstracts one side from the other.
OK, got it. MVC is bad and consolidated applications are the worst.
Nope! We’re not ready to retire the paradigm yet. It’s still got a place in software design. It’s hard to beat the speed and ease of use of a well built MVC framework like Rails or Django. As long as the assumptions their authors have made about your needs are correct, you’re in the fast-lane, baby!
Decoupling also comes with:
- Exposing your business logic and data via an API: First of all, if a mobile app is part of the equation, this is required. Otherwise, exposing features of your application for integration with other products can significantly increase your products visibility.
- Allows for easier distribution of services: Is that one endpoint doing way more work than all the rest? Is it consistently jamming up your server? Split it off into a separate service, or utilize cloud computing. The world is your oyster.
- Lets you use some great modern tools like React, Vue, GraphQL: Some of this tech is just beautiful. If you haven’t worked with GraphQL yet, check it out — you’re going to love it.
Before you build another monolithic, consolidated application, consider:
- Should your data modeling drive your client-facing product? Usually, no.
- Should the challenges you face in implementing your business logic change the way you approach your client-facing product? Again, I don’t think so.
- Is every member of your team equally comfortable in both the front and back end? If your dev team isn’t full of unicorn developers (or even if it is!), you may see benefits from letting your front-end devs be front-end devs, and your back-end devs be back-end devs.
Abstraction. What is it good for?
I have a daughter. She is a toddler, and to her the world is glorious and new. She is also beginning to see that the world can be slightly terrifying in its immensity. When she is confronted with something that feels too big for her, I like to show her that it and everything else is made up of things she already knows how to do. Like the great Kǒng Fūzǐ (Confucius — his name was Kǒng Fūzǐ, which means Master Kong. Imperialism, am I right?) said:
“the man who moves a mountain begins by carrying away small stones”
Abstraction is how any of us performs complex tasks. A concert pianist does not individually interpret notes on a page, remember where to put each finger on each hand for every moment of a piece, consider how much pedal to use and when, phrase, balance, and then also remember to breathe and not fall off the bench. The master has abstracted each of these elements away such that at the time of performance, there is only one thing. It is the music.
The greatest value of decoupling is abstraction. Like the master concert pianist, a developer’s finest work is done when there is one thing. When complexity is abstracted away, we can focus our efforts on greater things. On the front-end that might be a highly interactive, complex UI, or just a fancy design with lots of animations. On the back-end that might be implementing faceted Elasticsearch or utilizing Python threading in your Django API.
When I need to add a model to my REST API, there is only one thing — the data. When I need to create a new widget for handling a new feature, there is only one thing — the user. Whether your team has dedicated front-end developers or not, there is great value in the separation of domains provided by a decoupled application.