From the opening of Structure and Interpretation of Computer Programs [0] there is the famous aphorism, "Programs are meant to be read by humans and only incidentally for computers to execute."
I've been programming for over twenty years. Try as I might to produce code that expresses the problem eloquently and succinctly to unfold the solution in the readers' understanding as they skim through the source... it has rarely ever worked. Firstly you cannot please everyone. And secondly, programs are not structured for pedagogy.
Writing maintainable code is a communication skill but I find the best skills are writing, speaking, and illustrating concepts in prose, specifications, white board sessions, chats, etc.
The technicalities of ensuring code follows some kind of style guide, design principles, etc plays a big part. But nothing will explain "why" or the big picture stuff quite like a specification or blog post in my experience.
Author here. Looks like we both have a similar length of experience. I wouldn't give up this battle yet, because
> Firstly you cannot please everyone
> And secondly, programs are not structured for pedagogy
My theory is that you only need to please a couple of maintainers that work with you, not everyone. That's why I proposed a test with 2 colleagues at the end. It could potentially be spiced up with 2 colleagues of different levels. I believe this can act as one of those 20% effort to get 80% there, but definitely don't claim to have proof of this.
I am also on about the same timeline as you and GP, and in my humble experience, it's really just about having a lot of code/prose "under your fingers", so to speak.
I can't remember where I read it, but the wisdom I heard for writing is that until you've written a million words, your writing won't be worth reading. This feels to me like the 10,000 hour rule.
Code has the added problem that the reader must have additional fluency in it on top of human language, plus a whole bunch of idioms that may or may not be in vogue, or mayhap haven't been seen outside the organization they originated from (think silos; copyrights, secrecy and only getting binaries really don't help here). In some respects, we have code written by Chaucers, but is only from 50 years ago.
I do agree with you that Pareto principle definitely applies, but wherever possible I try to make my code as understandable as possible, with comments and ancillary documentation showing the "why". What I really wonder, is where are the world-class codebases we can point to as exemplars of what readable code looks like? Who can we cite as masters of the craft that make code others understand easily? Is Knuth one of them?
One codebase that I liked in terms of these qualities (albeit I'm sure it's not 100% perfect) is Redis[1]. There are YouTube videos[2] of antirez walking through it. Would love to find more examples too.
I think it is possible to produce code that conveys everything the spec would. The problem is the same as with Donald Knuth literate programming: to use it, you now require your coders to be both great programmers AND great writers. And these two traits rarely coincide in a single person.
IMO this is why good developers are so in demand. They are those rare people who are good at both. People who are great at both are the fabled 10X or 100X programmers.
Writing code is writing foremost for communication. If you are not good at writing you aren't good at programming. There is really no way around that.
Wait, is this the same McIlroy who claimed that PL/I has features no other language has, then listed syntactic sugars and things that could be implemented easily in libraries?
Edit: After having read the link, yes, McIlroy has a point. For quick prototyping, a one off, above all else small project, the UNIX way fits, and fits well. It's a philosophy I agree with and use on a very regular basis as a sysadmin.
But as a developer on larger projects, where chunking them into pipeable tools would probably result in 1000 pipes, any one of which might break, and you want to hand it off to people who don't even know what a pipe is, well, I'm sorry, but I'm going to make something in the tools that they understand and use, and I'll make it more fault-tolerant to boot. And yes, I've run into exactly this sort of situation multiple times in my career.
I might prototype with pipes and commands, but Larry Wall invented Perl for a damn good reason.
Really, TL;DR is that Bentley picked an over simple problem (count words in a file), asked Knuth to write a program in the literate programming style, and McIlroy completely missed the point of the exercise. What a shame, he might have had something useful or insightful to say had he understood what Bentley and Knuth were trying to achieve.
You have to be careful with readability in code review: you can't please everyone.
There's nothing more demotivating than spending 8 hours on a problem, feeling good about your solution, and then having some "senior" developer come along and tell you to rewrite it "for readability."
My best defence for this is to have a guiding philosophy or design guide beyond the usual linting rules and code formatting tools. It prevents unnecessary stylistic changes.
A good guide will centre itself around the intersection of the IC's values and the requirements of the system. If you're working on a game engine you might value performance and tend to prefer vectorized code over branching code in order to exploit parallelism as much as possible in the pipeline. Whatever your team values the most is what should go in there and it should be as clear as can be so that people can reference it when giving suggestions in reviews.
> There's nothing more demotivating than spending 8 hours on a problem, feeling good about your solution, and then having some "senior" developer come along and tell you to rewrite it "for readability."
While a senior engineer just asking you to rewrite it without further details is bad, it's good practice to follow the "make it work, make it right, (optional) make it fast" approach. The "make it right" part is where you make your code readable after you've ensured that it works and before you submit it for review. If you find later that you need to make it fast, it is expected that readability will have to be traded for performance.
Or, for the contrarian view, you have a few people mutually reinforcing poor coding practices under the guise of whatever they view as readable and maintainable, which in my experience is equally likely.
Even if you don't agree with the coding practices, at least it enforces consistency throughout the code base. It might not be the consistency that you desire, but it much better than every author having their own style.
> Firstly you cannot please everyone. And secondly, programs are not structured for pedagogy.
I would say that this is understating it, even. Not a Donald Rumsfeld fan, but his remark about the "unknown unknowns", that is, things we don't know that we don't know, is apropos.
Everyone knows about Quake 3's fast inverse square root with floating point bit hacking. It's a clever bit of code that, based on the comments, no one at id Software knew how it worked (at the time). And yet, it's not unnecessarily clever. It's not being clever to be clever to stroke any egos. It's critical to the entire game! (Tangent: Who here is brave enough to release critical, but mysterious code to millions of people and not have a panic attack?)
To bring this back to SICP, I believe I first encountered the recursive Fibnoacci function in SICP. It's a popular bit of code that demonstrates recursion in Scheme. The naive, but elegant version is:
(define (fib n)
(cond ((= n 0) 0)
((= n 1) 1)
(else (+ (fib (- n 1))
(fib (- n 2))))))
And of course, SICP goes into an iterative form and later goes on to describe a memoized form. Each version mucking up the elegance of the original tree recursive form a bit.
But what if you're terrible at math (cough, cough), and aren't aware you can do this:
Readable? Understandable? Maybe to a mathematician. No recursion, no iteration, no memoization. I suspect most developers would say "what the heck is this?", much like they did with Quake 3's inverse square root function. Although this at least has a wiki page about it. Try Googling 0x5f3759df when Google doesn't even exist. Like the Quake code, this code starts losing precision with larger "n" values. There is also a matrix form which is a bit better, but requires many more multiplications. Which code is right for you? That's the question. Imagine you only ever need the first 20 values of fib sequence. You might opt for a hardcoded lookup table. More lines of code. But it's a valid trade-off.
This is a straw example, and Quake's code is a case of necessary optimization (as opposed to premature optimization). But the point is each person carries their own set of "unknown unknowns" with them. If enough people leave your project, then the unknown unknowns start piling up. You may even be tempted to rewrite your system. Now you've entered the hell known as the second system effect.
We can talk about communication all day. But I have yet to work at a place not tempted by the siren song of the rewrite or ended up rediscovering every bit of knowledge Fred Brooks dropped on the world more than 45 years ago. The Mythical-Man Month isn't even a long book. But I don't think anyone reads it today. I certainly don't think we would have went through the microservices fad if people understood the implications within that book.
Note that, if you coded these two Fibonacci functions in e.g. Python 3, the "naive" solution remains correct as n goes into triple digits, while the "fancy" one runs into floating point error and then range overflow...
I've been programming for over twenty years. Try as I might to produce code that expresses the problem eloquently and succinctly to unfold the solution in the readers' understanding as they skim through the source... it has rarely ever worked. Firstly you cannot please everyone. And secondly, programs are not structured for pedagogy.
Writing maintainable code is a communication skill but I find the best skills are writing, speaking, and illustrating concepts in prose, specifications, white board sessions, chats, etc.
The technicalities of ensuring code follows some kind of style guide, design principles, etc plays a big part. But nothing will explain "why" or the big picture stuff quite like a specification or blog post in my experience.
[0] https://en.wikipedia.org/wiki/Structure_and_Interpretation_o...
Update: added missing link