Compounding Locality of Behavior
March 9, 2025
What more is there to say about locality of behavior (LoB)? The idea that what code does should be obvious to anyone reading it seems obvious, an almost unobjectionable preference. Lots of better programmers than me have already chimed in on the subject (I can recommend Silas Reinagel's blog post in particular). But Carson Gross's htmx essay on LoB stands out from the rest. Why was he so attuned to LoB and the hidden costs of indirection to the point that he was able to coin the term "Locality of Behavior" and renew interest in the topic? I would argue that it's because the benefits of LoB naturally compound.
Working Memory
How exactly do the benefits of LoB compound? There are two reasons, the first of which is that making a chunk of code more obvious to the reader makes it less cumbersome to keep in one's working memory. The programmer's memory, not the program's. If you can easily grasp what code chunk A does, it's easier to keep that in mind while you examine code chunk B. So having obvious and straight-forward code is like greasing the wheels of your working memory.
It might not seem like that big of a deal, but working memory is *very* limited. I think this is part of why Wes Bos expressed his frustration with having to spread a simple component into multiple files when using React server components in this episode of SyntaxFM. To take a non-coding analogy, basic juggling with three balls is not that hard; most people can learn to do it in an hour. But juggling with four balls is exponentially more difficult. If you can juggle well with five balls, you're already in professional circus-performer territory. So if you can facilitate keeping your blocks of code in your working memory, it will be much easier think about how they work together or debug why they're not working together as intended. LoB is mostly about the first part of just making a single chunk of code's behavior more obvious. This initial benefit compounds when you need to consider that chunk alongside others.
HTML as Codebase
The second way LoB compounds is a little more specific to web development, or rather, html development. When html effectively serves as your codebase, then all your chunks of obvious code suddenly find themselves all in the same document. When using htmx, you're probably keeping different components of your website or app in separate files and inserting them with partial DOM replacements. But when you inspect the rendered page, your html elements all line up one after the other. When an html element has declarative attributes that makes its purpose clear. If that element also interacts with another element specified by an hx-target attribute, it's even better when that other element is just a glance away on the same page. Using any javascript framework would also eventually put a bunch of html elements together on a page, but a lot of the heavy-lifting code won't be visible together. So all the things that, for example, an on-click handler does won't be as obvious as having that functionality made explicit via html attributes.
Not having to jump between html and javascript contexts brings with it remarkable clarity about how different parts work together. The benefits of LoB really compound in this html-as-codebase context. The funny thing is that htmx is of course still an abstraction that hides a ton of javascript. So you're still indirectly invoking javascript functions, but it feels like it's native html and that's all that matters.
# Add link to Wes Bos's complaint about having to store a button in its own file from React Server Components EpisodeCompression vs. Distillation
No blog post about locality would be complete without the compulsory quote from Richard Gabriel's 1996 book Patterns of Software:
The primary feature for easy maintenance is locality: Locality is that characteristic of source code that enables a programmer to understand that source by looking at only a small portion of it.
Gabriel wrote that in the context of compression while juxtaposing the costs and benefits of compression vs. locality. Compression obviously reduces the file size of software, but at the cost of its readibility.
The LoB in the html of an htmx project results in dense code, but that density arguably improves its readibility. Unlike javascript, html has historically prioritized readability over saving bytes. In an interview with Lex Fridman, Marc Andreesen explained that this was an intentional decision to favor ease of use (reading and borrowing other people's code) over performance.
Rather than a compression of the purpose of an element, htmx-style declarative html is a distillation of it. Hypermedia-driven systems take this a step further. Only the things you need (and often all the things you need) are right there in the html. This amounts to a refreshing concentration of purpose in the code. Each time you make an html element dense by this process of distillation, you consolidate it in your working memory and can consult it easily in the context of the entire document in the browser.
Since these compounding benefits are particularly noticeable in a hypermedia-driven application, it makes sense that Carson Gross was the one to reformulate the idea of locality to the more developed concept of Locality of Behavior which has really resonnated with the field of web development.