Skip to content

AllToolsAreParsers

Ben Christel edited this page Jul 29, 2024 · 5 revisions

Alternate title: "All Tools are Partial"

EDIT(2024-07-29): I don't like the title of this page anymore - I think the focus on "tools" makes my argument hard to grok. But replace "tools" with "abstractions" and it makes a lot more sense. Some tools have built-in abstractions, but not all do.

Every tool is a layer between ourselves and the universe that maps a less-structured reality into a more-structured view (where by "more structured", I mean to imply "more knowable and controllable").

That is to say, every tool is a parser according to AlexisKing's definition of the word. It is a function that transforms less-structured input into more-structured output.

A universal flaw/feature of parsers is that they are PartialFunctions. That is, there are some possible inputs that do not map to any output. This "flaw" is absolutely necessitated by our concept of what "more structured" means.

This is why, in the words of JoelSpolsky, AllAbstractionsLeak. There are some inputs, some situations in the messy complex world, that our tools just can't make sense of. In those situations, we get errors or undefined behaviors.

It is a further universal fact about parsers that, when a parser encounters a problem, you, the user, have to understand, at least abstractly, what is going on "under the hood". To use a quite literal example of a parser: if you're writing code and get a syntax error, you have to understand not only the syntax of the programming language but perhaps a bit about how the parser for your language works as well—the parser can only tell you what it didn't understand, which might be a bit of code distant from and seemingly unrelated to your change. If you get a type error you have to understand a bit about the theory of types and how the typechecker is processing your code. If you get your git repo into a weird state where you're simultaneously rebasing and cherry-picking, you may have to learn a bit about how git works in order to fix it. (or you could just BruteForce your way out.)

And finally: the general lack of awareness among software developers that all tools are parsers is, quite possibly, what leads to the invention of so many dubiously useful tools. We tend to look at our tools and think "this interface is such a mess and there's so much to learn, but if we just abstracted it all away it could be really easy to use". What we usually don't see, at least in advance of building the new tool, is that it really is partial: there will always be some use cases it doesn't handle and some states it can't make sense of. And so we trade, at great expense, the old partial function for a new one, perhaps one that breaks in different cases or has different warts. And then when it doesn't quite work as perfectly as we hoped we scratch our heads in puzzlement, and think "well, maybe next time". There's always a next time.

So what is to be done? In the spirit of 36Views, I suggest using many small, simple tools that complement each others' weaknesses. Keep your dependency graph shallow (see DeepHierarchy) because you will have to understand the layers beneath you to some degree. And don't expect any tool to solve all your problems.

Clone this wiki locally