"Software libraries suck. Here's why, in a sentence: they promise to be abstractions, but they end up becoming services. An abstraction frees you from thinking about its internals every time you use it. A service allows you to never learn its internals. A service is not an abstraction. It isn't 'abstracting' away the details. Somebody else is thinking about the details so you can remain ignorant.
"Programmers manage abstraction boundaries, that's our stock in trade.
Managing them requires bouncing around on both sides of them. If you restrict
yourself to one side of an abstraction, you're limiting your growth as a
programmer.1 You're chopping off your strength and potential, one lock of hair
at a time, and sacrificing it on the altar of convenience. "
"Division of labor is a relationship not to be gotten into lightly."
"I think software finally gives us a way to avoid division of labor."
"I think namespaces and modules are socially counter-productive even when
implemented in a technically impeccable manner, because they encourage
division of labor. In even the smallest of projects, without thinking about
it, we often start out with the goal of working with someone, and proceed to
do so by defining an interface and then working apart. That is no fun, and it
is gradually self-limiting. I think we do this because it's so easy to create
interfaces and silos, to isolate ourselves from each other's changes using
namespaces and similar constructs. By creating these constructs, by making
them too easily available, we forget to ask if we should use them. This is, I
think, an example of taking the human out of the loop. But even here, the only
way I can think of to do a rollback is by trying to build a software stack
"For the past couple of years I’ve been researching ways to write software
that make it easier for newcomers to understand rather than for insiders to
maintain. In this quest I built a toy OS and Basic-like language called Mu
which tries to “rhyme with” the design process by which Unix was coevolved
with C. The big additional design constraint compared to Unix+C is to make the
OS primitives testable. I want to be able to pretend in tests that we run out
of memory or disk, that a context switch happens between these two instructions,
and so on. My hypothesis is that having the ability to easily write such tests
from day 1 would radically impact the culture of an eco-system in a way that
no bolted-on tool or service at higher levels can replicate: it would enable
new kinds of tests to be written and make it easier to be confident that an
app is free from regression if all automated tests pass. This would make the
stack easy to rewrite and simplify by dropping features, without fear that a
subset of targeted apps might break. As a result people might fork projects
more easily, and also exchange code between disparate forks more easily (copy
the tests over, then try copying code over and making tests pass, rewriting
and polishing where necessary). The community would have in effect a diversified
portfolio of forks, a “wavefront” of possible combinations of features and
alternative implementations of features instead of the single trunk with
monotonically growing complexity that we get today. Application writers who
wrote thorough tests for their apps (something they just can’t do today) would
be able to bounce around between forks more easily without getting locked in
to a single one as currently happens."
"The lesson I draw for software from https://creators.vice.com/en_uk/article/animator-hand-draws-film-in-4-years-nova-seed
isn't about collaborating or not, it's about avoiding division of labor. When
working with someone on a project don't "design an interface" and then work
alone on either side of it. Work together all over it."
"It is undeniably useful to be able to put off learning about some parts of the system until we feel the urge. The golden mean may be to be on a stack that isn't 'lumpy', where between you and machine code are many gossamer-thin layers, any one of which can be easily peeled back to understand how it works.
"I started out mocking NPM for the left-pad debacle, but over time I've
actually grown more sympathetic to left-pad. The problem isn't that somebody
wrote a library for left-pad. It is that even something as trivial as left-pad
has triggered our division-of-labor instincts. A library like left-pad is just
begging to be saved into projects that use it so users have one less moving
part to worry about at deployment time. Turning it into a first-class dependency
also ensured that a lot less people looked inside it to understand its five
lines of code or whatever."
"One of the benefits of my scheme is that calling programming languages
abstractions is almost always obviously incorrect. Libraries are also never
abstractions. Clarifying this wording immediately cuts through a bunch of
confused discussions online."
"Libraries with non-trivial functionality take a long time to get right, and
in the meantime they are produced more like guilds of craftsmen than factories.
(Even if the products themselves permit factory-like operation at scale.) In
that initial bake-in period we are ill-served by conventional metaphors of
software components, building blocks, etc. We should be dealing more in
vertically-integrated self-contained systems rather than plug-and-play
libraries. More OpenBSD, less `gem install`."
"Division of labor is an extremely mature state for a society. Aiming prematurely
for it is counterproductive. Rather than try to imitate more mature domains,
start from scratch and see what this domain ends up needing."
"Confusingly, I've been calling Iverson's notion of subordination of detail
"abstraction", and Iverson's notion of abstraction "service" or "division of
labor". Though lately I try to avoid the term "abstraction" entirely. That
seems on the right track. Regardless of terminology, this is a critical
"I consider an example of exemplary library use to be how I copied the termbox library into Mu, periodically merged commits from upstream, gradually cleaned it up to fit better with my project, and gradually stripped out code from it that Mu does not require.
"In the process I made some wrong turns, deleting
features that I later decided I wanted and created
myself. But when it did things I didn't want, I
was now empowered to change them. One of my patches was useful upstream,
so I submitted
it. I would be in no position to submit that patch if I hadn't taken the
trouble to understand termbox's internals. And that shows a final benefit of
copying and privately forking libraries: it makes you a better citizen of the
open source world, because open source depends on eyeballs, and using a
library blindly helps nobody except your (extremely short-term) self."
"I've been thinking about the problem with division of labor for 7 years now, and I think I've boiled it down to two sentences. Why division of labor is disempowering:
1. (the setup) Power = capability - supervision.
2. Division of labor tends to discourage supervision."
"Let's assume code reuse is a mirage. What can we achieve if we stop aiming
for it? In this I think I'm close to the Forth aesthetic."
"Division of labor discourages learning from your
- The only way to guarantee you won't run afoul of Hyrum's
Law is to make no updates.
- As a consequence, I don't care about Hyrum's Law. I make updates to the
best of my ability, trying not to break others, but I don't/can't guarantee
they won't break others.
- If my updates can break others, I can't push them to others without
explicit consent. Others have to pick them up on their own schedule, when they
have the time to test them for their own context.
- If my updates can break others, others may have to make changes to them for themselves.
Rather surprisingly, these baby steps lead to a world entirely different from
the one I live in. One where we don't have interchangeable
parts yet, where software is often tweaked for a specific situation.
Comments gratefully appreciated. Please send them to me by any method of your choice.