Saturday, July 25, 2009

fragile (code) - handle with care


I'm working on a "legacy" software system. Legacy means different things; in this case I mean it has been around for a few years. The original developers are long gone, and there are numerous sections which are a mystery. Even more annoying, the code produces mystery entries in the database. There are columns with fields that have dual, hidden meanings. There are extra rows for undocumented special cases.

One of my colleagues, let's call him "Mr Eager-Beaver," recently decided he'd had enough, and removed some lines of code which had been adding apparently extraneous information into the database. He's not an idiot, so he tried doing this on a test system first, and found that nothing went wrong. So he argued for committing the change, and so it was.

Unfortunately, the application is extremely large and complex. Being finite, I'm sure you could design a suite of tests which check every possible feature in the application. However, the company motto is "we will test no code before its time." The end result is that we actually have a very limited suite of tests for this application. Further, from a QA perspective, you can't just go in and hit a few pages, click a few buttons, and declare a code change has done no damage.

So ever since this change was committed, we've been uncovering bugs related to it. In a few dusty corners of source code, the application expects to find the missing information in the database, but doesn't, and barfs.

It wouldn't be so bad if these bugs were easy to find, or if they could all be dumped on the original hero who did the refactoring. No; what happens is that you have no idea what is causing the bug until, after several hours of research, the realization dawns on you: "Oh, this is due to Eager-Beaver's code change!" At that point, you can fix the thing pretty easily, and there's no point in reassigning the bug to him.

So far I have had two such bugs assigned to me. Eager is actually a pretty decent guy, so while I do get an urge to come over and give him a good metaphysical ass-kicking when I finally discover the source of the bug, I don't. I can only hope he's been assigned his own fair share of these bugs. And that he'll be as nice to me, whenever he uncovers some code crime of my own.

Saturday, July 18, 2009

stack overflow

stack overflow

I've never had much need to write recursive functions in my programming career; I've written one perhaps two or three times, all told. Hence, I haven't paid them much attention, and still don't really know much about them.

It turns out that interviewers are quite keen on asking questions about recursion; perhaps this is because there's a heavier focus on them in CS classes than there is a use for them in reality?

The first time I encountered a question about recursive functions during an interview, it kind of threw me. Why ask a question about something so rarely used? My response was that, yes, I've written them, but rarely, and I try to avoid it when possible because I find them confusing - I have a fear of writing something that will result in an infinite recursion in some subtle case. It was during this interview that I learned that recursive functions can lead to stack overflows. Thereby proving that interviews can be useful, at least as learning experiences.

Well, today I caused my very own stack overflow by creating a recursive function, albeit unknowingly! I had created a Java class which extended another class, which mostly had getters and setters. The intention was to eventually implement these methods in the child class, but meantime I had the child class override the parent's methods, and just had them return the results of the super class methods. For example, I had the getFoo() method call the superclass method, super.getFoo(), and so on. Only, in one case, I inadvertantly left out super and had the getBar method return getBar - so the method called itself recursively. When I ran the code, I immediately saw this huge stack trace in the output. At the top it said "Exception in thread ... java.lang.StackOverflowError. This was followed by 1024 repeated lines giving the method which had generated the error.

I don't recall ever experiencing this in my entire career, and I could immediately see what had gone wrong, so I found it very entertaining (perhaps I am too easily amused).

Wednesday, July 15, 2009

the blame game

bug
There are a couple of developers where I work who are in the habit of making public announcements when other people's bugs are found. They'll write it in a bug report: "I found these lines of code written by X", followed by the egregious offending lines of code. Or they'll announce it in a meeting: "Yesterday, I was working on a bug that had been assigned to me, but it turned out to be a problem introduced by Y's implementation of the foo feature."

Is this normal, common, or in any way productive? In my view, it is counter-productive: there's an element of public humiliation in it, where there doesn't need to be. And it does no good that I can see; rather it engenders a hostile and competitive work environment, whereas I prefer a cooperative one.

I am probably too thin-skinned about this, but it really grates on me. My gut reaction is to want to retaliate by publicly pointing out every bug made by these finger-pointers.

However, I see no reason to publicly call someone out on such a thing. Instead, I apply my default behavior to everyone equally. If I find something wrong in someone else's code, I fix it, and in the bug report, I'll write something like "the problem was in the implementation of foo in class Blah, where == was used instead of the equals method." If the person is still at the company, usually I'll walk on over to them, point out the problem, and ask if they agree with my solution, or if they want to fix it themselves. I don't do this to rub their noses in it, but because that's the way I'd like to be treated - I want to know when I've made a mistake, and be given a chance to correct it.

