I make a ton of sloppy mistakes when I code. Stuff that leaves me kicking myself when I spend 20 minutes trying to debug it. Even though I've gotten better at programming, the number of sloppy mistakes I make is still way too high and its my biggest time drain.
I think part of the problem comes from writing code, glancing through it quickly, and then testing it with a large number of "F5s". I'm trying to get away from this and am reading my code more thoroughly before testing to see if it works. Anyone struggle with the same issues? HOw did you improve?
Thanks!
"I think that without a debugger, you don't get into that mindset where you know how it behaves, and then you fix it from there. " http://linuxmafia.com/faq/Kernel/linus-im-a-bastard-speech.h...
For example, I make a lot more typing mistakes typing into text editors than I used to do when typing on a typewriter. But I type net faster, by a lot, because fixing mistakes is so easy.
There are several ways to make mistakes cost less in programs: writing functional code; using a very abstract language; writing programs in layers; testing every change as you make it, in a repl.
You can switch modes, too. I sometimes start by writing something rapidly and comparatively carelessly, and then later when I reach a natural stopping point, I'll reread it carefully.
Then run through the code in your mind. Does it work? Pass in some variables.
Your mind can process information much faster than you can type it out. If you build the image of your code in your mind, you can map it out in a matter of minutes, but if you start coding without the image, you make more mistakes.
Some other commenters have said write it out or draw it out. This is a good idea if you can't keep it in your head. Do flow charts and state diagrams and things like that before you start coding.
Compared to what?
You may not have a problem.
Sometimes "code, mistake, fix, code, mistake, fix, code, mistake, fix,..." is faster than "code it perfectly once".
For me it usually is. I'd rather crank stuff out quickly and fix it than drive myself nuts thinking it through.
Stupid syntax and typing errors will go away with repetition. Otherwise I wouldn't worry too much as long as you keep cranking forward.
[For what it's worth: I do not use an IDE, I do not use color or syntax highlighting, and I use debug as a last resort. Many here disagree with me, but I believe my brain internalizes those things that help me avoid stupid mistakes by coding without training wheels.]
use a language a programming style that lets you catch errors early. it's amazing how much time i've wasted testing for errors after small changes in ruby programs. errors that a decent language & compiler wouldn't have allowed or detected much earlier. some languages just weren't designed with this in mind. i no longer program in ruby.
related: once upon a time, i had the idea that i should be able to write a program and have it compiler & work at the first & final attempt. code was in c. of course that failed miserably. especially with the lack of c coding experience. the lesson: don't try to be silly/"smart", use the tools to your advantage. (if your tools don't have advantages, don't use them).
Coding is debugging just like writing is revising.
In other news, I try to check my answers by deriving them two ways. If they agree, then I at least have a good defense :). If I'm working on something that can only be reached one way (like pulling data from a database), I assert boneheaded things that should be true about code + data structures. Sometimes it's superfluous, sometimes it catches mistakes.
If you don't work in a language that provides stack traces on crashes, add logging. You'll get a rudimentary stack trace of what was happening when everything went to hell, as well as have a small radius for where the crash occurs.
My guess is that worrying too much about low-level correctness while writing your code could lead to very poor productivity and even OCD.
With that in mind, perhaps also think about the way you are structuring your development. Do you have a mental (or physical) sketch of the code before you write it? There's something to be said for having a bit of paper to scribble on before and during the coding process. Map out little examples (e.g. "test cases") and think about how you will deal with all of them.
Finally, writing stubs (i.e. functions or modules that are basically empty) when you first start can be great. If you know you're going to need some pieces of functionality in order to solve your problem, then write stubs for those and then solve the problem (i.e. write the main program flow). Hopefully then when you come to write the supporting functions that do most of the heavy lifting, you will have clarified your intuitions around how they are supposed to work.
So my advice would be to be a little more rigorous in your approach _before_ you get to the point of having screenfuls of code in front of you.
This is especially true when I'm editing existing code rather than checking in new functionality. I read the diff while mentally asking myself "is this going to change anything other than what I intended it to change".
Error logging. When you make a mistake, and find it, document it, with as much of the reason why you made the mistake as you understand. Keep a diary of these for a few months, and you'll be surprised by how much you learn, as well as learning which mistakes you're most prone to.
This may be a little old fashioned of me, but any time I try to solve a problem that isn't immediately obvious, I write it down on paper first (or whiteboard it).
If you can't hold the solution in your head and visualize it, then you should try to break the problem down into smaller chunks so that you can at least fully visualize all of the moving parts.
Around my office, I have a set of maxims that I always emphasize in order to keep our quality high - #2 on the list is to always measure twice before cutting (or writing, in this case); rule #1 is to pick the low hanging fruit first. There's no point in starting to code a solution until you know with a level of certainty what it is you're trying to achieve. Lots of people with debugger syndrome don't know where they're going until they happen upon a solution by coincidence instead of by intention.
When I encounter a bug I write an assert that reveals the problem before I fix it in order to prevent having to deal with the same issue more than once. This is especially big for me since I work with a lot of (other people's) data.
It's ok if you don't get it perfect all of the time. It's the 20 minutes debugging that's killing you. Shorten your cycle and eventually you will get less sloppy (or immediately know where/what the sloppiness is before you even run). It will be like that typo you "know" you made even before you finished typing (something won't feel right and you'll go back and fix it before you read the debugging output).
I know what you mean about hitting F5 all the time. I usually program that way when I don't feel like thinking. I want to cross my fingers and hope that it works. When I notice I'm doing this, I need to stop and think about what it is that I'm doing. I'll often write down in text what I'm trying to do. Or I'll turn off the computer and think about it.
- When I'm working with a fast compiler, I setup a small CI system to immediately compile my code and run my tests every time I save my changes. If I can't do this for some reason then I setup a trivial background script to do this constantly and watch the output in another window.
- I try not to cut corners. It's easy to stay in the flow once I have things setup so that I can build and extend my tests and scaffolds along with my code.
Small moves, Everest, small moves...
I use a little tool that runs unit tests on compilation, when Im doing something new that unit tests works well with, I write a bunch of tests and just code until I have 100% tests passing.
If you make a lot of mistakes, have sanity tests cover your ass.
It's a bit like the integrity mechanism of developing two copies of the same software, done by totally separate teams. You and your friend are both thinking about how to solve the problem, but separately, which means the likelihood that both of you make the same dumb mistake is fairly low.
2. Start unit testing your code, there are plenty of libraries available for this.
3. It comes with experience.
Don't try to always be coding. You need to have total focus when you work. If you work when you don't have it you are just creating more work for yourself later. It's a net loss.
1) ASSERT. Catch the mistakes while they're still dumb.
2) Take advantage of your type checker to catch mistakes.