Most of the posts here are from people with problems, looking for help. I thought I would try to talk a bit about ways to find your way out of "stuck". It's been on my mind lately, since I've been wrestling with Swing and it's been winning. Finally worked out some stuff today after five days of head vs. wall interaction.

So we all know about getting stuck - you write the code, and you know what you meant for it to do, and when you run it... that's not it. And you go through the code, and it's all there, just like you wrote it... how do you learn to see mistakes?

Here's some things that have worked for me. I hope some of the regular solvers here will throw in a few ideas, as well.

The first thing that I have learned to do when I'm stuck on something is to think about asking for help. No, I don't run to Daniweb and say "I'm trying to write a program to do this and it won't do it! Help!", but I think about how I would write that post to get the most useful answers. That means, I think about exactly what problem I'm trying to solve, and how I've constructed my overall solution to that problem, and where it is that the snag is occurring. Wait - how do I know that's where the problem is occurring? Well, I can make a guess based on what has happened on the screen up to the error. I can narrow it down, by putting in printouts to show that I've made it to this point in the code, and then to this point. Oh, this method depends on that one having run - am I sure that happened? Put in a

println("Entering method foo() with value " + parameter);

You see how that goes. Often, just trying to locate the problem brings me right up against it.

First step to getting unstuck: find where your problem is happening.

Sometimes that doesn't work, though - that's okay, I know a lot more now about the problem. Next thing: what is the behavior that I'm seeing. Can I describe it exactly? "My JPanel isn't displaying correctly." No, that's not it. It's displaying exactly the way I told it to - what did I tell it to do? So I look at each step in the setup of the JPanel, and think about exactly what that does. This usually involves looking very carefully at the Sun docs. (yes, I know it's Oracle now... I look at the Sun docs...) When you get out of the simple workhorse classes, you can find yourself in some pretty intricate code that tries very hard to be very smart and do what you want it to do. This can cause you all sorts of problems if you're trying to be smart as well. This afternoon, I found out that GridLayout aggressively resizes your components to fit its grid, and there doesn't seem to be any way to change the width of a column or the height of a row. No wonder my JPanel was all messed up. I went to a BorderLayout, and, easy-peasy, it looked sort of like I'd wanted it to.

Second step: figure out what you're telling the computer to do.

This step is the one I sometimes summarize in answers on this forum as "pretend you're the computer". For algorithmic problems, that's often the best way to see the answer: walk through the steps of your algorithm and track the changes to the variables as they happen. It's amazing how often I find incredibly obvious and stupid mistakes that way - and how often I miss them because I know what I meant to write.

Okay, well, that doesn't always work. At this point, I go have a sandwich. I pick up my accordion and play a few tunes, or I go for a walk or I read a book about philosophy of mind or I work on some scheme (scheme is way fun, by the way - The Little Schemer is a book that will blow your mind, if it hasn't been blown in this fashion before). Anything that'll take you out of the problem for a while. When you stop thinking about it, the answer often comes out of nowhere - and even if it doesn't, twisting yourself in knots isn't really helping that much anyway.
The thing to be careful with here is that you don't want this to be an excuse to eat a lot of sandwiches and play a lot of accordion - you do have to actually work yourself into knots before this does any good!

So step three: take a break. One very productive way to take a break is to work on some other facet of the program - there's usually half a dozen things to work on in any complicated program at any given time. Pick something that you've been meaning to do, and work on that. Stub your way around the failure if you have to, and get something else to work. Refactor some of the slop that's left from your early breadboarding code. Maybe tighten up some loops or try to eliminate some conditional branches (conditional branches... there's a topic I could go into... I love getting rid of if statements...) Sometimes that takes you right up to the problem, sometimes it doesn't but it does get some work done while you stuck, which is a lot like not being stuck.

Some combination of these usually works for me. If I get to this point, and nothing's worked, I'll resort to what I call "interrogating the code". I take each class, and I look at its methods, and I grill each of them about what they're meant to do, why they're there, shouldn't they be somewhere else, and what right do they have to exist in the first place? If I grudgingly concede that this method should be allowed to live, I try to whip a few lines off it, just to make the point. By the time I've done this, I've usually reminded myself of some parts of the code that had slipped into the back of my brain, and that sometimes gives me the kick to see the problem I'm looking for.

So that's a pretty long post, but I'm sure there's more to be said about the matter. Anyone have any other good ways of breaking the deadlock in the brain? I'm sure that some of the posters here have had some pretty gruelling bouts with stuckness - anyone want to share any tips?

(If you've got to this point, and you've guessed that I've got code sitting on my work machine, needing a bit of a polish-up, you've guessed correctly! :) )

I really want to endorse the "println" approach.
Some of the hardest problems to solve are because:
1. You have an incorrect understanding of how some API works, or
2. You are missing something that you didn't know you needed
In both cases no amount of introspection or code re-reading is going to help, but lots of printlns (or using a full debugger to trace execution & variables) will quickly reveal the source of the trouble.

The other key strategy is to debug in small increments. It's amazing how often you see beginners coding a complete app before trying to run anything, then have no idea why "it doesn't work".
It's usually possible to package a small "main" method in every public class that just runs a quick hard-coded test of that class's basic functionality. I always use these to check out classes before trying to integrate them.

First, excellent post - every experienced programmer is doing all of above and more after learning it the hard way - you cannot force your brain to work and solve all your problems, sometimes you need to rest, sometimes you need a different approach, and almost all of the time you can't assume that you know what your program is doing - you need to verify it.
Regarding the prints - I usually override the toString() method in order to print all the material that I want to know about the class and print that information completely in other parts of the code where I use instances of that class, I find it very helpful.
In addition to the prints, it is important to learn how to use the debugger, since it will give you more information in a more convenient fashion then just printing it.
JamesCherrill - I agree with you regarding testing each class, and I have a small main method in every class to check that the class itself doing all the it suppose to do (and does not do what it does not suppose to do).

Comments
I like the override
This article has been dead for over six months. Start a new discussion instead.