You know the feeling. It's happened to all of us at some point: you've pored over the code a dozen times and still can't find a problem with it. But there's some bug or error you can't seem to get rid of. There just has to be something wrong with the machine you're coding on, with the operating system you're running under, with the tools and libraries you're using. There just has to be!
this is great reminder, but with the now programming culture most of us working with beta stuff sometime alpha and not released bits so depending on the current programming culture the percentage you stated from Code Complete is lower - you should take in account what lib and tools developers are working with today.
Interesting enough, the exact opposite happened to me. I was building an application using Java 1.6.0 Update 3, and I kept having odd behavior with the JComboBoxes for the GUI (you could only select the first item on the list after selecting a later item, which causes problems when you only have one item in the list!). Needless to say, it was very odd behavior.
Being a new developer, I made the assumption it had to be in my code (it was my first application using Javaās Swing package). After trying every card in the book, I ran it in Java 5, and it worked perfect! There was a bug in Java 6 with the GUI.
Anyway, my number one rule in programming: Never Assume Anything!
I agree with the advice in general given in this blog post and thatās what I would advise most other programmers too.
But there have been more than a few cases within the past few years where I blamed myself and my code (I would have been tearing out my hear if I actually grew it long enough to tear at), only to find out after isolating the case that the bugs within some framework or OS bug. Iāve even had an instance in my previous job where some networking code was broken because of buggy firmware implementation on the hardware layer. And everytime its been some bug somewhere in the deeper layers, it took hours of painful work to find out about it and isolate it.
So although I do generally blame my own code before blaming anyone elseās when it comes to tracing bugs, I have learned to keep my eyes wide open for the possibility that it may not be my fault.
I have to agree with Robert above, Never Assume Anything!
I donāt think Jeff was claiming that everything but your code is 100% error free. Of course there are errors in other things; they are, after all, someone elseās code.
The point is that you donāt go bothering the people who made the other things telling them there are bugs until you have done your best to rule out your own code. Itās so tempting to think everything you have done is right and that the problem MUST lie with another component, to then stir up a big fuss, only to later realise that the bug was indeed in your own code and have to go around apologising. Iāve done it. Quite recently, in fact. Weāve all done it, I imagine. Itās an ever-tempting course of action, so itās really important to keep the underlying message here in mind: āItās always your fault.ā That is hyperbole, of course; it isnāt really always your fault, but you have to think it is your fault until you have proven otherwise.
If you think thereās a bug in something else then the best thing you can do is strip away as much of your own code as possible and produce an extremely simple bit of code which reproduces the bug. Then itās easy to prove where the fault is.
All too often the problem is that the bug is our own fault and is due to our misunderstanding of how a component works. In those cases itās easy to see why we assume the bug is somewhere else: We look through our code over and over and everything looks perfect, but only because we have an incorrect view of how it should be.
I often find myself staring at the code, often to find no problems, Iāll pass it to another programmer, heāll find no problems. 3 days later ill still be banging my head.
Iāve never read anything more true than this! Iāve got a friend (co-worker) who always seeks the reason for failure in the 3rd party even if its PHP itself.
Thatās why our boss says about us:
He is a fighter-coder because he always FIGHTS with the code.
Iām the programmer because I make things work, no matter if the failure was my fault of someoneās else.
Just the other day a programmer where I work was faced with a process that was dying with a SIGABRT. He looked at the stack trace and found the signal was being generated on a line that contained an assert(). Somehow he managed to convince himself that the compiler was generating the wrong code and getting the assertion test backwards!!! I arrived at the office that morning and found in my inbox a mail from late the night before with a detailed disassembly of the code in question, along with references to the Intel IA-32 specification showing the compilerās error.
I opened the code, and put a āprintā statement in right before the assert(). What do you know, the value being asserted was 0.
Walking away from the specific bug and getting a good nightās rest is crucial to problem solvingā¦ as Iām sure you know. Staring at the problem causes me to go bug-eyedā¦ refreshing the brain does wonders.
When, watching your code run in the development environment, you see the system tell you that boolean literal True has a value of False, you really are seeing a bug in the tools, and itās time to restart the machine, because something has gone deeply wrong in a core library somewhere, and just restarting the environment wonāt suffice.
Ask me how I know this.
(Now, the other 999 out of 1000 times, the bugās my fault.
In almost 30 years of software development, the number of bugs Iāve found attributable to compiler/tool bugs is probably something like five. So Iāve learned this lesson.
But thatās not to say weird things donāt happen. Many years ago, I was debugging a complex computation in a Lisp program and just going nuts, the behavior made absolutely no sense. Then, in frustration, I typed ā2.0 + 2.0ā to the command promptā¦and got back something like ā256002.0ā as an answer. The systemās floating point extension card had failed in a way that returned wrong answers without raising exceptions.
YOU RUN IT, AND IT DOESNāT CATCH THE EXCEPTION! Instead, the spl_autoload handler I registered catches it and prints out your āfooā extension.
Clearly it had something to do with how the language was being executed. So I changed the OPCODE CACHE to something else (XCache nistaed of eAccellerator) and it worked.
But now the question ā WHY is this happening? Am I just going to have to tell people who use my stuiff to NOT use eAccelerator? There must be something in my code taht I did that creates this bug in eAccelerator. But what?
The worst kinds of bugs are the ones you canāt track downā¦
My colleague spent something like two days on a problem that he was convinced was his fault, because he thought .net that was so tested and quality assured possibly couldnāt contain a defect. Meself had a more experience on the gui parts of .net and kindly insisted that there may be an error. And after posting on the MSDN forum we found out that, yes, there was a bug.
I agree totally, take responsibility and assume itās your fault. But donāt be stupid. GDI/GDI+ for example contains a whole lot of funny things.
I totally agree! It is such a common situation that you describe in the first lines of your post: totally frustrated with a stupid bug that must be in a few lines of code youāve been looking at for a long time (which might not even be your code in the first place). Then if you do admit that the fault is in the code itself (and not the programming language, library, OSā¦), then there still a danger of choosing the wrong solution. Say you made some changes that did the trick, but you donāt know why or how those changes solved the issue. But you donāt care; you solved it, commit the fix and go on with more interesting work. Obviously this will make things worse instead of better; for the solution too code ownership is code responsibility.
But I donāt think being an humble developer should be a goal for any of us. Being humble is indeed good - but it is not a professional goal of mine.
My rule of thumb when dealing with bugs is: āif you blame a component, or anything that you have not written yourself then you have to prove itā. Always try to reduce the problem or the bug to minimal example where you can isolate the problem from the rest of your application. If you canāt isolate the bug, then there is always the assumption that the bug is in your code.