General

Debugging steps

  1. Determine what is working in the realm of the problem.

  2. Determine precisely what is not working.

  3. Simplify the problem. Attempt to simplify the test case whilst retaining the problematic behavior.

  4. Generate hypotheses.

  5. Test hypotheses using divide and conquer. Taking each hypothesis in turn, dive into the system and find a sub-unit where you believe that something may be going wrong. Then run your small test-case and look at the internal behavior before and after that sub-unit. If you find a problem before that sub-unit, then your hypothesis may have been wrong, and you at least know that you need to investigate further back towards the input of the system. If, on the other hand, the input to that part of the system seems correct, but the output seems incorrect, then you have support for your hypothesis, and you can zoom-in more closely.

  6. Think of other versions of this class of bug.

  7. Generate anti-regression tests.

  8. Fix the bug(s).

  9. Check that the tests now work.

  10. Check the original simple case.

  11. Check the original issue.

  12. Document the fix.

  13. Note any other possible bug classes.

  14. Release.

Debugging approaches

  • Brute Force Method

  • Backtracking. This is additionally a reasonably common approach. during this approach, starting from the statement at which an error symptom has been discovered, the source code is derived backward till the error is discovered.

  • Cause elimination method. In this approach, a listing of causes that may presumably have contributed to the error symptom is developed and tests are conducted to eliminate every.

  • Program slicing. This technique is analogous to backtracking. Here the search house is reduced by process slices.

Tips and Tricks

  • The most important step in solving a complex problem is to break it down into the smallest possible pieces.

  • Start with code that already works.

  • Run your code every time you make a small change.

  • Single Responsibility Principle (SRP). One of the most important steps of debugging is to prevent bugs from being created in the first place. An important concept to which your code should adhere is the Single Responsibility Principle.

    Each class and method should have a single responsibility, and should call on other classes or methods as necessary to achieve additional functionality. Try to apply this principle at each scope of your code.

  • Descriptive Naming. Ensure every variable, function, class, or other element you name is clearly descriptive of what it holds, returns, or does. For instance, a method that checks the validity of an email address and returns a boolean should be called isValidEmail. We're able to assume a function called appendDateToString will do just as its title says and add a date to the end of a string, because the name is descriptive and clear. You might call the return of that function appendedStringWithDate.

  • Don't Repeat Yourself (DRY). If you find yourself writing the same code multiple times, put it in a separate method and call that when necessary. This creates fewer potential points of failure and will make refactoring easier, if necessary.

  • Error/Warning Messages. Error messages and warnings are provided for your benefit. If you get an error or warning message, take a moment to read through it. Many simple, but unapparent, problems will be made clear, and you will now have a point from which to start your search for a solution to more complex problems.

  • Check Variables. A good place to start debugging is to track the value of your variables. You may find that variables don't hold the values you expect, or don't hold any value at all. There are several ways to examine the values your variables hold.

  • Logging. It's good practice to insert logs as you write your code, long before any problem arises, so you can more easily visualize the flow of your program as it runs. An effective log should contain a brief description of where it is, what is going on, and what the contents are of relevant variables. Such a log message might look like this:

  • Take a break and walk away from the keyboard. It’s really easy to get caught up in the details of your current implementation. You get bogged down in little details and start to lose sight of the forest through the trees.

Process

  1. Try debugging by yourself. Every major problem you come across can be broken down into smaller problems, and almost every one of those smaller problems has been experienced and solved by someone else.

  2. Search in Google. This should always be your first stop. Simply searching for an error code or a clear description of the problem you face will bring you multiple potential solutions. If relevant results don't show up, increase the specificity of your search terms. Conversely, you can abstract your search to more generally describe the problem at hand.

  3. Search in documentation. Official documentation is an often-overlooked resource for problem solving, and should be the starting point for much of your debugging. Use documentation to understand the capabilities, properties, and characteristics of the elements of your code. If you're not sure what something can do, or how to interact with or implement a piece of code, dig into the documentation.

  4. Ask your teammates.

    1. Don't spend more than an hour trying to solve a problem on your own.

    2. Think and formulate a precise question before you ask.

    3. Ask not what the solution is, but how you can solve the problem on your own.

    4. If you need to solve it on the spot, prepare and setup your environment before hand.

    5. Only then ask or invite over your teammate.

      1. Ask your question and explain what you’re trying to do.

      2. Show the code that’s giving the error.

      3. Show the entire stack trace including the error message.

      4. Explain 2-3 things that you’ve tried already and why they didn’t work.

Last updated

Was this helpful?