@khinsen and @akkartik mentioned locality in another thread, and I wanted to lift that up to its own topic.
I’ll repeat the quotes they shared from Richard P. Gabriel’s 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.
If I look at any small part of it, I can see what is going on—I don’t need to refer to other parts to understand what something is doing.
If I look at any large part in overview, I can see what is going on—I don’t need to know all the details to get it.
Every level of detail is as locally coherent and as well thought out as any other level.
This idea of locality feels related to the “modular analysis” a compiler may do if it supports separate compilation: the compiler considers one unit of work at a time and does not need to see the whole program. There’s an eventual stage (e.g. linking) that puts everything together, but the compiler at least does not need to think in whole program terms.
As a reader of programs (whether human or machine-as-a-compiler), I agree locality is great. I want to be able to understand behaviour by looking only at the part in front of me.
As a modifier of programs though, it’s less clear to me. For example, I would like to modify the behaviour of some intermediate library layer. One can imagine various ways (e.g. aspect-oriented programming) that would allow you to reach in and modify the library from the outside, but this would seem to violate locality for future readers (including yourself): you can no longer understand that library’s pieces in isolation, because there’s so-called “spooky action at a distance” to watch out for now.
Of course, I could also fork the whole library and make my edits, but that’s a lot of work for a small tweak.
How can we support modifications and edits of the code we use while balancing locality as well?