Larry Wall famously lists three great virtues of a programmer: laziness, impatience, and hubris. I should like to add ingratitude.
The common understanding of Wall's virtues is as vices or faults of character. Young programmers are amused; perhaps dangerously, their poor and careless habits are endorsed; perhaps they are emboldened to do Good. Old programmers reflect on the exceptional nature of computer programming as technology, art, and culture; and may see merit in both interpretations.
I suggest ingratitude has a similar, dual nature. I define this here as the unwillingness to accept gifts and unexpected success. Rather than thank $Deity, Fate, or even a fellow engineer's forethought, the superior programmer looks with disfavor on things that work right when they should fail. Success due to unknown causes may be fragile and is suspect.
Therefore the virtuous programmer is ungrateful. He looks the gift horse in the mouth. She sees the routine that handles more cases than planned and hammers it for weakness. We bite found gold coins.
As have the first three, the virtue of ingratitude has a vicious nature, too. Failure to accept something that does, indeed, work and work well can lead to something perfectly robust being thrown out, or excessive time wasted building a more perfect substitute in a demonstration of false laziness. But the commonly-prescribed, inverse quality of gratitude serves the too-trusting programmer poorly. The minimum wise reaction in case of an attractive wooden horse found at the door is to study its documentation before towing it inside.
About four weeks ago, I decided to hack into Smart::Comments to have it accept alternative filehandles for output; the Vanilla version (1.0.4) prints only to STDERR. Particularly, I want to be able to log smart output to a hard disk file. I consider Vanilla a lightweight debugging tool, not for production; I thought the project a simple hack.
Well, it's a source filter; and its author, TheDamian, has perhaps taken liberties in its construction which he does not prescribe to others. Still, how hard can it be to replace every instance of print STDERR with print {$outfh}? And oh, there's the issue of getting and setting that $outfh. Turns out there's much more to it.
Still, I made surprisingly good progress in just a couple of hours. I wrote a few tests and they passed. I didn't use an elaborate testing framework, since I felt the accumulated weirdness of testing a source filter inside TAP::Harness was sufficient. I copied one test script to another and elaborated.
All went well until I actually got to the point of supplying a hard disk filehandle, opened for writing. This *almost* worked right but the file written had just a couple of newlines fewer than output to STDERR or even STDOUT under the same provocations. Since the test script strictly compared the output, it failed. The expected output, literally written into the script, was a duplicate of the expectations in prior tests. Where did these two newlines go?
S::C outputs gratuitous or prophylactic newlines under some conditions; I've spent much of my working time on this, trying to figure out or control when. I got to the point of a long-winded CB ramble on the topic. I worked on other issues. I played with fire, using an untouched copy of Vanilla to reverse engineer my working copy -- using a source filter within a source filter. I wrote an essay in defense of S::C. I groused, sulked, annoyed people. I set the project aside for a week.
By the time I returned, it was clear to me that I didn't want so many newlines in disk file output anyway. I'll beat you to the punch and admit that I still have not figured out what's causing more newlines to print to STDERR than to the disk file.
In pursuit of my two missing newlines, I have been over every line of S::C. Even after the week off, I spent much time looking for those newlines. I've torn up Conway's original code, broken out subroutines, tackled several unrelated tasks, and tinkered with every single place where the module might emit anything, anywhere. I've written enough comments -- boilerplate, algorithmic, elucidating, defensive, indicative, and discursive -- to launch an intercontinental ballistic missile. I added the entirety of Vanilla's original test suite to my own.
My original plan was to diddle the original code as little as possible; leave the complex stuff alone since, after all, it works already and it's way above my level. I meant only to add a feature, not to rewrite old ones. Instead, I've come to understand S::C much better than I planned; and I hope I've brought the code to a more maintainable state.
Finally, I caved in and moved the goal posts to where I wanted them to be anyway. All current tests passed, Conway's and my own. I became grateful that chance or fate had eliminated newlines where I didn't really want them anyway.
After much more refactoring and indeed tearing up my whole approach to storing state, the gratuitous newline issue has resurfaced, with wheels on. I have no alternative but to track it to its source and fix it (still TODO).
The point is not that I'm clever or even hard-working; I'm not. The point is that my ingratitude, my untrusting nature, my unwillingness to accept the gift of the module working unexpectedly well, is what drove me to overcome my inexperience and ignorance, to rise to the challenge.
When I became grateful and falsely lazy, I stumbled.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Ingratitude, the Fourth Great Virtue
by jdporter (Paladin) on Jun 29, 2010 at 14:04 UTC | |
by Xiong (Hermit) on Jun 29, 2010 at 14:56 UTC | |
|
Re: Ingratitude, the Fourth Great Virtue
by pemungkah (Priest) on Jul 02, 2010 at 00:01 UTC | |
by Xiong (Hermit) on Jul 02, 2010 at 12:30 UTC |