“As a designer, hell, as ANY type of craftsman, you are responsible for what you help to put in the world.” —Mike Monteiro
Last week, while working on my bustime node module, I decided to try out Code Climate as part of an effort to be more mindful the quality of the work I put out. Code Climate can integrate a test suite into their analysis, which is nice, but the reason I signed up is that they offer code analysis going by their ABC Metric. I have a lot to learn about my craft, especially when it comes to server-side scripting, so I jumped at the chance to have my work scrutinized by a service created by folks more knowledgeable than I.
The first evaluation gave every file in the project an A, except for one file: an object validation submodule which Code Climate gave a scathing D. This was really exciting, because it meant I get to learn something. Upon reviewing their analysis I learned that the big issue was “method complexity”, yet I saw no way to further simplify the code. It is what it is, I thought. I couldn’t possibly make it more straightforward. Excitement gave way to frustration, that old friend.
After mulling it over, researching the problem on SourceMaking, emailing Code Climate support for guidance and even tweeting about it (admittedly in frustration), I found a solution to my conundrum and learned a valuable lesson in the process.
The problem was not that my code wasn’t efficient, but rather that it was too efficient at the expense of legibility.
Where I was originally loading multiple external methods as needed in each local method, I am now building a separate object loaded with each of the external methods embedded, then referencing that local object in my methods. What once looked like this:
rt: Joi.alternatives().try(Joi.string(),Joi.number()).required() (indicating this property’s value must be a string or a number and is required), now looks like this:
It’s like my methods were a map and, in my pursuit of efficiency, I didn’t include a legend. A legendless map, with little labels for every different type of landmark or terrain, may sound straightforward (after all, everything is explicitly labeled), but it ultimately makes the map difficult to read. A legend adds a layer of logical complexity to a map but also reduces cognitive load and helps to better convey meaningful information. Likewise, by adding a single layer of logical complexity to my submodule, I removed several layers of cognitive complexity for anybody who tinkers with it.
The experience has taught me that, in addition to being efficient, code should also be easy to read. After all, the idea is not only for other developers to use my work, but to fork, modify, improve, learn from and share that work. To that end, my code should err on the side of legibility.