To be fair, the finger-pointers do, on rare occasions, point out bugs of their own making. So maybe they're just applying their own standards to everyone. Still, it seems like the standard (and friendly) behavior is to point out a bug, but not call attention to the bug creator. I wonder what motivates those who insist on playing the blame game.

Saturday, July 11, 2009

how can you be so sure?


I'll preface this story by saying that I don't think I'm unusual in my confidence level. I am comfortable and generally feel confident with what I know, and am not so confident when straying into areas where I have less experience.

That being said, when the code suddenly stops working the way I think it should, my confidence level drops like a stone. Sometimes, I'll immediately assume that there's some hidden rule, unknown to me, causing the strange behavior.

Yesterday, as I was stepping through the code with a debugger, I saw something happen which just isn't supposed to happen. I had an object of type Apple, which extends class Fruit. (Needless to say, class names have been changed to protect the innocent). Both classes had a getSize() method. When that method was called, the getSize() method of the Fruit class was being exercised, not the corresponding method of the Apple class. It went something like this:

  Fruit fruit = doSomethingComplicated();
  int sz = fruit.getSize();
  ..
}
protected Fruit doSomethingComplicated() {
  ...
}

Way down the call stack, doSomethingComplicated() was creating an instance of Apple, so fruit.getSize() should use the getSize() method of Apple, not Fruit. Yet I could see that the Fruit getSize() method was being called.

Just as I noticed this problem, and was thinking "whoa, what's that about??", a coworker came over and I explained what I was seeing to her. She seemed pretty sure that it was simply not happening, even though I could show her by stepping into the debugger that indeed, it was happening. Basically, I believed what my eyes were telling me, and she didn't.

She was right, and I was wrong. I had failed to notice that midway down the call stack, a new instance of Fruit class was being returned, not the original instance of Apple that I had seen created at the bottom of the call stack. I don't feel too bad about not noticing this, since it had escaped the eyes of my coworker too, even after we had stepped through with the debugger a couple of times.

What makes me feel bad is that I had such uncertainty about the way inheritance works in Java that I wasn't sure the behavior I saw was completely insane; in contrast, my colleague seemed convinced that something was totally wrong.

I really need to put some study time into relearning some of the basics, in addition to training on new material, to achieve that level of confidence!

Wednesday, July 8, 2009

females are better at documentation? c'mon...


was this code written by a man or a woman?
long code comment

I recently became aware that there's a stereotype that women write more "touchy-feely and considerate" code than men, interspersing it "with helpful comments and directions, explaining why they wrote the lines the way they did and exactly how they did it..."

I have my doubts about this sweeping generalization. Nevertheless, today I received some recognition from a colleague for the helpfulness of my written documentation in three places: directly in the code where I documented why a change was made, in version control when I checked in my code changes, and in my bug reporting comments. He told me that all of this information greatly reduced the amount of time that it took him to resolve an issue.

I don't think my documentation skills are due to some natural ability as a woman. I have a PhD, and as Terri points out at CU-WISE blog, documenting your research is a key skill ingrained during graduate school, if you don't already have it.

I guess I should be happy about being complimented for something, but I'd have been happier if it had been about my excellent coding skills. This was akin to being praised for tidy penmanship.

Tuesday, July 7, 2009

engineer vs bugzilla

bugzilla logo by Dave Shea
In my view, a good bug report contains an ordered list of steps to take to reproduce the bug. I realize this is not always possible (e.g. the bug is intermittent, and QA does not have the time or resources to nail it down).

In reality, I rarely see a sequence of steps in a bug report where I work. I haven't quite figured out why. I think that QA is often just poking around the application, trying things out. They do a sequence of steps, and suddenly something goes wrong. However, they haven't recorded the series of steps as they went along, so the reports go something like this:
Widget on the fribble panel sometimes vanishes. See attached screenshot. May have clicked the foo button three or four times in rapid succession before that happened, not sure, was doing some other tests at the time.
This kind of bug report makes life difficult for me. It means I have to spend a lot of time trying to figure out just how to reproduce the bug, time that could be better spent doing actual development work.

I suppose I could just mark such bugs as invalid, or reassign them back to QA, with a request for reproducible steps. I haven't done this, yet, at least not without a good faith effort to try to reproduce the bug. I get the feeling that QA doesn't take it well when you send bugs back to them in this way.

In my view, QA and development should all be one big team, trying to make the software work. In reality, it sometimes feels like the two departments are at war. Is that common in the industry? Is there a way to stop it?