tag:blogger.com,1999:blog-7359791525336117032.post8326471250582293878..comments2020-04-24T20:58:07.807-05:00Comments on Castles of Air: Search and destroy missions for your bugsAnonymoushttp://www.blogger.com/profile/05324968314168283095noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-7359791525336117032.post-33652003729815335522009-05-03T17:19:00.000-05:002009-05-03T17:19:00.000-05:00Hmm, I should add one caveat.
when dealing with ra...Hmm, I should add one caveat.<br />when dealing with race conditions .... turning up the debug level .... <br />will probably 'turn off' the bug.<br /><br />Writing multi-threaded programs ... it's bound to bite you in the behind<br /> once in a while and still remains a bit of black magic.<br />but then again, if it was easy ... anyone could do it, and where would that leave us, the skilled programers :D )Remko Duppennoreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-31477786017210788502009-05-03T17:10:00.000-05:002009-05-03T17:10:00.000-05:00In my experience it is vital to have a system in w...In my experience it is vital to have a system in which you can turn on logging at runtime, and preferably in steps.<br />I know some people advocate the DEBUG preprocessor way with removing all debug statements at runtime, but if you do that, when the shit hits the proverbial fan, you are probably looking at a big black box.<br />We tend to have problems which are difficult to reproduce, as most of the time it will be a concurrency/race condition kind of thing, most of the time there is no good way to try and reproduce the problem in our development environment (the customer may have a way faster machine then we have at out disposal or we just don't have the external connection/facilities needed to reproduce the problem)<br />Extensive logging which we can tune per facility and level saved our bacon numerous times.Remko Duppennoreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-4955601229167397052009-03-16T15:30:00.000-05:002009-03-16T15:30:00.000-05:00Derick,You are correct, of course. In an ideal wo...Derick,<BR/><BR/>You are correct, of course. In an ideal world, you should be working on code that has unit and integration tests built in, so that it's easy to pinpoint the source of the failure. As a long term developer, you should strive for that to maintain stable code where it's easy to find errors.<BR/><BR/>We don't live in an ideal world, though, and we don't always have the power to go back in time and throttle the guy before us into writing correct code. I'm speaking from the perspective of a guy who's relatively new on a particular job, and there's a large project written by predecessors with very few tests built into it already. Inexperienced programmers are going to run into this situation many times in their career, so they might as well learn to deal with it early.<BR/><BR/>I strive to replace existing stuff with tests to catch future problems, but in the short term, everyone's faced with the basic problem: "There's a bug. There's inscrutable code that I didn't write. What's causing the problem?"<BR/><BR/>After you track the problem down, then you can start wrapping tests around that section of code to get it under control. But short of a clean sweep where you rewrite everything at once to confirm to best practices, you can't assume that the error has already got test coverage.<BR/><BR/>I admit that test-driven development is still relatively new to me, and something I'm working to get better at.Anonymoushttps://www.blogger.com/profile/05324968314168283095noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-66021226015328868272009-03-16T13:59:00.000-05:002009-03-16T13:59:00.000-05:00that honestly sounds like a very slow, painful way...that honestly sounds like a very slow, painful way of finding the bugs in a system. <BR/><BR/>I prefer the TDD approach where i code my system to make tests pass (unit tests, integration tests, test automation of UI, etc, though i'm only beginning to do UI automation). then when the system doesn't do what it should be doing, i should have a test that is failing, and telling me exactly where the problem is, without having to hunt through so much code. <BR/><BR/>In this situation, finding the bug is no longer 99% of the work. You can see a failed test in the test report, go right to where the failure occured, and eliminate 99.999% of the codebase from the outset. this makes finding the bug a much smaller percentage of the solution.<BR/><BR/>I understand the value of this approach, though. There are times when you just have to dig into the debugger or otherwise hunt for a bug, to figure out what's going on. for example, when you have a bug but all tests are passing... the first thing you do is figure out why it's not working with the sort of approach you're talking about. then, write a test to prove that it's a bug by specifying what it should be doing and seeing the test fail. then fix the code so the test (and all other tests) passes. now i have a regression test to ensure that this bug is never introduced again. <BR/><BR/>:)Derick Baileyhttps://www.blogger.com/profile/11278436552796934211noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-76323243852391217392009-02-28T09:13:00.000-06:002009-02-28T09:13:00.000-06:00Hi Russell and all, I came across this blog on the...Hi Russell and all, I came across this blog on the atheist blog, good stuff.<BR/><BR/>I do QA for a living so I normally _have_ to test my code before checking it in (unlike engineering proper hah! no just kidding). <BR/><BR/>Some things I've learnt about writing debuggable code (because I've had to debug so much of it):<BR/><BR/>- don't be clever where you don't need to be clever, at least when just trying to get the code to behave the way you want. This includes things like highly clever branching code:<BR/><BR/>if(a()-b())<BR/>{...}<BR/><BR/>just check for non-zero in the usual way:<BR/><BR/>if (a !=0 ){}<BR/>if (b != 0){}<BR/>Much more readable (and most compilers/interpreters are very good at branch optimization anyway).<BR/><BR/>- avoid code that obfuscates the flow of control, i.e. I commit this kind of sin a bunch in C# and Java:<BR/><BR/>foo = String.Split("/", bar).Replace("\\","/").Length;<BR/>etc...<BR/><BR/>I'm paying for this at work already just having to figure out what I wrote a few months ago.<BR/>This kind of stuff puts you at the mercy of your debugger and how well it displays stack crawls, locals etc.<BR/><BR/>- don't #define things to death (in compiled languages like C and C++). Macro expansion/conflict bugs are often very hard to figure out both at compile and runtime. Use typedefs instead (which are better anyway because they obey the type system of the language in C/C++). This is partly why languages like Java don't have #define facilities ;).<BR/><BR/>- Exception abuse. Please dont do things like<BR/><BR/>try<BR/>{<BR/>...<BR/>}<BR/>catch(...)<BR/>{<BR/> std::cout << "oh shit!";<BR/> return 1;<BR/>}<BR/><BR/>most debuggers can't follow exception propagation, so don't use them for control-flow operations like this (this just subverts the purpose of exceptions anyway).<BR/>Some of my code at work has some of this, for which I should be flogged (well I am because I have to maintain it hah!).<BR/><BR/>Less obvious things are stuff like unrolling your own loops and things like that....<BR/><BR/>Finally, make sure you have debug versions of any 3rd party libraries your code may use. Debuggers get very confused if they have to try to go through code sections without debug information.<BR/><BR/>Just some things that have occurred to me drinking my morning coffee...<BR/><BR/>LSlshttps://www.blogger.com/profile/17901508236729383702noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-83431566124195869922009-02-27T23:12:00.000-06:002009-02-27T23:12:00.000-06:00Along the lines of different backgrounds, the Web ...Along the lines of different backgrounds, the <A HREF="https://addons.mozilla.org/en-US/firefox/addon/60" REL="nofollow">Web developer toolbar</A> for Firefox has the option of outlining elements based on different criteria on a page, which is a handy way of doing it without having to add any extra code.Zurahnhttps://www.blogger.com/profile/06325048684652466640noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-14728562441356440072009-02-27T16:58:00.000-06:002009-02-27T16:58:00.000-06:00It's funny that you mention that technique, Arensb...It's funny that you mention that technique, Arensb, because I was just doing exactly that with a stubborn jsp page about 20 minutes ago. Horrible table design, it was. Horrible.Anonymoushttps://www.blogger.com/profile/05324968314168283095noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-38522418855506967522009-02-27T16:54:00.000-06:002009-02-27T16:54:00.000-06:00One technique I've found useful when debugging lay...One technique I've found useful when debugging layout, in either GUIs or web page, is to give each element a distinctive background color: red, yellow, orange, purple... That way, you can see that the misplaced button is on a blue background instead of the orange area where you expected it, and narrow down the scope of your search.<BR/><BR/>I showed an app to a coworker while I was debugging it, and he christened it "Angry Fruit Salad".arensbhttps://www.blogger.com/profile/15251547886605570242noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-628111435291184592009-02-27T16:27:00.000-06:002009-02-27T16:27:00.000-06:00Added Shane's correction to the post body.Added Shane's correction to the post body.Anonymoushttps://www.blogger.com/profile/05324968314168283095noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-62578122282451823782009-02-27T15:13:00.000-06:002009-02-27T15:13:00.000-06:00I'd have to say it's definitely debugging by far. ...I'd have to say it's definitely debugging by far. Even when you're developing new code, you're still "debugging" by thinking ahead all the time to see what you could do to break your own program and trying to catch those errors in advance. Effectively you start looking for bugs even before they exist.Anonymoushttps://www.blogger.com/profile/05324968314168283095noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-87056932471791740992009-02-27T14:00:00.000-06:002009-02-27T14:00:00.000-06:00Good post.Which takes more of your time: coding, d...Good post.<BR/><BR/>Which takes more of your time: coding, debugging, or maintaining?James A. Brownhttps://www.blogger.com/profile/12580984579089010427noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-84846717697553572162009-02-27T12:32:00.000-06:002009-02-27T12:32:00.000-06:00Yeah you're absolutely right... I was going to say...Yeah you're absolutely right... I was going to say (but forgot) that the best way to do this is to create your own "debug" function that can be globally turned on or off.Anonymoushttps://www.blogger.com/profile/05324968314168283095noreply@blogger.comtag:blogger.com,1999:blog-7359791525336117032.post-69775150946566838512009-02-27T12:14:00.000-06:002009-02-27T12:14:00.000-06:00Distinctive string or not, anytime you have to "ma...Distinctive string or not, anytime you have to "make sure you don't miss any", you should automate it somehow. Set a global constant "DEBUG", or use built-in facilities to automatically deal with debug statements when you do a release versus debug build.<BR/><BR/>If you have to go back and search and find all occurrences of something, you will miss at least one. It reminds me of a story I once heard of a generic office application that was released with a very obscure bug that would happen only in a specific, very rare program state. A debug window was left that would pop up--complete with a joke picture of one of the developer's bare ass. The program was subsequently re-classified as "Adults Only". Might be partially or completely an urban legend, but it illustrates the point.Shanehttps://www.blogger.com/profile/16772934680218562238noreply@blogger.com