Following the Pareto rule, a programmer spends only 20% of his time for really useful things.
I spend 80% of my time debugging, fixing small things to get everything working.
Is there a way to spend less time debugging?
Software Engineering Stack Exchange is a question and answer site for professionals, academics, and students working within the systems development life cycle. It only takes a minute to sign up.Sign up to join this community
But still, in most cases you'll be much more productive spending 20% of your time on coding and 80% on testing and debugging. 100% of a week is much more than 20% of an hour. If debugging is what you need to get things done, than debugging is not a waste of time and you should not be bothered with "improving" this proportion.
After I started applying unit testing I found that the code I wrote became better structured. It was then easier to avoid and spot bugs. I spent less time debugging, but more time with writing unit test.
I also think that the time invested in unit tests has a better return of investment then debugging. After a debugging session I just fixed the code. The same bug can appear weeks later and I have to debug again. If I write a unit test the bug is documented as a unit test and later acts as a regression test. If the bug appears again the unit tests reveals this to me.
Unit testing will help as hopefully if you introduce bugs they will break before your production code - well written unit tests will also tell you exactly what broke.
That'll get you most of the way, but for 99.999% of projects you will still need to debug things from time time. The best thing to do here I find is to do 4 things:
My 80% is debug. I am fixing simple bugs and trying to make all working.
Start by writing unit tests, and try to have as high coverage as possible. Someone mentioned TDD, but I would go with BDD.
At the end, you'll most likely spend 80% on debuging complex bugs.
Understand the what and the why before you start writing code. Then use a methodology consistently. Which methodology you choose is not nearly as important as consistent repeated use of the methodology. If you want consistently good results, you need to do consistently good work and having a "method to your madness" is the first step to getting these results. As you identify issues you can adjust your methodology as needed and over time you will improve your development process, and hopefully fewer bugs and more new, meaningful development.
Most answers seem focused on how to reduce the number of problems you have to debug and that is valuable. However, debugging will always be necessary so it is useful to look at ways of getting faster at debugging.
Know how to use your version control software.
Improve your understanding of the programming language you use.
Adding to the comments for Unit Testing but it is only really good if your code has been separated to support it (e.g. MVC). If you can't implement MVC (or similar) (legacy project), unit tests don't work at all for your UI. I would then add automated UI testing (Microsoft Coded UI Tests, WaitN) as this will reduce errors in that portion of your code.
I would also highly recommend running static analysis tools (e.g FxCop/Microsoft Code Analysis, Resharper, JustCode for the MS world). These can find all kinds of common coding problems which can reduce the silly debugging tasks and focus more on debugging business logic.
Make it work, then make it fast, then make it pretty. Most bugs come from early optimizations or re-factoring at lines of code that were totally fine. If you go with object orientation don't repeat yourself, keep it simple and always make sanity checks of value ranges especially if your methods will still work at constraints. It won't help you make less mistakes but it will likely help you to spot bugs faster and therefore debugging takes less time.
I've been given a lot of thought to this problem recently- the simple answer is go read Don Norman's The Design of Everyday Things; Write code like you would design a product.
To paraphrase, good design minimizes error. That means, a few things, most of which you already do (although you may not know exactly why).
-Name functions intuitively. This is formally known as affordance. That is, a button affords to be pressed, a lever affords to be switched, a handle to be pulled, etc.
-Make it hard to write bad code. Check for bad input and throw errors sooner rather than later, use apps hungarian when appropriate, etc. These are called lockout functions.
-Use abstraction where appropriate. Short-term memory is weak.
-Documentation is obviously important, but it is the least effective of making sure code is used properly. In short, well-designed products don't need any documentation. (The most obvious way to see this is looking at bad examples: namely, doors with handles that you're supposed to push.)
-Unit tests. These don't really prevent errors, so much as make it obvious where the bugs are, and provide sanity.
I'm sure I'm missing many more principles, but point is, read up on designing for error.
While I totally support the unit testing suggested above, TDD or BDD will be of great value as you need to first think about the problem and the solution.
But personally for me, taking a few minutes just to sit quietly and think about the problem and how to approach it and any pro's and cons with each approach, does wonders for my quality of code and helps clear my mind of clutter.
Sometimes a quick scribble on a piece of paper helps you see the larger connected pieces of the puzzle.
I write the worst code when I just dive in head first and pound the keyboard. A little bit of thought and contemplation makes a world of difference.
PS. I mean 5 maybe ten minutes, not hours writing a huge spec.
Some good answers already, just some more food for though in addtion to what others have said.
Learn from your mistakes. Don't keep making the same ones over and over again.
Make sure to cover edge cases when programming - those are places where there are frequently bugs.
Pay attention to the requirement. Even if it works but doesn't do what the requirement specified, that's a bug.
Exception logs can be a real help when something goes wrong six months from now. Be in the habit of recording exceptions.
My two top thoughts are 1) Write better code which will fail when you do something unexpected 2) Become better at debugging
My code is littered with
if(value!=null) throw new NotImplementedException(); if(obj.v>0) throw new Exception(); //sometimes i dont write NotImplementedException if(value=="thing") throw ...;
Whenever i execute that piece of code the exception is thrown which causes the debugger to stop which lets me code in the new features or avoid the conditions rather then get confused about what is happening/have a bug
To become better at debugging mess around with the call stack, breakpoints (with conditions), the immediate window (also known as prompt or repl window), 'watch' variables and whatever else.