Sometimes enlightenment is a stroll in the park.
The Guru was out walking with several Novices. “This park has hacker nature.” he said to them. They saw that it was true, but remained unenlightened. Sensing the situation, he posed them a question: “Why?”
“Well,” said the first one, “this park is like our project back at the office because they both have trees.”
The Guru said nothing. There was no need to.
“I don't think that's what he meant.” said the second, obviously unimpressed by this form of humor. I see that this park is a large thing made up of many small things, giving an overall effect which we are enjoying. “Over there” she nodded in the direction where a lawnmower could be heard “is someone doing maintenance, and to him it’s just a job. But here is someone who enjoys his work. I imagine your spotting him as we rounded the bend is what prompted that comment.”
“Very good.” said the Guru. “He runs this place, and is in fact a retired programmer.”
They watched the gardener as they passed the place where he was working. He was in the process creating a new tableau, arranging benches around an area that had been cleared and prepared with plant bedding. Platforms within the to-be-planted area hinted that more was to come. It was the beautiful and interesting landscaped areas that made this park one of the Guru’s favorite places.
“OK,” said the first, more seriously, “the park is like a program because they are complex wholes that require a lot of work on a fine level of detail to produce and maintain. Furthermore, people express their creativity in their work.”
“You got it.” said the Guru. “Now, how are we, the users of the park, like the users of a program?”
“Well,” said the second, “we see the end result without taking a part in its creation. We judge the whole and overlook the parts.”
“Yes!” said the first, “I perceive features and bugs by judging the whole in the context of my experience. The fountain is a feature; if the water overflowed it would be a bug.”
“You have the right idea,” said the Guru, “but you are missing the most important detail. This is not a minefield.”
Nobody spoke for a moment. Then the second mused, “Actually, a park with a minefield is not such a far-fetched idea. There are unexploded bombs buried in Europe, and some countries might have actual mine fields left over from a war and long forgotten.” Before the Guru could reply, she led the next card in the conversation: “What would be the ramifications of living where there might in fact be mines hidden underground?”
“People would be more likely to obey the ‘keep off the grass’ signs.” said the first, without missing a beat. At that the second hastily looked around to make sure no such signs were present, as she had kicked off her sandals and was wiggling her toes in the cool green blades as they talked.
“Not to worry,” the Guru reassured her, “this grass is safe. As safe as grass gets, that is.” he amended himself. “And we are quite welcome to roam freely throughout this area.”
With that the group wandered off towards a tall Live Oak, and discovered three hammocks strung among the low weeping branches, hidden from the main pathway. “Hacker nature, all right.” someone said.
“He has the right idea.” the Guru continued. “To generalize, if you had to worry about land mines, or for that matter even gopher holes or fire ants, you would not generally stray from the well-used pathways. This little hideaway would be unused and probably undiscovered.”
“The real point,” he addressed them both, “is that you overlooked the central fact of the park: its total freedom of usage. Anything you might want to try, such as walking to this tree, works properly without surprises. You do not fear that the world would come crashing down around you if you happened to step in just the wrong place.”
“You notice problems—a muddy hole, or wet paint, or a malfunctioning fountain would catch your attention as a ‘bug’. You notice the artistic fountain or this hideaway as ‘features’. But the biggest feature of all is the microstructure: remember, the park, we agreed before, is a large thing with lots of details. The large thing is the park, the small things are just parts. The park would still be the park without elephants.”
“Or without that big fountain we saw on the way in. You could change every feature and would still have, in essence, a park. It’s the relationship between the features, the overall presentation, that makes the park a park.”
“But, I digress. We are here to talk about the difference between antibugging and abugging.”
“We are?” said the first. “I thought we were here for our siesta.”
“I heard about those before. Anti- and abugging, that is. In the Piranha book, right?” asked the second, always eager to keep the subject on track after the other’s lame attempts to lighten the mood.
“Right. The terms were coined by a brilliant hacker with an unpronounceable Polish name in the late ’80’s. The theory goes that debugging is the last line of defense, and is something that occurs only as a last resort. Debugging is like digging up all the land mines. Well, you have to find them first. That’s the hard part.”
“But there are no land mines in the park.” grumbled the first.
“If we were in Europe, I could reasonably ask ‘how can you be so sure?’. But, seriously, when my friend over there build this place he didn’t put any land mines in. That’s antibugging.”
“So what’s the difference between antibugging and abugging?” asked the second.
“Generally, antibugging deals with design-level issues, and abugging deals with implementation-level issues. Anything you see is probably abugging. Antibugging is like the elephant.”
“The elephant that’s not here?” asked the first.
“The same.” replied the Guru. “You didn’t notice it until I pointed it out.”
“So, antibugging is when everything comes out just right, and abugging is when you have to deal with issues?” mused the second.
“Right. Mud on the trails after a rain, or high water due to the creek flooding, would definitely be a bug. How would you deal with it?”
“Well,” said the first, “I could put up warning signs. ‘Do not use trail during high water’. Or, if it’s really bad, close the park during bad weather.”
“OK,” continued the Guru, “that’s an example of abugging: catching the problem and dealing with it. That’s like putting barbed-wire fences around the places where the land mines are buried.”
“But antibugging is not having land mines in the first place.” commented the second. “So what’s the analogous situation for the rain problem?”
“Good design is not something you notice. Applied abugging leads to error checks at run-time, strong typing at compile time, and special cases in the code. But applied antibugging leads to elegance. This park has hacker nature. Go look for yourself.”
The Guru knew that she was a good student, and was genuinely interested. She walked away from the tree, to regain a view of the paths that wandered through the park. The others spent the minutes in quiet contemplation.
“I see it!” said the second as she returned. “Looking at the paths, at first I saw nothing. But I decided to find a worse-case situation to see if anything was more obvious. I looked at the bridge and thought about what would happen in a rainstorm: what would keep the mud and flood water off the path? I saw that the water would have to get quite deep indeed to pose a problem: there is a small hill on either side of the creek, and the path crosses from hilltop to hilltop. The bridge is several feet above the water. Once I had the insight, I followed the paths with my eyes and saw that it stayed on the top of a hill. The paths tend to be on the crests of the topology, and never goes through a local minimum. When it rains, water always runs off. In most places, mud can never run on.”
“What is at the local minima?” asked the first, probably just to be annoying.
“Trees.” replied the second.
Would you call the design of the pathways elegant?” asked the Guru.
“Yes” they replied in unison.
“I can certainly see that this park is a much nicer place due to antibugging techniques—elegant designs which don’t have the same problems that some lesser design would be prone too. So there’s no abugging needed when antibugging takes care of everything?” asked the second.
“There is no such thing as a design with perfect elegance. Not for anything non-trivial, anyway. A design that tries to be perfect everywhere would lead to paradoxes. Our hill-crest design doesn't to a thing for that big fountain. The perfectly elegant design would be a park without fountains, but we also have a feature that directly contradicts this. So what do we do?”
“Hmm” mumbled the first. “The fountain by its very nature fills up when it rains, and the area around it is flat by design, and as I recall its not at the top of a hill. The gazebo is at the top of the nearest large hill, overlooking the fountain and that big clock made from flowers.”
“That's the problem.” stated the Guru.
“Do we have to go there and figure it out?” continued the first, hoping not to give up his hammock. The second, still standing and leaning forward on a low-hanging branch, was more than willing to go look.
But the Guru made that unnecessary. “There are drains on the flat area around the fountain.” he said. The students, realizing that the solution was obvious once it had been stated, said nothing. “Putting in drains is an abugging technique. You cover what you can with antibugging, and then deal with the rest. Not having drains would be a bug, which would detract from the perfection of the park. But thanks to the drains, when it rains, it pours. Rather than standing on the flat ground, that is.”
“So how exactly does this antibugging stuff apply to our work? How can we recognize it?” asked the first.
“It’s easy to see what needs antibugging. When properly done, it’s characterized by a lack of problems, so you don't notice it. So, the rule of thumb is to look at the documentation or design for your code. If it contains phrases like ‘you can’t do this’ or ‘you must do this before you do that’, or ‘be sure to…’ then you have identified places that the code can be misused. Abugging would prevent such misuse by catching the attempt at compile-time or run-time. But with antibugging, those phrases would be missing, since the code would not be subject to such misuse at all.”
“Yesterday I was bit by a routine that could not be called until after a buffer was allocated by a different function.” the first related. “It took me two hours to find this bug. But before I fixed my code, I did as you taught me: make it impossible for this to happen again. I put a null-check in that routine, and then re-ran the program with my bug in place to make sure it was automatically caught. This time, the program stopped with an assertion, saving the next person who makes the same mistake two hours of debugging. Is what I did, adding the check, antibugging or abugging?”
“Good example.” he said to the first. “What do you think?” he asked the second.
“It’s clearly abugging, since you are dealing with a problem. The situation of ‘you must call this function before you call that one’ still exists, so you didn’t use antibugging. The mistake is caught automatically, but you can still make the mistake. As he said, his ‘fix’ was to save trouble for the next person who makes the same mistake.”
“On the nose.” the Guru said. “That’s ‘clearly abugging’, as you said. Now here’s one that’s not so clear: what if instead of a null-check, the function allocated the buffer itself?”
“Well, that sounds very much like the first one, but let me think…” mused the second. “It’s different because the results are different. With that fix, it doesn’t matter which order the functions are called in, that warning can be excised from the instructions. This must be antibugging.”
“So why didn’t he do that, if antibugging is better than abugging?” asked the Guru.
“Because he never thought of it?” she accused.
“No. I reviewed the situation when he found his bug—he had to come to me to check out the library that should have had the null-check. We discussed several possibilities, and the fix he made was the correct one.”
“OK, why didn't you like the second solution?” she asked the first.
“Because it would cause more problems.” he explained from repose. “I could have the second routine create the buffer automatically if needed, but with what size and modes? Reasonable defaults would not seem reasonable for everyone. It would open up the possibility of a new kind of mistake—getting the wrong buffer mode because you didn’t create it explicitly. That would cause a long debugging chore and is really no different from my null pointer problem.”
“Plugging the hole for you simply opened a hole for someone else.” The Guru gave her a nod, so she continued this line of reasoning. “It’s like building a stone wall with one stone too few. No matter how you arrange the stones, there will be a hole somewhere.”
There was silence for a few moments in the shade of the Oak.
“If only it didn't matter.” the second spoke at last. “The second solution would be good if it didn’t cause problems to have the buffer in the wrong mode, or if there was simply no need to have the user explicitly set it before continuing.”
The first jumped in, “I was thinking about that code, and I have a couple ideas, but it’s not a quick fix. It would be designing it differently all around.”
“If the code had been written that way in the first place, the buffer would be like the elephant. That is antibugging.” Said the Guru. And the students were enlightened.
Code Reviews series | Magazine top | previous part | next part