How do you design object oriented projects?

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.


The steps that I use for initial design (getting to a class diagram), are:

  1. Requirements gathering. Talk to the client and factor out the use cases to define what functionality the software should have.

  2. Compose a narrative of the individual use cases.

  3. Go through the narrative and highlight nouns (person, place, thing), as candidate classes and verbs (actions), as methods / behaviors.

  4. Discard duplicate nouns and factor out common functionality.

  5. Create a class diagram. If you're a Java developer, NetBeans 6.7 from Sun has a UML module that allows for diagramming as well as round-trip engineering and it's FREE. Eclipse (an open source Java IDE), also has a modeling framework, but I have no experience with it. You may also want to try out ArgoUML, an open source tool.

  6. Apply OOD principles to organize your classes (factor out common functionality, build hierarchies, etc.)


When I had the chance, I normally use what I call the "three iterations rule".

In the first iteration (or startup), I devise the general layout of the application according to the model objects, the algorithms, and the expected (really expected, not maybe expected) future directions. I don't write design documents, but if I have to coordinate multiple people, a rough sketch of the procedure is of course needed, together with an analysis of dependencies and guesstimate of the time needed. Try to keep this phase to a minimum if, like me, you prefer a more agile method. There are cases where a strong design phase is needed, in particular when everything is known and true about the logic of your program, and if you plan to have a lot of interactions between features in your code. In this case, use cases or user stories provide are a good high level idea, in particular for GUI apps. For command line apps, and in particular libraries, try to write "program stories" in which you code against the library you have to develop and check how it looks. These programs will become functional tests of your library when completed.

After this first iteration, you will have a better understanding on how things interact, got out the details and the rough spots, solved issues with a slapped duct tape patch. You are ready to make use of this experience to improve, clean, polish, divide what was too large, coalesce what was too fragmented, define and use design patterns, analyze performance bottlenecks and nontrivial security issues. In general, all these changes will have a huge impact on the unit tests you wrote, but not on the functional tests.

When you complete this second iteration, you will have a little jewel, well tested, well documented, and well designed. Now you have both the experience and the code to do the third iteration, extend. You will add new features and use cases to improve your application. You will find rough spots and you will eventually enter a fourth iteration which is analogous to the second one. Rinse and repeat.

This is my general approach to software design. It is similar to spiral design, with short, three months iterations, and elements of Agile development, that allows you to learn the issues and get to know your software and its field of application. Of course, it's a matter of scalability, so if the application is so large to involve hundreds of developers, things are a bit more complex than this, but in the end I guess the idea is always the same, divide et impera.

So summing up:

  1. In iteration one, you get a taste of it, and learn
  2. In iteration two, you clean up your product and prepare it for the future
  3. In iteration three, you add new features and learn more
  4. goto 2