Single-page web applications damage businesses.
It’s all too easy to look at prime examples of single-page apps like Google Maps and think “we could build something like that!”
I’ve seen this often in my consulting work with product teams. They can struggle with single-page apps because they underestimated the investment of time, expertise and energy required to make them anywhere near as good as the Google Maps of this world.
Let’s look at how this can happen. Spoiler alert: it’s got very little to do with the technology and a lot to do with teams and people.
Assumed user benefits
Product teams are drawn to single-page apps in the first place because there are some implied or assumed universal benefits to users (and therefore to the bottom line of the business).
Curiously, we don’t often talk about the user benefits of SPAs, preferring to talk about features and characteristics instead.
I think are three broadly assumed user benefits of single-page apps:
- Improved user experience. We are providing application-like patterns of interaction comparable to native desktop or mobile apps, focusing on data and tasks rather than an arbitrary page and document model.
- Improved perceived performance. Instead of interrupting task flow with full page refreshes we can provide visual feedback, and allow users to continue other tasks in parallel.
- It’s still the web. We can take advantage of all the benefits of the web platform: universal access and device compatibility, no installation, deep linking, sharing, indexing, etc.
Single-page apps represent a shift of complexity to browser-based code. Not just away from the server, but in some cases away from browser-native features too. We’ve seen this before. They used to be called thick clients. In the latter days of Flash, they were Rich Internet Applications. Now, many people just refer to them as web apps.
5 mistakes to create a dysfunctional single-page app
Below are five common mistakes I’ve seen teams make when building a SPA-based product. Each of these are people or practice problems that we often interpret as pure technology problems.
Unfortunately, each mistake can lead to the next, compounding the overall situation.
Mistake 1: Under-estimate long-term development and maintenance costs
Many teams underestimate the time and cost necessary to make a high-quality single-page app.
There are a lot of conspiring reasons for this.
Framework marketing focuses on the early developer experience
Framework marketing and discussion tends to focus on the ease of early development work, rather than on long-term maintenance. How much of the framework marketing makes claims of helping you to write code that’s easy to refactor? Not much. Likewise, educational resources around refactoring are rare compared to the army of introductory tutorials.
Low visibility of the true maintenance costs
Incremental improvement work is de-prioritised
In small product companies, UI product work is often expected to go at a break-neck pace. Continual improvement, refactoring and gradual long-term migration work can be seen as an unnecessary tax on feature velocity. The long-term result can easily be utter seizure due to technical and product debt.
Mistake 2: Use the single-page app approach unilaterally
This mistake reflects the most common argument against using the single-page app approach. It’s not the right approach to take in many circumstances.
When we start a project, many development teams make a single default choice of technical approach to cover all anticipated functionality. This usually means that your framework of choice absorbs everything, irrespective of user needs. “At BobsWidgets we use React!” screams the developer job advert.
This pre-emptive decision-making can be risky. Using the SPA pattern for everything can be overkill. After all, your typical business app is a Create-Read-Update-Destroy (CRUD) affair – possibly with one or two key features that demand a genuinely dynamic, data-driven UI. Mapping and real-time data visualisation are obvious examples.
We ask “What framework should we use for this whole app?” for new products up front, when we don’t even understand what we’re building yet. It’s far less wasteful to ask “What technical approach best supports this user need?” on a case-by-case basis as we learn more about those user needs during incremental product design and development.
This is just one example of a collective bias towards focusing on work inputs (the tools we use and the code we write) over their outcomes (the value our product brings to users and customers).
Mistake 3: Under-invest in front end capability
Complexity in web apps has shifted from back end to front end in the last ten years. Or, more accurately, we’re attempting to offer more capability, which results in more complexity overall. The front end is taking on most of this new complexity.
The balance in product team capabilities has not always shifted in line with this. Perhaps attitudes and habits are slower to change than technology adoption.
We’ve also seen the rise of the full-stack developer role in recent years. This is the industry’s collective attempt to deal with this shift in complexity as cheaply as possible, by forcing these skills to become a commodity. While individuals with genuinely incredible full-stack expertise do exist, they are rare, and not easily accessible to most companies.
The industry hypothesis that the full-stack developer represents is that software development expertise is portable from back end to front end without the need for a lot of expensive re-training. The same set of principles apply. This is true to some extent, but does not magically apply to knowledge of the web as a medium and platform. The transferability of skills is partial at best.
Here is one of the many jokes about full-stack developers:
These jokes are a little unfair on individuals, who are just trying to create a rewarding career for themselves. (There’s also a lot of bad and inconsistent advice out there on how to do this, by the way.)
For me, the full-stack developer mythos distracts from the need to think about the team as the unit of expertise.
In reality, everyone has qualitatively different capabilities and potential. Reducing capability to front end vs back end is over-simplistic, as is lumping a very broad set of skills into the full-stack developer role. It’s symptomatic of treating individuals as commoditised resources.
Shifting an existing product team’s capabilities more toward the front end to match the shift in system complexity requires a considered combination of training, coaching and recruitment. In other words: investment.
Unfortunately, this investment rarely happens intentionally, by the organisation that needs it, at the team level. Instead, teams are typically expected to learn on the hoof, sometimes at their own expense and in their own time.
Even worse, front end work is often given as an isolated piece of work to an inexperienced developer or intern to figure out by themselves without much in the way of mentoring or training. Learning on the job, in the W. Edward Deming sense, is fine. But leaving someone inexperienced to do it without guidance doesn’t count.
Underlying much of this is the persistent belief that front end development is relatively easy. As an opinion, it is stated overtly less often now, but its impact can still be seen in the way that teams behave and are managed.
Mistake 4: Use naïve dev practices
Under-investing in front end skills has knock-on effects.
Poor development practices reinforce each other:
- Poor or no test coverage, results in…
- Highly-coupled code, that encourages…
- Over-engineered solutions, that leads to…
- Big monolithic balls of mud, that forces us to deliver…
- Giant monolithic asset bundles
All of this makes it unlikely that we’ll deliver on those assumed user benefits we talked about earlier.
Mistake 5: Surf the waves of framework hype
Once we find ourselves with a poorly-executed single-page app (using our simple four-step plan!), we naturally want to do something about it. This is a very dangerous situation. It’s here where we can do serious compounding damage to the business.
Our team’s inability to move the product forward at speed; the redesign of that core piece of functionality that took six months instead of six weeks; those two developers that left the company out of frustration; the poor UX and performance. These are easily blamed on the technology we chose a couple of years ago. (Or that someone else chose a couple of years ago.)
So, we look at the alternatives.
I’m going to make a questionable argument in favour of this using The Gartner Hype Cycle. This infamous chart plots the visibility of a technology over time.
Could it be that product teams complain about their web app about here…
… just as an alternative tool is rising in popularity?
In extreme cases we can end up in a situation like the one below, as various attempts to rewrite a whole app or significant parts of it are undertaken, leaving a trail of frameworks and libraries throughout the code.
This is another way of illustrating the developer experience bait-and-switch, as described robustly by Alex Russell.
I may have been responsible for allowing something like this to happen in a rapidly growing product myself. I apologise unreservedly to anyone I’ve ever worked with who has had to deal with this. But I wouldn’t be the only one, by a long shot.
But there is still plenty of churn around other application capabilities like state management, handling of CSS and the use of platform native capabilities. Change is constant, but inconsistent.
So, what’s the solution, Mr. Grumpy?
This article is far too negative and long enough thank you, so I’ll be looking at approaches to getting some way out of this mire in a future post.
Few teams will have encountered all five of the problems above. They can surface at different times in a product’s lifecycle.
As pointed out at the start, the common thread of the problems I’ve identified above is not technology in itself, but people. We focus far too much on technology as the solution to problems that are not based in technology.
We don’t talk enough about team structure, dynamics, skills and capabilities, about the cost of writing and maintaining multi-platform asynchronous browser-based software, and about healthy and sustainable long-term software development practices.
That should give you some clues as to how product teams can start to address the situation.