Question: I'm working on a large project (for me) which will have many classes and will need to be extensible, but I'm not sure how to plan out my program and how the classes need to interact.

I took an OOD course a few semesters back and learned a lot from it; like writing UML, and translating requirements documents into objects and classes. We learned sequence diagrams too but somehow I missed the lecture or something, they didn't really stick with me.

With previous projects I've tried using methods I learned from the course but usually end up with code that as soon as I can say "yeah that looks something like what I had in mind" i have no desire to dig through the muck to add new features.

I've got a copy of Steve McConnell's *Code Complete* which I continually hear is amazing, here and elsewhere. I read the chapter on design and didn't seem to come out with the information I'm looking for. I know he says that it's not a cut and dried process, that it's mostly based on heuristics, but I can't seem to take all his information and apply it to my projects.

So **what are things you do during the high level design phase (before you begin programming) to determine what are the classes you need (especially ones not based on any 'real world objects') and how will they interact with each other**?

Specifically I'm interested in what are the methods you use? What is the process you follow that usually yeilds a good, clean design that will closely represent the final product?

Answer: 
Adding to what Scott Davies had to say:

1. Make absolutely sure you know what your program is all about before you start. What *is* your program? What will it *not* do? What problem is it trying to solve?
2. Your first set of use cases shouldn't be a laundry list of everything the program will eventually do. Start with the smallest set of use cases you can come up with that still captures the essence of what your program is for. For this web site, for example, the core use cases might be *log in*, *ask a question*, *answer a question*, and *view questions and answers*. Nothing about reputation, voting, or the community wiki, just the raw essence of what you're shooting for.
3. As you come up with potential classes, don't think of them only in terms of what noun they represent, but what responsibilities they have. I've found this to be the biggest aid in figuring out how classes relate to each other during program execution. It's easy to come up with relationships like "a dog is an animal" or "a puppy has one mother." It's usually harder to figure out relationships describing run-time interactions between objects. You're program's algorithms are at least as important as your objects, and they're much easier to design if you've spelled out what each class's job is.
4. Once you've got that minimal set of use cases and objects, start coding. Get something that actually runs as soon as possible, even though it doesn't do much and probably looks like crap. It's a starting point, and will force you to answer questions you might gloss over on paper.
5. Now go back and pick more use cases, write up how they'll work, modify your class model, and write more code. Just like your first cut, take on as little at a time as you can while still adding something meaningful. Rinse and repeat.

Just my two cents. Hopefully it's useful.
Just quoting <http://www.fysh.org/~katie/computing/methodologies.txt>

And at the core of RUP is a small area where you have to use OO design
talents.... if you don't have them, it's like having a methodology for
running the 100m.

"Step 1: write about running really fast. 
Step 2: Go and draw a plan of the racetrack. 
Step 3: go and buy really tight lycra shorts. 
Step 4: run really, really, really fast. 
Step 5: cross line first"

It's that step 4 that's the tough one. But if you put lots of emphasis
on 1,2,3 and 5 it's possible no-one will notice and then you could
probably make a lot of money selling the methodology to would be
athletes who think there's some "secret" to being a 100m runner over