Yeah, that's a pretty good example of how an design hole might play out. :) The developer wants to present a multiple-choice question, not a text box that happens to have default options off to the side. If they add an "other" choice, that's plan B, for when plan A isn't quite what the user wants to participate in.
If we say the developer has plan A, plan B, plan C, and so on, it's probably more honest to say these are a continuum. They're like layers of sediment, and a design hole in one layer just means we can step down into the next one. But the deeper levels of developer intentions are more fluid and fickle, and after some point (plan N, plan O, plan P...), the developer has no idea what they want. They'll just leave the problem for someone else to solve, whether it's their future self, a mind clone, a client, a friend, etc.
In this blog post, I imagined that cliff would be pretty drastic; one portion of the intentions is absolutely precise, and the other part is so open-ended that it must be handled by an intelligent representative. The dividing line is whether the program code contains explicit instructions, or whether it invokes an error mechanism. But it would be nice to acknowledge that this isn't the only line on the map.
Hmm, here's a possible two-dimensional map:
---
Rigor Dimension
Rigor 1: Code so rigorous and comprehensive, yet with such a simple interface, that you could call it a mathematical theory. Code like this almost never needs to change, but sometimes it isn't the right code for the task at hand.
Rigor 2: Code that is built using simple mechanical metaphors on a simple mechanical foundation (like most of today's programming language semantics), but is expected to change to some degree. This layer might be further divided into external API definitions, libraries, and application code, in order of decreasing stability.
- (In the blog post, my dividing line was somewhere around here.) -
Rigor 3: Code that relies on intricate and data-heavy techniques but can still be engineered in fuzzy ways, like AI.
Rigor 4: Code that relies on a true universal intelligence embedded in the program. Mind clones go here. So do human pilots.
---
Stubbornness Dimension
Stubbornness 1: Code that gets deployed with the program and always stays. Without this code, it just isn't the same program.
- (In the blog post, my dividing line was somewhere around here.) -
Stubbornness 2: Code that gets deployed with the program but actually isn't as precise as it looks. Perhaps it represents initialization data that may change over time due to external input, or perhaps it describes an ideal outcome that an AI system will try to approximate.
Stubbornness 3: Code which can be modified, and which is completely useless until that modification actually occurs, except perhaps for the useful behavior of begging an external system for help.
---
Actually, I hesitate to give the above lists without mentioning some other interesting kinds of code that don't quite seem to have a place in those two dimensions. I think it's actually possible to organize these outliers into two more dimensions:
---
Immersion Dimension
Immersion 1: Code which exists in such a transitory way that the developer hardly even considers it their code in the first place. For instance, a player can control Mario, but Mario is just a part of a much bigger program beyond the player's control, and (I think) players rarely consider themselves to be developers of Mario control programs.
Immersion 2: Code which communicates with the developer in a way that's extremely inexpensive for them both. A player can control Mario without bothering to open a text editor, so something like this might be possible for programming too.
Immersion 3: Code which, if modified, somehow exposes its modifications to the developer(s) for possible inclusion in future deployments. Copyleft licenses are a non-mechanical example of this. Another example is a personal shell script which never leaves the developer's machine to begin with.
Immersion 4: Code which is completely detached from the developer once it's deployed. (In the blog post, I only considered this kind of code.)
---
Openness Dimension
Openness 1: Code which an external system can modify using tools very similar to the ones that were used to write the original code.
Openness 2: Code which was created using certain tools but must be modified using others, like a special reflection API, scripting language, or bytecode generation.
Openness 3: Code which can't be modified.
(In the blog post, this dimension was irrelevant to me.)
---
(Stubbornness 1 and Openness 3 sound like the same thing, and I think Immersion 0 would be the same thing too. It might help to reverse the rankings on some of these axes; I just put them in an order that made them relaively easy to explain.)
So there, I guess I probably won't divide programs in quite the way I described in that blog post. I now have plenty of rope to confuse myself with. :-p