Humility and Better Programming, Part 3
A programmer who truly sees his program as an extension of his own ego is not going to be trying to find all the errors in that program. On the contrary, he is going to be trying to prove that the program is correct—even if this means the oversight of errors which are monstrous to another eye.
In this book in 1971, Dr. Weinberg described the concept of “egoless programming”, using a cooperative approach to programming. One of the main points of his book is that programming is better with teams that share their ownership of code. I didn’t know this style of development had a name, but this is what we’ve practiced on the LabVIEW R&D team since the beginning. The more modern “agile” software development methods have their roots in egoless programming.
There are a bunch of great anecdotes in the book, many of which are still relevant 40 years later. Here’s a great story that helps explain more about egoless programming…
A programmer (“Bill”) was responsible for writing an important section of code at the heart of a simulation system. This section of code was a loop that consisted of just thirteen lines of machine code.
…when he finally reached the point of some confidence in it, he began looking for a critic—the standard practice in this programming group.
Bill found Marilyn B. willing to peruse his code in exchange for his returning the favor. This was nothing unusual in this group; indeed, nobody would have thought of going on the machine without such scrutiny by a second party.
… His value system, when it came to programming, dictated that secretive, possessive programming was bad and that open, shared programming was good. Errors that might be found in code he had written—not “his” code, for that, terminology was not used here—were simply facts to be exposed to investigation with an eye to future improvement, not attacks on his person.
In this particular instance, Bill had been having one of his “bad programming days.” As Marilyn worked and worked over the code—as she found one error after another—he became more and more amused, rather than more and more defensive as he might have done had he been trained as so many of our programmers are. Finally, he emerged from their conference announcing to the world the startling fact that Marilyn had been able to find seventeen bugs in only thirteen statements. He insisted on showing everyone who would listen how this had been possible…
Marilyn, at the same time, did not feel any false confidence in her own work on the problem, for—she reasoned correctly—-where there had been seventeen errors, there were probably a few more… while Bill was giving everyone an enormous laugh at his expense, Marilyn and others managed to find three more errors before the day was over.
As an epilogue to this incident, it should be noted that when this code was finally put on the computer, no further errors were found, in spite of the most diabolical testing possible. In fact, this simulator was put into use in more than a dozen installations for real-time operations, and over a period of at least nine years no other errors were ever found. How different might have been the story had Bill felt that each error found in that code was a wound in his pride—an advertisement of his stupidity.
So how do you put this into everyday practice? I can sum it up this way… Don’t work in isolation. Here’s one major theme…
Review your code with others.
This is the way we do it in LabVIEW R&D. Approximately* all of the code that anyone submits to our source code control system is reviewed by at least one other person. (* There are exceptions for fixing misspellings in comments and other simple changes.)
It takes courage to bare your code to others. You have to be honest and not hide anything. It seems there’s always code that could have been written and documented better, designs that could have been more elegant, and error checking that could have been cleaner, weighed against getting the feature or bug fixes done in a timely manner. But we do it anyway. Remember, we’re reviewing code, not reviewing the person. It’s not about your ego; it’s about creating better software. I know that in some organizations, this will be a big culture shift.
Reviewing code has multiple benefits. It builds stronger teams, which build stronger, more maintainable applications…
- A reviewer is more likely to see bugs than I am. Sometimes you are so familiar with your code that you are blind to obvious bugs. There’s also the benefit that more bugs are caught early, before they are submitted to the main branch in the source code control repository.
- It helps ensure that my code is readable and explainable. I like to sit with my reviewer and go through the code with her. If I have trouble explaining it, there’s a good chance the code isn’t written well and I might need to rethink it. And on more than one occasion, I’ll realize I have a bug in my own code when I see that the code isn’t matching my verbal explanation. Other people like to have their code reviewed “offline”—“Hey reviewer, here’s my code. Get back to me.” This forces you to document it well enough that the reviewer will understand it without additional explanation.
- Someone else learns something about the code. If the author of a change goes on vacation and I have a question about the code, I can try to find the person who reviewed the changes. They may not know the code as deeply as the author, but they might be able to explain the code well enough for me to figure out my question.
- It encourages reuse. A reviewer might know that the team already has a function that does what you’re trying to submit. Or, I might remember that I reviewed a piece of code that’s just like a function I need now. I can find and reuse the code, rather than write my own.
- It’s a great way for the team to learn good coding practices and style. This is how new programmers learn the team’s style. A reviewer can remind you if the style guidelines call for a particular connector pattern, error handling scheme, or documentation style.
- The teaching works both ways. A junior developer can learn from an experienced reviewer. A senior developer can learn new tricks from a junior reviewer. (And for completeness, a senior developer may want to find a senior reviewer if a bug fix is particularly difficult or mission-critical, and it’s usually not a great idea to have a novice developer use a novice reviewer.)
- It forces developers to have at least a few social skills.
One more comment on reviewing all code… I’ve heard of teams that only review difficult or problematic (buggy) code. A major downside of this is that junior engineers only learn from difficult and buggy code—i.e., they are learning from the poorest examples. Conversely, I’ve heard of developers who hide the ugly code, and just want their best code reviewed. Reviewing all code means everyone gets a more balanced view of the quality of the project.
More ideas coming up in part 4.