Skip to main content Accessibility Feedback

Harmful complexity: using too little tooling for data-driven interactive UI

Last week, I wrote a series of articles on one of the two common types of harmful complexity I see in many client projects: using over-engineered tooling for mostly static content.

But there’s another, equally harmful type of complexity I see from time-to-time as well: using too little tooling for complex, data-driven interactive UI.

Let’s dig in!

The challenge with interactive UI

I recently worked with a consulting client who had a highly interactive UI.

They provide telecom services, and the services available to a potential customer vary based on where they live and whether they’re an individual consumer or a business.

A potential customer provides their address, and is then provided a variety of options they can choose from. Some options, like internet service, include optional upgrades to higher speeds, or bundles with other services.

Every step in the process creates a fork with a variety of different UI elements that may or may not be displayed.

  1. The user enters their address…
    • If service is available, show the options.
    • If it’s not, show a contact form for when it is.
  2. The user selects a service…
    • Display the included-by-default features, which vary by service.
    • Display a list of upgrades, if any.
    • Display the price for the selected service.
  3. The user selects upgrades
    • Update the UI to reflect that other mutually exclusive options aren’t chosen.
    • Update the price.
  4. The users selects an installation date
    • Show the available times for that date
    • Confirm contact details

As you can see, there are a lot of moving parts for what feels like a relatively simple transaction.

Traditional DOM manipulation can handle this… but it’s messy

Every step in this process is something that you could handle with traditional manual DOM manipulation.

  • Listen for form submissions and button clicks with the addEventListener() method.
  • Make API calls to get available services and scheduling dates with the fetch() method.
  • Render conditional UI elements with the innerHTML property, or createElement() and append(), or by showing and hiding visibility using the setAttribute() or removeAttribute() method and the [hidden] attribute.

But… when you combine them all together with a UI that changes dramatically based on a wide variety of conditions, it becomes much harder to manage, maintain, and reason about.

When I came into this project, you could tell it had started as a very simple UI that had grown over time, and the result was a tangled mess of DOM manipulation.

What worked when the project started had ballooned into lots of tech debt in a very short amount of time.

Updating the code was slow, painful, and costly. It was easy to make mistakes because of how many different parts affected each other.

State-based UI isn’t bad!

I complain about React a lot because it’s objectively bad software.

But state-based UI as an approach can be really useful for a particularly type of project… and this was one of them!

State-based UI is a fantastic tool when you have a UI that’s driven by data, and that data changes over time based on user interactions. It’s even better when the UI changes in subtle ways based on variances in the data.

For this client, we took some time to convert their existing code base over to state-based UI. The result was a smaller, faster code base that was easier to maintain and update.

We didn’t use React. We went with Preact for this one, because it’s smaller and faster with a similar API. But there are a lots of other excellent choices as well.

Tomorrow, I’ll share some of my favorite tools for managing complex UI like this.

And if you have a project that’s grown in complexity and could use some help wrangling it, I’ve got one consulting spot open for the start of 2024. I’d love to hear more about it!