Great Software is Simple on Many Planes of Abstraction
There is a dichotomy in software development, high-level and low-level software. This is particularly true in programming languages, where you have low-level languages that give you more control, but require more understanding of how computers work, and high-level languages that allow you to express your ideas more simply and allow you to not think about low-level details.
High-level software is called that because it operates at higher-levels of abstractions. This means that it obscures the lower level machinery of what happens, so that we can focus on the task at hand. For example, we would not want to think about how a web browser forms a TCP/IP connection, communicates with a DNS server etc. when opening a web page; at least we do not want to up until the point where we have some error.
High-level software unlocks the ability for us to perform more advanced tasks quicker with less mental overhead. It can also unlock a great deal of improved security, as it can restrict certain operations from the user and better adapt to their needs, which even if it removes some liberty is still desirable.
When we only focus on building a good high-level experience, it comes at the expense of low level control that becomes inaccessible or too complex for regular users. This invites us to be inefficient, construct false understandings, and without a deep understanding of our systems, we can not meaningfully fix the system nor optimize it. It invites us to outsource this control to experts, who are often restricted to building general solutions for many use-cases. Poor understanding often leads to rebuilding the same solutions over-and-over again, with the solutions becoming even more complex and inefficient each time. When only experts understand systems, it centralizes knowledge and power and makes the general population unaware of issues. I explored the democratic problems it leads to in my essay The Curse of Convenience.
Low-level tools gives us greater control and greater freedom. Understanding the lower-level units makes it easier for us to understand how everything fits together, and gives us the power to make the changes we wish. However, using only low-level tools makes it more difficult to cleanly express ideas and it can be a frustrating experience. It sometimes requires digging through manuals and the time it takes to accomplish tasks becomes much longer. It is also easier to make mistakes.
This dilemma leads me to solutions that attempt to be simple on many planes of abstractions. In programming languages such as Go and OCaml, the high-level semantics are simple, but a user can still also understand the lower-level details of what happens, which makes it possible to operate at a lower-level when necessary without being an expert. In software, Unix utilities find the balance of being simple and allowing users to express high-level ideas. Older motorcycles are easy to operate, and also easy to fix when necessary.
- Marc