File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Beginning Java and the fly likes Strategies and tactics for bug fixing - for beginners Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of JavaScript Promises Essentials this week in the JavaScript forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Strategies and tactics for bug fixing - for beginners" Watch "Strategies and tactics for bug fixing - for beginners" New topic
Author

Strategies and tactics for bug fixing - for beginners

Andy Jack
Ranch Hand

Joined: Nov 22, 2012
Posts: 257
I create my own test cases which test for boundary conditions and such. I don't know how to develop professional style test cases, but we'll leave that for another day.
Right now, i find bugs but i have a hard time fixing them. Please tell me if there are any tactics or strategies that can help to fix bugs faster. More importantly, are there any tips
or techniques to reduce the chances of having bugs in my final code ?

Thanks


Java Newbie with 72% in OCJP/SCJP - Super Confused Jobless Programmer.
I am a "newbie" too. Please verify my answers before you accept them.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39755
    
  28
Odd. Bug fixing is usually quick and simple. It is usually finding the bugs that takes the time.
Adhere strictly to the usual conventions of formatting, identifier spelling, object orientation (eg encapsulation, data hiding).
Design your algorithms and classes on paper before you try to commit them to code.
Use the features (eg generics, @Override annotation) which will produce errors messages from the compiler; remember the compiler error is your friend.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8159
    
  23

Andy Jack wrote:I create my own test cases which test for boundary conditions and such. I don't know how to develop professional style test cases, but we'll leave that for another day...

Well, for starters, I'd get a proper testing app - of which one of the most popular is JUnit - and try and get into the habit of writing tests while you're programming.

Please tell me if there are any tactics or strategies that can help to fix bugs faster.

1. Document your programs well. If you know what a method is supposed to do, it's usually much easier to work out what went wrong if it doesn't. Learn how the javadoc comments work, because they can be invaluable.

