(Like this article? Read more Wednesday Wisdom!)
I am regularly in discussions about code quality and, specifically, how to improve it. Unfortunately, I really have no clue how to do that.
I care about code quality. Mostly because low quality code is hard to understand and (therefore) leads to bugs and outages, but also because bad code just offends my esthetic sensibilities. I look (and have looked) at code a lot and it is obvious to me that code of high quality is much easier to understand, which reduces the time it takes to solve problems or to add features. The TCO of high quality code is much lower than that of low quality code.
I also care about document quality. I read and write a lot of documents and, like high quality code, whatever the document “does”, the point that the author is trying to make, is much easier to understand in a well-written document; one that has a logical structure, maybe contains an inverted pyramid or two, uses graphs well, and doesn’t take too many liberties with grammar and spelling. Much like high quality code, high quality documents amortize really well by offsetting the writing effort over multiple readers and across a (sometimes considerable) span of time.
Come to think of it, I probably just hate sloppy work across the board. One of the things I loved about living in Switzerland is the exceedingly high quality of pretty much everything there. When we moved into our new office (back in 2009/2010) I saw Swiss workmen use laser levels to hang up a whiteboard on our office wall and use small vacuum cleaners to collect the dust while drilling. Then, after using an electric screwdriver to fasten the whiteboard to the wall, they took out a manual screwdriver to make sure the crosshairs of the four Phillips screws in the corners were perfectly aligned with each other, the horizon, and the gravitational field of the Earth.
But, back to code quality.
In our relentless drive to make everything measurable, many of the code quality discussions I am in revolve around metrics: How to capture the quality of the code in a few numbers. The metrics-du-jour are often about code coverage: What is the percentage of lines and conditional branches that are exercised by (unit) tests. This then comes up in production readiness reviews and go/no-go meetings and leads to questions like: “Why is line coverage below 90%?” Answer: Because so much of our code is generated by dependency injection and aspect oriented programming frameworks and a lot of that code is not exercised during tests, only during production. Or: This is a tiny project and it contains a lot of try-catch statements for dealing with infrastructure exceptions that don’t happen during testing. To which the right answer is of course: Fault injection but really who has the time and how useful is it in a particular situation? In the meantime, the code might be a steaming heap of spaghetti that nobody short of the compiler can make any sense of, but instead we are talking about ways to get the metric up in ways that do not qualitatively improve the code.
Some companies I worked for have coding style guides. These commonly prescribe important things such as the obligation that there be two spaces before an inline comment (a comment that is not on a line by itself). Another great one is that lines cannot be longer than 80 characters because, surely, the 1928 IBM punch card standard still needs to influence my C++ coding today. Style guides sometimes contain very worthwhile items, such as prescribing the use of the explicit keyword in C++ constructors, but mostly I daresay they do nothing to significantly further the overall quality of the code. They do typically make sure that bad code is at least decently and consistently formatted, which is a small win in itself, but one that source code formatters can easily take care of.
My “favorite” style guide items relate to naming and specifically the often found ban on single character variable names, which I find to decrease code readability in situations where a “i” or “s” are perfectly canonical and easy to understand names for a for loop iterator or a string with limited scope. On the other hand I never minded the Google rule that C++ member variables names’ need to end with an underscore, so it’s a mixed bag I guess.
Code quality is much like pornography (link is SFW): It is very hard to say exactly what it is, but easily recognized when seen in its full glory. But how to bring it about?
I try to write high quality code because I think it is important. And I think it is important because I have dealt with low quality code a lot. I care about writing high quality code because high quality code is better in all respects. I don’t even believe that it is slower to write high quality code, because I understand the difference between speed and velocity. But, as I said, I have so far been unable to move teams that I worked with and that could use a nudge in the right direction.
Here is what I tried and what didn’t work:
Be an example. I try my best to make all code that I write of reasonable or better quality in the hope that this inspires people around me. This has not worked so far, which makes me wonder if people actually recognize good code when they see it.
Be an active code reviewer. Most organizations use some form of code review and that is a good place to point out places where the code could be better. This has led to situations where team members compared pull requests and one bragging that they had only received 75 comments from me, which I would certainly think is nothing to be proud of. So far this approach hasn’t worked though. First of all I typically do not have the time to be in enough reviews and give them enough TLC to really move the needle. Furthermore, even I don’t want to be the curmudgeon all the time. Also: If you become too annoying in code reviews, you will get fewer code reviews over time, thereby making this tactic less effective over time.
Write coding guidelines or standards. Policies simply don’t work as a vector for change. A policy works to drive alignment around the details of something that people already mostly agree on. Also: Imagine writing a policy that guides bus chauffeurs on how to be a good driver. What would you write in there? Always indicate before a turn? Do not drive faster than the maximum speed? What would you write in a coding guideline that would seek to make someone a better coder? Use the narrowest type possible? Do not use global variables? These are surely good rules to live by, but the problem is that it is possible to write terrible code that adheres to these two strictures and great code that breaks them.
Give presentations. Been there, done that, doesn’t work, nuff said.
After all that work and the many disappointments I have come to the sad conclusion that you can’t teach caring. I try to write high quality code because I care. All the people that I ever worked with that wrote great code, cared. People who care always do their best to write the best possible code, even in situations where nobody else seems to care. And apparently, you can’t teach people to care…
I'll be very brief here, bordering on curt (sorry): I think the problem of not caring is when computing started being a job that pays well, rather than a job one does because they like the craft. So your question is more, "can you teach people to love computers (the craft itself)?".
But what do I know, I'm an old curmudgeon…
You always write just what I need to share!! :)
But today I have to say - I've had the same conversation with managers and caring about people... I would argue that people who don't care about people shouldn't be hired to manage. So a corollary could be....(?)
I think companies' priorities are reflected in all these things.