Eight Object-Oriented Design Tips
Somebody asked me for a list of things that can be done to improve object-oriented design. Here it is:
Objects “do” things. Most important point in the whole of OOP! Don’t think about them as “data holders” – send them a message to do something. What verbs should my class have? The “Responsibility-Driven Design” school of thinking is brilliant for this. See Object Design: Roles, Responsibilities, and Collaborations, Rebecca Wirfs-Brock and Alan McKean, Addison-Wesley 2003, ISBN 0201379430. For each thing the system must do, come up with a bunch of concrete scenarios describing how the objects talk to each other to get the job done. This means thinking in terms of interaction diagrams and acting out the method calls. Don’t start with a class diagram – that’s SQL-thinking not OO-thinking.
Learn Test-Driven Development. Nobody gets their object model right up front but if you do TDD you’re putting in the groundwork to make sure your object model does what it needs to and making it safe to refactor when things change later.
Only build for the requirements you have now – don’t obsess about “re-use” or stuff that will be “useful later”. If you only build what you need right now, you’re keeping the design space of things you could do later much more open. The old tendency to build the one, ultimate object-model up-front that takes every possible need into account caused so much complexity and trouble in the 1990’s and since then we’ve learned to do “evolutionary design” so there’s no need to burden ourselves by attempting to build a massive, bloatware object model.
Forget about inheritance when you’re modelling objects. It’s just one way of implementing common code. When you’re modelling objects just pretend you’re looking at each object through an interface that describes what it can be asked to do. Don’t make decisions about inheritance relationships based on names.
If a method takes loads of parameters… or if you need to repeatedly call a bunch of objects to get lots of data, the method might be in the wrong class. The best place for a method is right next to most of the fields it uses in the same class (or superclass …)
Read a Design Patterns book for your language. If it’s C#, try Design Patterns in C# by Steve Metsker. This will teach you a series of tricks you can use to divide work up between objects.
Don’t test an object to see what type it is and then take action based on that type – that’s a code smell that the object should probably be doing the work. It’s a hint that you should call the object and ask it to do the work. (If only some kinds of objects do the work, you can simply have “do nothing” implementations in some objects… That’s legitimate OOP.)
Putting the methods and data in the right classes makes OO code run faster (and gives virtual machines a chance to optimise better) – it’s not just aesthetic or theoretical. The Sharble and Cohen study points this out see http://portal.acm.org/citation.cfm?doid=159420.155839 (See the graph of metrics on “number of instructions executed per scenario”)