Designing an implementing successful object oriented code is tough because of the variety of situations with which a programmer will find themselves. Often when a coder is trying to code a solution to a problem the question is asked, “what pattern should I use, or what object scheme should I use?” The answer invariably is “it depends”. There are so many variables in any problem, there is generally not a single fit answer. This page is an attempt to capture more of the interesting ways of looking at problems.
Goals
Red Flags
Red Flags are conditions which should indicate to you that something isn't heading in an object oriented direction…
Too many method parameters: If you spot a method with too many arguments, it's likely you've built it for a very specific use. That's OK, but if you are writing a general purpose object, you want it to be easy and the more information you require of the caller, the less easy it is to use. Consider aggregating some of the information into another object, or split your method call (of course that's another problem). Another sub-class of this problem is passing exactly the same arguments to several routines. Consider adding “setFoobar()” methods to your object, or make them part of the constructor so they can be part of the object. This pattern is good for optional arguments (e.g. listener pattern receivers are often optional).
Getters and Setters for everything in the object: It used to be that conventional wisdom said you need to put Getters and Setters on every item in your object. That may be partially true if you are creating a JavaBean (but even then it's limited). If every (or even most) of the instance variables have getters and setters, why bother making the instance variables “private”, perhaps “public” would be a better option. It makes them quicker to access with less fuss. We're not talking about cases where some code needs to be involved to translate the data (e.g. setTemperatureFarenheight vs. setTemperatureCelsius) or do other processing. Also consider what's happening here. You've provided access to everything in the object, which is like going back to C style structs with full visibility. You've lost the ability to do information hiding, such as how something is implemented. Generally callers should be dealing with abstractions, and not specific implementations.
Not understanding how to use a pattern If you encounter a pattern you've never seen before, or used in a context that doesn't “seem quite right”, don't guess. Instead ask the author, you may be making assumptions about the object/pattern that aren't true and may introduce unwanted symptoms (more coupling than required, etc). It may be that the discussion with the author will reveal that it's time for the original pattern to change because you've introduced a new use case.
Methods written, just in case I have nothing against writing code to be more general, but writing code that isn't being used is a waste of your time as a programmer, both for implementation and testing (if you are a good coder and write your unit tests). It also increases maintenance costs because you'll end up needing to review/fix/etc. the extra code, which you aren't using it. Programmer time is more expensive than just about any other resource, and time to market is always a concern. Write what you need, but no more.
Circular References In order for objects to be useful and flexible, they need to be used in a wide variety of circumstances. Much like exposing implementation, or making a class knowlegable about it's callers implementation, circular dependencies between classes reduces this flexibility. When you have classes which are dependent upon one another, you can't use just a single class without using the other dependent classes. In general, keep your dependencies flowing in a single direction. Technically this would be called a Directed Acyclic Graph (DAG), in the class “type space”. Note that this applies not only to two classes referring to each other, but to a series of classes which also form a cycle. In fact this becomes worse with more classes.
References
Design Patterns: Elements of Reusable Object-Oriented Software, Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Addison-Wesley Professional Computing Series, Addison-Wesley, Reading Mass. 1994.