Site Map  Search

OOA Home OOD content UML Corrections book Code object Exercise Solutions oriented Resources tutorial Miscellany textbook

"25" golden rules

Here are some more "dos and don'ts" selected from the big list of (150-ish) practices and rules of thumb in the Object-Oriented Analysis and Design book. (Being able to count to 25 accurately wasn't considered terrifically important. The actual number tends to float around the 25 mark.)

  • You need a design (a plan, a structure)

    Only on 1 day in 10,000, and only for systems with less than 1000 lines of code, and only for systems that will endure less than 100 person-hours of use can anyone start coding without a design.

  • You need an analysis model or a metaphor

    Only on 1 day in 1000 can anyone start a design without a subject-matter model or a metaphor to guide them.

  • You need requirements

    If you don't know what is required of a system, how can you hope to know what to study, what to build, how to build it?

  • Don't waste any time allocating methods (member functions) to your software objects on the basis of the processing that their subject matter (analysis) counterparts do

    If you are producing a subject-matter model (doing analysis) you have to remember that it is a model, and that the continuity between a model and whatever is being modeled, lies in state and not in action. Including processing or actions in analysis models is largely a waste of time or is dangerous. In the analysis activity, establish the relevant subject-matter objects (state packagings exhibiting identity), establish their attributes (intrinsic state), establish their characterizing relationships (extrinsic state). At that point you will have good ideas for some creatures in a structure.

    This sounds like a big thing; but really it's a small thing. Method allocation is a design step and just comes a little bit later than is sometimes thought. As a design step (invention rather than discovery) you can decide what your creatures' software counterparts are going to do. While the existence and state of the software creatures will have a good match with their subject matter counterparts, their doings will not.

  • Relentlessly question both many-to-many and bidirectional association relationships

    Both of these are difficult to implement successfully in today's languages and databases. And they are actually rarer (perhaps much rarer) than people imagine. Unnecessary many-to-many and bidirectional association relationships are frequently the result of early models that are vague and too coarse-grained; they nearly always occur because of overlooked or missed model elements.

  • N-ary relationships are an abomination

    Relationships have two ends. Anything else is vague or imaginary and, anyway, is unimplementable.

  • Pounce on any hint of conflict or tension in a model

    If one modeler thinks a relationships is aggregation but another thinks not, there's a very good chance that the model is too coarse-grained. If one modeler thinks an association is 1..1 and another thinks it's 0..*, there's a very good chance that the model is too coarse-grained. Conflict and tensions are valuable flags that model elements may well be missing. And a model with 5% of its elements missing is worth only 50% of what it might have been worth.

  • You will need to know the UML well; but not so much for knowing what to use, as for knowing what not to use and where the difficulties lie

    Of the 15 types of UML diagrams, you will probably only need 2 or 3, (maybe 3 or 4 for a complex project) on a regular basis. And of the diagram types you do use, you will only need between 50% and 90% of the content they offer. And with that content, you will have to be quite careful as to what it signifies; very little is obvious or unambiguous. As to which diagrams and what content, might I take the liberty of referring you to a rather good book ...

  • Everyone should know and agree if any use of the UML is as sketch or as blueprint (or as programming language)

    If the UML is acting as a formal specification vehicle, its use requires more care and attention than people usually give. If the UML is being used as a programming language, then you are among the few, the brave or the foolish.

  • Vet UML multiboxes with more than one substantive compartment

    Far too often every UML box is casually shown with two substantive compartments (two feature-listing compartments). Entity (analysis) boxes, type boxes and interface boxes usually have a single compartment. It's partially abstract classes and concrete classes that have boxes with two lists. (And classes are sufficiently complicated that they often need three or four lists.)

  • Many models need no state machines at all; those that do, need fewer than is sometimes suggested

    Just about all "business" objects (commerce, science, engineering) should not be modal. They should be boring -- doing the same old, predictable thing, day in, day out. They should have what we can call combinational complexity; they take only pure data inputs. Only 5% of hard real-time systems' objects should be allowed to live modal, exciting lives -- lives where some of their inputs are control inputs -- sequentially complex lives. This means that only 5% of 15% of the software producing world's objects will need state machines (or something similar) as part of their specification.

  • The state machines that you do need require a more care and attention than is usually given

    The creation of correct state machines is a technique that cannot be learned in one casual attempt. Each kind of deliverable, model or model constituent -- requirements, analysis, design, interface, implementation, ... -- requires a different manner of using and interpreting state machines. And each interpretation of a state machine will take more than one go to learn. And even when you have learned to create and interpret the kind of state machine you need, state machines are among the trickiest things to get right and they also have a tendency toward "one mistake and the whole thing's useless". So, repeating, you probably need fewer state machines than you might have thought; and you need to lavish much more care on the state machines you do end up needing.

  • Be object-oriented (and message-oriented) not class-oriented

    Instances are just as important and should be designed before classes. Analysis models suggest object instances, not classes. It's the object instances, once we start to know them, that suggest the types and the classes. And object instance design is best driven by the messages the object instances are there to service. Exemplar sequence diagrams are just as important as class diagrams.

  • To design good objects you must think like an object, not a programmer

    Anthropomorphic thinking is necessary for designing and programming good objects. You can't think like a programmer; you can't think like some overall program executive (which there shouldn't be anyway); you must think like an object instance running its methods in response to its messages. CRC is a good way to encourage this and to put it into practice. [A famous computer scientist thought otherwise. See Edsger Djikstra .]

  • Interfaces are more important than implementation

    The type system is more important than the class system. Public method (member function) signatures need more thought, care and attention than they are usually given.

  • Design (high-level and low-level) from the outside inwards

    Having followed the previous three rules, and thus having made a good "outside-in" start, continue with the outside-in approach when you arrive at class design. Begin with the "they will come back to haunt you" signatures of the public methods (member functions) and arrive at the "here today, gone tomorrow" instance variables (date members) last. (Last, that is, apart from deciding what implementation you're going to inherit).

  • Inherit interface first, and implementation later

    Inheritance isn't the wonder-device/savior/silver bullet that was originally hoped for.

    If your language forces you to use inheritance to set up a polymorphic type system, focus on type sharing (inheritance of interface) first. In languages like Java and C#, don't use extends (inheritance) if implements (classes implementing interfaces) is appropriate.

    In any language deal with inheritance of implementation later, when the concrete classes are settling down and most have appeared.

  • Treat superclasses (base classes) with care

    Never instantiate superclasses; and seldom use superclasses that are only partially abstract as types. Instantiate only leaf-node subclasses; and tend towards using purely abstract superclasses or interfaces as types.

    Almost a golden rule in its own right but covering three of four of the preceding points, variables have types; objects have classes.

  • Make all names (identifiers) precise, colorful and no more concise than they should be

    Have all model and code names be honest and accurate. Avoid wishy-washy, gray names. Avoid handle(r), process(or), manager(r), and their ilk, as parts of names. You want a name to put a clear picture and the same picture into everyone's head.

  • Respect the "Need to know" principle

    Restrict what your software elements know about each other: they know no more than they absolutely need to know. This is another phrasing of "strive to minimize coupling".

  • Respect the software engineer's affirmation

    Ensure you follow, "the thing, the whole thing and nothing but the thing". An object should empower one thing, all of that thing and nothing but that thing. A method (member function) should do one job, the whole job and nothing but that job. Another phrasing of, "strive for maximum cohesion". Database designers know this exhortation as "normalization".

  • Be guided by use cases but don't be driven by them

    Use cases are a requirements artifact (and a very useful one at that). However, be aware that like sequence diagrams and like testing, they are a sampling activity; if you don't know when to stop, you never will. Also, they take a functional picture; and as such, there is a risk that if they drive the design, rather than answer questions asked by the design, the ensuing object architecture will be poor and fragile.

    And don't confuse use cases with object interaction. Use cases look at the system-to-be from the outside; sequence diagrams (object interaction diagrams) look at an emerging system design from the inside.

  • Understand the concept of identity

    It still astonishes me, as the years go by, just how much you can figure out if you clearly understand the concept of object identity. It helps distinguish analysis model secondary elements like attributes from primary elements like entities. It helps choosing between composition by value and composition by reference. It helps with cloning decisions (in Java and C#) and with reference/pointer/value passing decisions in C++. ...

  • Program in the future tense

    Foresee the inevitability of having to change and extend tomorrow, what you are writing today.

  • Use enough self messaging

    Self messaging is elegant and powerful. If you (as an object) aren't self messaging then you (as a designer-programmer) have missed a step in your ascension to true object-orientated greatness.

  • Delegate and empower

    Understand the Law of Demeter. It's not possible to explain it fully in a paragraph, but ...

    This law is important because of tendencies that we all seem to have, but that seriously degrade the value of an object orientation. Allow (empower) your objects to deliver normalized services. Don't tell them how to do it; and don't ask them to tell you or give you what you don't need to know, just so that you can do some of the work that they ought to be doing.

  • 7 2 really does apply

    Some course participants think we're joking when we say that 85% of methods should have 7 2 non-blank, non-comment lines of code. We aren't. Furthermore, stabilizing class in a stabilizing architecture should tend towards adding or overriding no more than 7 2 public methods; UML diagrams should have no more than 7 2 multiboxes, 85% of whose compartments should list no more than 7 2 of their features.

These top "25" golden rules were selected from my 150 practices and rules of thumb. And they were originally an appendix to the notes for the course I give -- the course from which the book was derived.