In praise of rewriting
Edited for style after publication.
There is value in doing old things from scratch in a new project. You learn to simplify and to correct mistakes. If you reflect well on your previous design, you may achieve a sort of reverse second system effect: a more precise, more straightforward replacement for what was overly complicated. The common wisdom says you shouldn’t rewrite a large codebase from scratch, and it’s probably correct for the vast majority of cases. However, if you are starting a new project that has overlap with what you’ve done before, it may be an opportunity to get right what you didn’t. If your new project is small enough that you are not forced to reuse bits from its predecessors, rewriting should be fair game.
The real-world case that lead me to this conclusion was working on the build system for tcl-augeas and then tcl-duktape. The former handles a more complicated build and abstracts away some particulars of the project it was developed for, but it lacks features to be easily reused in another project. As a result, it currently sits uncomfortably somewhere in the middle between a build script and a “real” build system. While it may be expanded into a “full-sized” build system later, this is beyond the scope of the project using it. You can feel the downside today: its source code is not as easy to read as you would want due to the abstraction.
The latter build system throws away much of the abstraction and the declarative approach to configuration that followed from abstracting the build. Instead, it goes for an imperative approach. It defines commands useful for compiling and installing Tcl extensions written in C. There is just a few settings to reuse certain values for the sake of DRY. Thanks to this, the code reads more like a Tcl makefile than a Tcl SCons. The second build system’s code turned out less abstract but easier to read and to maintain thanks to the developer’s previous experience and the freedom to start from scratch.
It says something that I eventually replaced both build scripts with GNU Autoconf, which is standard for Tcl extensions, because it is standard. My extension was different from the others a user of tcl-augeas and a user of tcl-duktape built for their respective projects. With these users’ somewhat unusual build targets, it was an ongoing source of inconvenience for them. Part of why I wrote the custom build scripts was my unwillingness to deal with Autoconf. I overcame it (at least for a time!), learned some Autoconf, and made life easier for my users. Perhaps the lesson is that,
- Rewriting from custom to standard is also underappreciated;
- Custom software gets written because of something like “ugh fields” around existing software. I’d had painful experiences with Autoconf before.