We’re back after an undeserved week off and this week I want to discuss designing for maintainability.
Because this past weekend I put myself through more DIY plumbing madness and learned even more lessons about software!
Our story starts like so many home plumbing stories, with a slow draining bathroom sink. Probably a hair clog, which leaves open a few strategies. We had liquid clog dissolver handy, but I generally prefer to try a mechanical solution before using corrosive liquids.
First went in the plastic zip tool to try and fish out a clog. That failed, so I tried the snake. No such luck there, either. I know, I thought, I’ll just try a plunger and loosen it up a bit.
That had no effect (that I could tell at the time at least). Trying the snake one more time I noticed it was terminating a bit more abruptly and then I heard a most discomfiting sound, the sound of a water dripping.
The metal trap had corroded to the point where the snake was able to punch a hole in the bottom.
And only _now _begins my problem.
Thinking I’d try replacing it myself, and knowing that even if I had to call the plumber on Monday (this was a Saturday afternoon!) that he was going to remove the old trap, I proceeded to do so myself. This _should _be easy but for aesthetics and, yes, space efficiency, the previous owners installed a pedestal sink.
This isn’t ours but it’s close enough.
That porcelain pedestal not only supports the sink, it also hides [some] of the plumbing, including the tail pipe (from the sink) and the J-trap which then leads into wall and down the main drain line. This means you can’t see what you’re doing while you [dis]assemble the pipes and it’s near impossible to provide tool access. I’m convinced that whoever thought installing a pedestal sink was a good idea had never worked on the plumbing behind it.
At any rate I removed the trap and brought it to our local big box hardware store to try to match it up for a replacement. The exact match was an installation failure, however, because I couldn’t properly manipulate the joints. And actually, this was a second failure. I had hoped to find a PVC trap with the same dimensions instead of another brass trap; sure the brass looks nicer (while its brand new) but PVC _doesn’t corrode _and it would occupy a barely visible place. However for some reason PVC traps actually have a slightly different offset, meaning the tailpipe leading down from the sink would have to be ~1cm further back…
To wrap this up or get us closer, I ended up getting a PVC trap and a flexible replacement tail pipe extension so that I could take advantage of both the longer expected life of the PVC trap and the assurance of PVC slip joints which for this application I think are superior.
I was able to test and tweak the entire setup for leaks because the drain was still clogged.
My previous attempt at plunging the sink likely had the effect of moving the clog out toward the main drainage pipe. So after disassembling _that _connection and pulling out what I could, I reassembled, tested for leaks, and brought out the liquid clog dissolver. After a few minutes I added some water to move it further down the line, then let it sit, tested again, and voilà a clean flowing, non-leaking sink!
There are a couple of obvious lessons here:
The second… well, the liquid clog dissolver probably would have worked, but I don’t know how much it would have benefited an already corroded pipe. And we’d still have a time bomb of a sink trap.
But there are some things we can extrapolate further that are more directly applicable to software design and Django sites.
Problems with how functionality is _ embedded _usually come dow to more general software architecture decisions. Is there a ton of logic in the templates that would make refactoring more difficult, for example?
The problem of aesthetics triumphing over functionality is far more likely to be found in residential architecture than Django sites. More often than not you’ll see at attempt at cleverness where it’s unwarranted which makes either changing or testing the code more difficult or is just plain harder to understand.
Testing only individual pieces , that is only unit testing, means you don’t have a clear understanding of how - or if - the pieces fit together properly. This is a horse which has been beaten to death elsewhere however.
Relying only on whole system testing , however, is also a vice! But, you say, it tells us surely if everything is working! It does, you get a very nice pass/fail grade for the whole thing, but if you lack smaller level tests, whether unit or integration tests, then when the whole system tests do fail you have a much harder time identifying and fixing the problem at a lower level.
At one point re-installing the trap I encountered more leaking when I thought I had everything on tight. Frustrated by the pedestal, I removed everything and tightened up the intermediate parts of both the tail extension and the trap before reinstalling them as a single unit. This was a little bit harder to get in at first but it was far easier to verify that the key joints were tight. Can you imagine if you just had to try every single thing when the top level test failed? The new, verifiably tight joints worked, by the way.
There is a school of thought out there, a kind of TDD sectarianism, that you should delete most of your unit tests when you’re “done” developing and rely on integration or system tests to test against regressions. Surely there are _some _tests which you could remove, but if you’re relying only on higher level tests you might just find that updating your system is a bit more black box than you’d like.
Documentation is an obvious issue, but often overlooked is the decision history in a project like a Django site. There are formats for capturing this on its own, but outside of the documentation a thoughtful Git history is excellent _for describing not just when something in a project changed _but why. Unfortunately Git only captures the sequence and timestamps automatically, the responsibility for providing an articulate “why” is left to the developer.
Systems that are designed for maintainability provide (1) insight into how they’re performing and how they operate, (2) means for verifying changes to the system, (3) documentation for design decisions and changes, and lastly but not least (4) affordances for actually making the changes, ideally in place.
Which do you struggle with the most in your projects?
 Slip joints: http://www.freeonlineplumber.com/slip.html Even if you never knew what it was called or how it worked, you’ve almost certainly seen them
 There’s probably some nuance I’ve forgotten since reading this argument, but I don’t think I’m misrepresenting the argument
 Git commit message image: https://xkcd.com/1296/
 A related article about using Git https://wellfire.co/learn/illustrated-distributed-git-workflow/
Learn from more articles like this how to make the most out of your existing Django site.