Reusable Software Components2018-01-21
I have been experimenting with a somewhat radical sounding practice for developing software — one designed to reduce both complexity and bugs. It isn't agile, and it isn't TDD, the closest thing to it is copy-paste.
Engineering Best Practices vs. Open Source
I got the idea from a conference video where the speaker advocates a fundamental rethinking of industry practices, in particular, in the context of open source software. The heart of his argument is that copying or re-implementing only those things absolutely necessary for an application from what would normally be third-party libraries can reduce both complexity and bugs.
Because it would be crazy to suggest something like this at work, I instead opted to try and refactor one of my own projects, quiescent1. My own static site generator originally used Jinja2 for templating mostly because I didn't know any better, if you follow any internet hype you can easily be lead to believe "Everyone in the Python world uses Jinja".
Sizing Up Jinja
I do have an ulterior motive in all this, which is that I've grown dissatisfied with Jinja as a useful templating library. I have found it huge and awkward in practice (though not in this particular project), and want as little to do with it as possible. In order to justify some of this, I took a look at just how big Jinja really is, along with its one dependency markupsafe:
Before excising Jinja from my project I dug out my copy of 500 Lines or Less, which spends chapter 21 implementing a templating engine in Python. The code size can be deceptive, the end result is a full-blown code-generating template engine that supports a variety of general purpose templating constructs like looping, if/else clauses, and property access.
During the process of implementing it, I went ahead and stripped out a few more
things along the way to suit my tastes. I didn't like the
| (pipe) operator,
or comment syntax for templates so I took them out. What I am left with is a
workable solution that does only what I want.
|quiescent, 3rd party templates||7||89||134||446|
|quiescent, custom templating||9||145||210||741|
By adding about 300 lines of code (which includes tests), I was able to remove both Jinja and its one dependency. On the whole, +300 and -14,000 — not too bad, especially considering the necessary changes to my site generator were near-zero2.
I found the idea of eliminating dependencies appealing, and having tried implementing it, I think the potential is persuasive. I can't guarantee I'll be giving up on third-party libraries, but if only in design — keeping libraries quarantined so that you can rip them out easily isn't such a bad goal. It will be interesting, though potentially difficult to see how this idea ages, this particular project is low-traffic enough that it may never matter.
There are a few issues outstanding with the templating system, as implemented that might eventually be addressed to improve quality-of-life.
- Templates don't support inheritance yet, which means page headers are copied by hand. Might be an interesting exercise to add "template extensions" to the engine.
- Formatting dates is probably too rigid and required I use the same format between the archive page and index
- I should probably specify or test supported encodings (I assume it is only UTF-8 at the moment)
- With as much attention as it gets on my blog you might think it was my only project
- One necessary change involved removing datetime formatting from the templates and including a single format in the site generation, I haven't thought too much about this but think it could be improved.