Some resources, asides, dos and don’ts, …
The Capability Maturity Model extensions
The Capability Maturity Model (CMM) is a development model created in 1986 after a study of data collected from organizations that contracted with the U.S. Department of Defense, who funded the research.
Anthony Finkelstein of Imperial College, London [ACM SIGSOFT Software Engineering Notes, Volume 17 , Issue 4 (October 1992), Pages: 22 – 23] was one of first people to speculate as to whether the official CMM levels 1 to 5 were entirely too optimistic. He suggested levels 0 down to -2 where, for example, organizations at level -1 act positively to subvert software development. These organizations insist on complex processes, involving the use of arcane languages and inappropriate documentation standards.
It’s not easy to access Finkelstein’s work unless you are a member of the ACM, but Captain Tom Schorsch of the U.S. Air Force wrote an elaboration of Finkelstein’s suggestions in the November 1996 issue of Crosstalk. I can’t keep up with the shifting home of the paper, but perhaps this Wikipedia article can.
“10” golden rules
I like lists and top 10s. Here are my top 10 (or so) rules for encouraging successful object-oriented analysis and design (selected from my top “25” golden rules):
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.
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
When I wrote this, the Unified Modelling Language was achieving widespread adoption. It was also beginning to worry some of us that it was being treated as a magic bullet. When you read this, perhaps there will be another modelling language or diagramming standard.
Of the 15 types of UML diagrams, you will probably only need 2 or 3 types, (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 …
Be sparing with the number of state machines you use; but spare no effort in assuring the quality of those you do use
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 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.
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 rule, 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.
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”.
Some of these “rules” are only top 10 rules because of today’s software development context. In other words, some of them are important because there are authorities that would tell you something different and possibly dangerous; and some of them are important because software development is still chronically under-resourced in most or most organizations.
These top “10” golden rules were selected from my top “25” golden rules.
(And one or two of the “rules” mention Dijkstra, so …)
Edsger Wybe Dijkstra (1930-2002)
Edsger Dijkstra was responsible for many of the software engineering precepts that we take for granted today, such as his beautifully reasoned argument against the goto and for structured programming. However, I must disagree with his later stance against programmers who think or talk in an anthropomorphic way about their software. It’s actually very important to say, “now if I were a InvoicedCustomer instance, I’d …”, rather than “you do this and you do that” or if one is very posh, “one does this then one does that” For more information on this stance, and others, try this wikipedia entry, which should also lead you to a transcript of the original paper.
Cardboard cut-out review
This was mentioned in one of the book’s exercise answers.
When you’ve reached the inevitably incorrect conclusion that the compiler is broken, because you just cannot see why your code isn’t doing what it should, it’s probably because you are seeing what you think you’ve written rather than what you’ve actually written. You’re in a mental rut. You need help to get out of the rut. You call a colleague over. You describe to your colleague what you’re code is doing. Almost certainly after a few seconds’ description, you will exclaim “Doh! Of course. Silly me”. Then your colleague can walk away without ever having said anything. In fact a cardboard cut-out of a colleague works just as well. In fact, if it’s late at night and no-one is watching, you can drag the potted palm over and describe what your code is doing, to the palm tree; and it still works.