Dumont Digital logo

Separation of concerns

Published

Separation of concerns, a key principle in computer science, is often misunderstood, resulting in software partitioned along inefficient and occasionally arbitrary lines.

This confusion can be seen in a type of recurring comment, a meme, in online discourse. The comment usually goes something like this:

  1. HTML, CSS, and JS, being distinct languages, represent separate concerns.
  2. Modern frameworks are bad because they violate this rule.

Before we delve into the discussion, it’s worth noting that the points raised here specifically apply to web application development.

If you’re not building a highly interactive application in a component-driven way, your concerns might differ from the ones outlined here.

In this context, are the concerns of Structure, Style, and Interactivity truly distinct?

Components in other languages

If someone were to design a language today with the sole purpose of building interactive applications, would they divide it into three? Would they need one language to construct the structure of a component, another to style it, and yet another to define its behavior?

It’s doubtful that anyone would agree that this is a good idea.

Yet, we see individuals insisting that this is how web development should be approached, seemingly oblivious to the historical context in which these technologies emerged.

The web is a combination of HTML, CSS, and JavaScript not because these technologies are the optimal UI development paradigm, but because the web evolved from a read-only document sharing system that later gained styling and interactive capabilities.

Consider SwiftUI, a relatively recent approach to building user interfaces, as an example. Here’s some code from their documentation:

Button(/* */) {
  Label("Refill Water", systemImage: "arrow.clockwise")
    .foregroundStyle(.secondary)
    .frame(maxWidth: .infinity)
    .padding(.vertical, 8)
    .padding(.horizontal, 12)
    .background(.quaternary, in: .containerRelative)
}

You’ll notice that the concept of separating styling from the component structure is absent here.

Now, I’m not pointing to SwiftUI as the definitive source for UI development. My experience indicates that this approach is more efficient than separating structure and style.

I’ve seen monolithic CSS files that span thousands of lines, and methodologies like BEM to try to control the chaos, but nothing is as simple and elegant as component-scoped styles.

Styling as a specific concern

Different frameworks handle styling in their own ways, but most embrace the concept of component encapsulation.

Having external styles impact your components in a cascade, originating from outside to dictate the appearance of child elements makes reasoning about and debugging styles more challenging, requiring the developer to constantly keep extra context in mind.

The question, “Where is this CSS coming from?” should never need to be asked.

HTML and CSS serve the same concern, with JS often joining them. This is why frameworks like Vue and Svelte bundle them into single-file components.

While React doesn’t prescribe a styling approach and uses JSX rather than SFCs, the popularity of CSS-in-JS is undeniable.

Style encapsulation at the component level is more efficient and easier to work with, particularly as the component library expands.

Consider this example using Theme UI, described as “a library for creating themeable user interfaces based on constraint-based design principles.” For simplicity, the example is pulled from their front page:

// Create your theme

import type { Theme } from 'theme-ui'

export const theme: Theme = {
  fonts: {
    body: 'system-ui, sans-serif',
    heading: '"Avenir Next", sans-serif',
    monospace: 'Menlo, monospace',
  },
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#33e',
  },
}

// Style your UI

/** @jsxImportSource theme-ui */
import { ThemeUIProvider } from 'theme-ui'
import { theme } from './theme'

export const App = () => (
  <ThemeUIProvider theme={theme}>
    <h1
      sx={{
        color: 'primary',
        fontFamily: 'heading',
      }}
    >
      Hello
    </h1>
  </ThemeUIProvider>
)

Notice how style information is defined as data in the theme, which is then used in the JSX template via the sx prop.

Again, I’m not advocating for a specific library here; rather, I’m using this example to demonstrate that web technologies collectively address the same presentation concern, encompassing both structure and style.

Conclusion

While presentation is not the only concern in modern web apps, the purpose of this article isn’t to provide a comprehensive treatise on the subject.

Certainly, we could discuss data fetching or state management as distinct concerns, but the discerning reader will have grasped the crux of this article by now:

In the era of components, structure, style, and interactivity are unified – they are no longer separate concerns. HTML, CSS, and JS aren’t isolated technologies but integrated tools serving a common purpose.

So, the next time you hear someone mention “separation of concerns” in relation to web technologies, as if the phrase itself were a compelling argument, feel free to challenge them and ask what concerns they’re attempting to separate. They may be misappropriating a principle without fully understanding its implications.


© 2024 freddydumont