2. Avoid situations where references can be null. NullPointerException's are some of the most pernicious and hard to find of all, because they are thrown automatically by the JVM, and sometimes miles from where the problem actually originates. So:
  • Don't define reference fields without initializing them, either directly or in a constructor.
  • Don't write methods that return null. There's usually a much better alternative (eg, if you're returning an array or List, return a 0-length one).
  • If you throw NullPointerException yourself, provide a message with it. Indeed, if you throw ANY exception, provide a message that includes the values of all relevant variables.

  • 3. Never ignore exceptions. Specifically, never do anything like this:at the very least, print out the stacktrace; but better still (especially while you're testing) may be to simply let the program fail, in which case you will get the stacktrace automatically.

    And when you get the stacktrace, read it carefully. It contains tons of valuable information.

    More importantly, are there any tips or techniques to reduce the chances of having bugs in my final code ?

    Yes. Program defensively.
    Whenever you write a method, think not only about what it should do when things go right, but also when they go wrong; and make sure you have a strategy in place for when it does.
    Test all arguments to your methods, and throw IllegalArgumentException (again, with a good message) if they're wrong.

    Remember: the faster you find an error, the easier it is to correct it, so a good maxim to follow is: fail early, and fail LOUD.

    HIH

    Winston

    Isn't it funny how there's always time and money enough to do it WRONG?
    Articles by Winston can be found here
    Campbell Ritchie
    Sheriff

    Joined: Oct 13, 2005
    Posts: 39755
        
      28
    Example of Winston’s last point:-
    Junilu Lacar
    Bartender

    Joined: Feb 26, 2001
    Posts: 4989
        
        8

    C.A.R. Hoare, winner of the 1980 Turing Award, wrote:There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.

    My strategy for avoiding and finding bugs is to write code of the first kind. To do that, you need to choose good names that clearly state the intent, have good separation of concerns, and maintain the code in a state such that it is well-factored into single-minded classes and methods. My methods are generally no longer than 10 lines of code. Others average even fewer; I write/refactor to many single-line methods. Compose method is one of my goto refactoring techniques.

    Without clarity and conciseness, hunting down bugs in your logic is much harder than it needs to be in most cases. The discipline of Test-Driven Development also helps me tremendously.


    Junilu - [How to Ask Questions] [How to Answer Questions]
    Campbell Ritchie
    Sheriff

    Joined: Oct 13, 2005
    Posts: 39755
        
      28
    So, I clicked on the compose method link you posted and the top hit was this. Please read it.

    I don’t like multiple return or return in the middle of a method. I know people will disagree with me about that, but I can think of two ways to enhance their suggested solution, both making the programming more defensive:-Both my versions have the advantage that the calling code can “find out” whether the add method was called successfully. The second attempt is much more assertive, and the boolean return is now redundant:-
    Matthew Brown
    Bartender

    Joined: Apr 06, 2010
    Posts: 4457
        
        8

    Campbell Ritchie wrote: I know people will disagree with me about that...


    True . I think the original version is much clearer than the first "improvement" (and it could return false inside the first condition without affecting the readability if that was desired).

    I would prefer the second approach in general, though it does actually change the behaviour, and that may not always be desirable or (if the code is already released) possible. But if something is considered an error, I would always prefer to throw an exception, following Winston's earlier advice.
    Campbell Ritchie
    Sheriff

    Joined: Oct 13, 2005
    Posts: 39755
        
      28
    I prefer the version which throws the Exception, too. It is exactly how what you get from this behaves.
    Campbell Ritchie
    Sheriff

    Joined: Oct 13, 2005
    Posts: 39755
        
      28
    And you cannot replace a previously‑released void method by one with a return type.
    Winston Gutkowski
    Bartender

    Joined: Mar 17, 2011
    Posts: 8159
        
      23

    Junilu Lacar wrote:My strategy for avoiding and finding bugs is to write code of the first kind.

    Me too; but in 35 years, I've never quite mastered the art completely.

    @Andy: Junilu's point is a good one, however. An ounce of prevention is worth a pound of cure; and to that end, learn to Write Dumb Code.

    Winston
    Winston Gutkowski
    Bartender

    Joined: Mar 17, 2011
    Posts: 8159
        
      23

    Andy Jack wrote:More importantly, are there any tips or techniques to reduce the chances of having bugs in my final code ?

    One more - although this has more to do with preventing bugs than finding them - protect encapsulation.

    Put private in front of everything - that is: fields AND methods, whether instance or static - until (or unless) you know that they will be used outside your class. Additionally, don't create getter and setter methods (especially the latter) willy-nilly.

    Also: put final in front of everything - especially classes - again, until (or unless) you know that they will need to be extended (in the case of classes or methods) or changed (in the case of fields).

    You can always change a private or final entity later on if you need to. What you can't do is change it back.

    Winston
    Junilu Lacar
    Bartender

    Joined: Feb 26, 2001
    Posts: 4989
        
        8

    Campbell Ritchie wrote:I don’t like multiple return or return in the middle of a method. I know people will disagree with me about that, but I can think of two ways to enhance their suggested solution, both making the programming more defensive:

    IMO, the guard/sentinel clause is an acceptable exception to the single exit point "rule". While the enhancements you suggested are reasonable, they change the original behavior. The example is meant to show how much easier it would be to understand the logic if it were composed of method calls with intention-revealing names rather than have all the implementation details in a single method.

    Some coding anti-patterns are addressed by the refactoring: arrowhead code (unnecessary complexity) and obscure intent (drowned out by implementation details) and multiple responsibilities in one method.
    Campbell Ritchie
    Sheriff

    Joined: Oct 13, 2005
    Posts: 39755
        
      28
    I am going to have to post more things people disagree with; it makes for such interesting discussion afterwards
    Martin Vajsar
    Sheriff

    Joined: Aug 22, 2010
    Posts: 3611
        
      60

    Winston Gutkowski wrote:at the very least, print out the stacktrace; but better still (especially while you're testing) may be to simply let the program fail, in which case you will get the stacktrace automatically.

    My advice would be to always let the program fail, especially in production. Any exception to this rule must be well grounded and documented.

    The reason is that error messages in logs may go unnoticed for days years, and even if a message is displayed to the user, the sad truth is that users do not read messages. Allowing a program to continue after a failure might mean that the incorrect results of the program are then used as if they were correct.

    It's true that I've in my entire career developed applications where the accuracy of the results was crucial (financial applications and the like). One of my first projects involved Monte Carlo simulations, and the entire job took many hours to compute. To save the useful work in case of failure, I've decided - on my own - to skip failed iterations and not include them in the results (of course, warning were issued and printed), allowing the program to finish and produce results. I was quite reprimanded at that time, so my strategy was fail-deadly ever since. I've never regretted that.

    But perhaps other domains are more forgiving.
    Winston Gutkowski
    Bartender

    Joined: Mar 17, 2011
    Posts: 8159
        
      23

    Campbell Ritchie wrote:I am going to have to post more things people disagree with; it makes for such interesting discussion afterwards

    Agreed. Pot-stirring is fun. In fact, I'm surprised my 2nd post didn't get any comments about 'overkill'.

    Winston
     
    wood burning stoves
     
    subject: Strategies and tactics for bug fixing - for beginners