Solutions to exercises – 1

Chapters 1 2 3 4 5 6 7 8 9 11 12

These are the solutions that were always available to anyone.

Chapter 1

Question 1.1
Research or recall at least two more definitions of objects and of object-orientation. Compare and contrast those definitions with the ones given in Section 1.1.1.

Rumbaugh et al., in Object-Oriented Modeling and Design (1991) “define an object as a concept, abstraction, or thing with crisp boundaries and meaning for the problem at hand. Objects serve two purposes: They promote understanding of the real world and provide a practical basis for computer implementation.” This definition is trying to be general and to serve as a definition of something that might be found in real world models (called subject matter models in Deacon) as well as something that might be found in software. There could be difficulties in trying to cover both real world models and technical models with a single definition. The definition of Rumbaugh et al. is sufficiently non-specific, though, that it succeeds in covering both whilst avoiding inaccuracies. However, someone trying to understand exactly what might constitute an object be would be left with questions, especially in technical models: both data structures and functions would qualify as objects under this definition, for example.

Deacon, in Section 1.1.1 defines an object as “a cohesive and loosely-coupled, self-processing, implementation-hiding, meaningful software agent that exhibits identity and that usually has a personal and persistent state. An object makes itself useful through, and hides its implementation behind, a message-accepting interface.” This covers software objects but not real world objects. Deacon avoids providing a definition that covers both analysis and design models.†

Sommerville, in Software Engineering (7th edition, 2004), says “An object is an entity that has a state and a defined set of operations which operate upon that state. The state is represented as a set of object attributes. The operations associated with the object provide services to other objects (clients) which request these services when some computation is required.” This is a more software-object-oriented definition than that of Rumbaugh et al. Deacon still goes further, though, and includes what might be considered style judgments. Despite its near-universal acceptance, Sommerville doesn’t mention encapsulation and information hiding, for example.

†[If this exercise were to be set after more of the book had been read – chapter 2 and 4 perhaps – the answer could go further: Deacon avoids providing a definition that covers both analysis and design models, claiming that there are enough differences between the objects of the real world (which he terms entities) and the objects of the software, that trying to provide a common definition isn’t feasible or helpful.
Someone familiar with object technology could go on to consider my inclusion of identity as part of the essential character of an object, pointing out that this might tend to exclude some value objects like dates and complex numbers. My definition could be criticized for insisting on identity and yet admitting stateless objects (which are surely no less peculiar than value objects).]

Question 1.2
Describe how, in the face of changing problems, practices and people, analysis has evolved, or should have evolved, since the 1950s. Include a consideration of the appropriateness of the terms that have been used for the job.

This is a revision question. Everything I would have expected in an answer is in the chapter. The answer might have mentioned: the problem realm moving from arithmetic and maths, through clerical applications to just about anything today; the “analysis” strategy moved from “Eh? What analysis? Mathematics is an entirely adequate specification language in its own right.” through systems analysis and the era of computerization, to my claim that we need to re-title analysis as “subject matter analysis” today, since many (or most) developments are not computerisations and if there is a system to analyze, there’s a strong chance it’s already an unanalysable computer system; the people have moved from single pioneers to multiple teams; job titles like analyst-programmer appeared in the middle, computerization, years and job titles like designer and architect appeared in recent years; and terms like analyst-programmer and systems analysis are probably over-used and misused today, again because computerization is becoming a rarity and because typical systems are big enough that a design phase is essential.

Question 1.3
[Practitioners] Consider the development unit you work for. It might be the entire development team of a small software house, or it might be a team of around a dozen people in a larger organization. If your team is part of a team that’s part of a very large organization, you might consider your immediate team and the next one up.

Without being unduly tough on yourself or unduly optimistic, assess where you think you are in the CMM (capability maturity model) scale mentioned on page 9. When your unit has a successful project, is it more luck than judgment? Or can your unit “turn the handle”? What self-awareness does the unit have? What quantification is there?

By all means do a little more research on CMM, especially its recommendations as to what each level should do in order to move toward the next. (And note the observation that you cannot skip a level.) If, in your research, you encounter one of the extensions of the CMM, such as Imperial College’s, with zero and negative levels, I hope you don’t recognize your unit’s level there.

What did you find? Success only through coincidence and heroic effort? Teams producing the goods rather than heroes, but teams without insight? Teams with insight into their own practices and processes? Quantification and metrics? Optimizing, self-aware, self-healing team? Or did you feel that to reach even level 1 was a distant goal? If you haven’t come across the zero and negative-level extensions to the official CMM scale, they are in the miscellany section.

Question 1.5
Consider one or two subject matters that you have a degree of familiarity with. You might or might not have developed computer systems dealing with your chosen subject matters. Note down a few (half a dozen maybe) of the key creatures or entities as we will be calling them. Although we will have entire chapters on choosing entities, it’s not that difficult to start and you will almost certainly discern a few reasonable ones.) You might review these choices after you’ve completed the chapter on entities.)

Of course, the answer here depends entirely on what subject matter you’ve chosen. However, there are a few general points against which you can check your answer. Are your entities really there? If your subject matter was managing the local video rental shop, did you include the printer just because there’s one behind the counter? The “real” entities would be Renter, Video, DVD, Snack Item, Shelf Category, etc. Notice the last one. It’s more subtle. It’s not the wooden or metal shelf itself; it’s the concept of the place to put something. Real and relevant subject matter entities needn’t be physical or tangible. Do your entities exhibit identity? Did you include something like Studio (Miramax, etc.)? That would be a difficult one; renter address would almost certainly not exhibit identity in this context, and thus be modeled as an attribute; whereas Renter would and thereby achieves entity status. I would initially consider studio not to exhibit identity, i.e. to be modeled as an attribute rather than an entity; but it’s a tricky one; probably more information would have to be sought. Did you give your entities strong, colorful names? Did you have something like Renter, or did you have something like Customer?

Consider and list the processing that your entities carry out. (An entity that carries out some processing changes the state of itself or another entity.) Don’t read any further until you have done that. Have you done that? Now read your lists and ask yourself if your entities really do carry out those processes. Don’t claim, for example, that a real world employee tells you how much to pay it, because it doesn’t.

If you realize that you’ve invented some processing, ask yourself how reliable your invention is likely to be, and how much agreement you would get from other developers. If you decide that your entities’ processing is honest and real, picture typical software objects like Java objects or C++ objects doing that processing and assess how reasonable that would be. (If your experience of object-oriented programming is slight, then carefully put your lists away and review them in a few months’ time.)

Do you find that you agree or disagree with the position of this book, that either your entity’s processing is unreal or it would be a poor method allocation for its corresponding object?

Again, it depends on your example, but let’s stick with the rental store. Did you write down something like a renter moves to a new address, or a game cartridge breaks? Those are certainly actions in the real world but, and maybe you just have to trust me on this, they won’t ever make good methods (member functions) for the software objects. The address is an attribute or relationship that the store employee updates, the renter object won’t run a move() function. And, again, a renter or employee will note that a cartridge is broken and will update the system. A Java cartridge object won’t run anything like a dysfunction() function. Perhaps you wrote down that a renter issues an overdue letter. Well, that’s quite likely to be a good method for a software object (although we don’t have much evidence for that assertion just yet); however, it’s an invention – the real world renter simply doesn’t do that. Let’s leave invention until after we’ve assembled as many facts as possible.

Most people start off surprised to hear that modeling operations and processing as characteristics of subject matter entities is invention rather than fact-finding. That’s probably mostly a decade or more of methodologists having suggested otherwise. Hopefully, when you really looked, and really looked honestly at your subject matter entities, you did indeed find that whilst not irrelevant, processing is something to be very careful with; and that if a subject matter entity operation did suggest a good method for an object, then really, honestly it wasn’t actually something a subject matter did – you invented it. And if you did list some actual processing that your subject matter entities really did carry out (and if you have some experience of object-oriented designs), the object technology counterparts of your subject matter entities would not be likely to benefit from matching methods.

Chapter 2

Question 2.1
Compare and contrast software engineering with hardware engineering. Consider particularly the comparisons that help us understand why software engineering is, or appears to be, so difficult.

Both kinds of engineering began with ad-hoc practices that, as things scaled up and as people’s willingness to pay went down, eventually had to become standardized, and with materials that eventually had to become standardized and componentised for the same reasons.

A good bridge, building or DVD player will have arisen from a well-understood process that involved requirements elicitation, analysis of something that had prior existence, and technical design. Many of us continue to believe that similar elements are required in a software process.

However, the “soft” of software also makes it rather different. We can, indeed, seemingly, must use an iterative or spiral development process rather than linear or “waterfall”. We can, and should, wherever possible use incremental development and delivery rather than “big bang” delivery. And we must build today something that can be changed tomorrow without mishap.

One very significant difference is our inability to use our senses on software. It is much more difficult to understand what we must write, or what we have written; we have misconceptions because forming a conception is so difficult. In the machine there is a pattern of billions of bits that we must get a handle on, yet we can’t see them, hear them, feel them or smell them.

Many of the systems in other engineering disciplines are continuous: a small change has a proportionate result. Changing one bit of a software system, however, can have an enormous and difficult to predict result. Software systems are non-continuous systems.

Perhaps it is that almost unique characteristic of software – that it can’t be sensed – that is responsible for another difference: unwillingness to pay what is required for a successful product. Now, of course, skimping and underfunding will occur in many areas of engineering, but it seems to be particularly bad in software engineering. Just because almost anyone can write a program, software project management seem to think that software should be cheap and that the only reason it isn’t is that, so far, they’ve failed to find their silver bullet that will make it so.

Software engineering is a less mature discipline than most other engineering. We have lots of amateurs, rather than professionals, producing software systems. Estimating “blue books” are not available. Standards for technology and documentation are still evolving rapidly, and although we might expect the documentation standards to stabilize we can’t expect it of the technology (and, quite possibly, the rapidly changing technology means that the documentation standards will never be able to expect to settle down).

Question 2.2
Think of and describe three metaphors that make interfaces easier to use. They don’t all have to be for software systems.

In software, the classic interface metaphor is the desktop. The book mentioned sound recording and mixing software than mimics a mixing desk and an effects rack. There have been database systems that mimic record cards. The spreadsheet mimics the accountants squared paper, pencil, eraser and calculator. Would the drag/drop mechanism count as a metaphor? I think so.

Outside of software chemical plant and transport control system have layouts that can easily be related (and respect the topology of) the routes of the pipes, the tracks, the roads, etc.; and, for example, valves controls look like valves and are presented in position, on the representation of the pipe in question.

In an aircraft the attitude and turn-and-bank indicators all present fairly direct representations of the aircraft, the horizon, etc.

[Screen widgets like thermometers, spinners, dials are, perhaps, meta-metaphors, metaphors for abstractions or other metaphors. A real speedometer, in a car say, is an abstraction of the notion of speed (and speed is a pretty abstract notion – most people turn out to have a better grasp of calculus that they think they do [and I love the observation that President Kennedy is said to have used a third-order derivative once: the rate of increase of inflation is slowing down]) and interface designers find it interesting to ponder why a needle and dial speedometer turned out to be vastly preferable to a digital speedometer in a car.]

Question 2.3
What is the difference between a model and a miniature? What is the difference between a model and a prototype?

A miniature doesn’t necessarily use an alternative medium as a model typically tends to do. A bonsai tree is a tree; it’s just unusually small. A miniature train is simply a smaller train. A model train on the other hand isn’t really a train. A model makes the communication, the exploration of something more convenient and cost-effective by representing just those things that are considered relevant [remember abstraction is ignoring as much as possibly you can] and representing them in a cheaper, or more tractable, etc., medium than the original. A toddler’s wooden train is a very abstract representation of a train, but it’s fun, cheap and, to the toddler’s imagination is an entirely adequate representation of a train. A program listing or a UML diagram isn’t just a smaller program or a smaller subject matter; instead they are more convenient abstractions and representations.

A model contains no inaccuracies or falsehoods (hopefully). A prototype [and because of the political and social problems with that word in software circles, the book recommended that you use the term “mock-up” instead] almost certainly has parts that are necessary for it to function, to fulfil its purpose, but parts that should have no place in a solution or parts that represent nothing in the subject or solution domains, or that aren’t there directly to help communication, reasoning, etc.

Question 2.4
Think of two more kinds of models that we use in engineering design and planning. Identify where they exhibit correspondence and where they don’t; where they predict something useful about an eventual product, and where they don’t.

I thought of a wind-tunnel model and a crash-test dummy. A vehicle model suitable for aerodynamic tests in a wind tunnel wouldn’t represent the engine very faithfully at all, nor would it represent the interior design; it would, however, faithfully (very accurately in fact) represent the external shape. A crash-test dummy wouldn’t have correspondence with the coloring, the chemistry or the electro-neural systems of a real animal, but it would faithfully represent shape, mobility and stiffness, mass and density distribution.

Question 2.7
(Moderately difficult) Why do you think the chapter text and the above question used the phrase “… objects would exhibit” rather than “objects would have”?

Some older approaches considered that not only did subject matter objects (or entities as the book terms them) have properties or attributes – which is fairly incontrovertible – but also that those attributes guided developers to the data that the counterpart solution objects would hold (instance variables (data members)) – which can’t really be correct. This is because in today’s approaches, the generally held belief is that solution object instance data will be private and should not directly predicted by anything the analysis discovers; rather than instance variables, the analysis entities’ attributes will guide us to object instance query services – methods that make a return and that don’t change the state of the responding object instance. If a query service happens to be implemented by reading a stored instance variable, well that’s coincidence in version v of the class, and might well be implemented differently in version v+1 of the class.

Question 2.8
[This is a difficult question for this point in the book, unless you already know object technology quite well. JD]
Describe as many ways as you can in which developers might actually show more of a class orientation than an object orientation; and describe as many benefits (or otherwise) of a true object orientation.

Developers might assume that analysis entities give us guidance as to what the classes will be like, rather than guiding us as to what the instances ought to be like. Class choices are heavily influenced by purely technical issues. We should establish the nature of the needed object instances and then let that, plus the technical issues guide us as to the classes required.

Developers might limit themselves to only reasoning with, and only documenting and specifying with, structural diagrams (“class” diagrams). A system development in which no instance diagrams (e.g. sequence diagrams, or object interaction diagrams) were done would be unlikely to be a successful system development.

Designers with a superficial knowledge of object technology might be led to design and specify the concrete classes or the abstract base classes (abstract superclasses) before designing the types (the interfaces or the purely abstract base classes). In outside-in design, as the book terms the approach it believes to be the correct approach, we care about the types the objects manifest before we care about designing the objects’ internal mechanisms.

Programmers might be tempted to use concrete classes as types (types of variables, types of parameter, types of returns) which isn’t really going to get the best from object-orientation. Types should tend towards being more abstract than concrete classes.

Classes vary from language to language far more than objects do, classes are a means to an end that are not even in all languages, and classes are more complicated than instances. Therefore, given the complexity and artificiality of classes, and that analysis suggests better objects than it does classes, i.e. the evidence as to the right objects is easier to come by than the evidence for the right classes, an object-orientation really is what we should be striving for.

Question 2.10
Consider classes that you or your colleagues might have developed. Do any of them exhibit suspiciously numerous getX() and setX() methods? Why would we be suspicious? Can we definitely say that such classes are wrong?

Form a judgment as to whether those classes were designed from the inside out – where version 1’s instance variables drove the design of the interface – or designed from the outside in – where the interface required by the clients drove the methods and variables of version 1’s implementation.

I’m thinking of a couple of classes I have seen, like an Invoice class and a Student class. The Invoice class stored number, date, net amount, tax and gross amount; and the interface had a “get” and a “set” method (member function) for each of these. This was OK (although my students are divided fifty-fifty on whether or not the names of the methods should actually include the prefixes “get” and “set”). The services that an invoice should deliver are indeed remembering and divulging its number, remembering and divulging its amounts, and remembering and divulging its date. And of course it’s quite reasonable to implement those abilities by storing those items of information. In other words the invoice object was, righteously, designed from the outside in.

The Student class had many more instance variables, each one of which was “given out” via “get”s and “set”s, for example, getMySqlMigrationDate() and setMySqlMigrationDate(). Given that there was no meaning whatsoever for the second of these, I concluded that the design was inside-out and thus poor. The version 1 date had been the only driver of the object’s interface design – not good.

Although one can be suspicious of classes with large numbers of get/set method pairs, one cannot say whether they are poorly designed or not without knowing more.

The key test of righteousness is whether a technical change to the stored data – the instance variables (data members) – wouldn’t necessarily imply a change to the interface. If we decided, for some bizarre reason, to store the day, month and year of the date in separate instance variables in the next version of the Invoice class, we would probably still keep the original two “date” methods in the interface. A developer who automatically gets rid of the original two methods and adds six new methods like getDay(), setDay(), getMonth(), etc. is really pining for Pascal or C, and is just producing thinly-disguised, overly-complicated data structures.

Then there are database systems that have decided to present their contents via objects (whether home-grown or via something like EJB). Here, inevitably, one will find a much greater degree of match between the interface and the stored data.

Question 2.11
Think about engineering and interfaces in general. Can you recall any examples of important interfaces, from economic history? Describe the characteristics of an interface and what we achieve by having them.

The examples that I had in mind involve Eli Whitney, Sir Joseph Whitworth and William Sellers. Eli Whitney had claimed to manufacture standardized musket parts, as as unique selling point for one of the very first government arms contracts, but had probably faked the whole thing thus beginning a grand tradition of the industrial-military complex that continues to this day. Joseph Whitworth described a method for standardizing screw threads in an 1841 paper titled “A uniform system of screw-threads.” An American, William Sellers, was convinced that standardized screw threads were a good thing but that Whitworth’s standard was technically inferior to his own, and convinced American manufacturing to start using his modification of the Englishman’s standard.

Although questioned at the time, standards quickly became important to all industry. Quickfit glassware, track gauges and plumbing fittings are just some of the countless examples of standards we rely on today. Interestingly, in the 1980s, the computer industry was not convinced that standards were a good thing – and open standards were viewed even more suspiciously. Standardization became accepted however.

A standard should be widely accepted. As long as it’s widely accepted, it can survive as a de facto standard, although it typically does help if eventually it becomes a de jure standard. A standard must be easily adhered to or it won’t be adopted and will be a standard in name only. A standard should be as simple as possible (loose coupling), restrict itself to describing what others will rely on and should avoid describing any implementation detail (information hiding).

With standards we can encourage componentization, increase reuse, increase plugability, decrease costs, ease maintenance and ease division of effort.

Question 2.12
[Practitioners] In a software development project you were involved in, think about the process that was used. Did the process claim to be linear, to be a “waterfall”, and if it did, was it really linear? Alternatively, perhaps the process claimed to be iterative or “spiral”? Was it? How was it managed and controlled? In your opinion was it under-managed with no clear definition of the major iterations and their deliverables and “mileposts”? Or was it over-managed with too many controlled iterations and deliverables?

The possible answers are all the question. You may have had a spiral process that worked fine, and all the while the management were thinking it was a successful use of the waterfall model. Or they might have insight and realized that they were using a very coarse-grained linear control model while the development was following an unmanaged iterative model. You may have worked in a project were someone had become enthused with the spiral model and insisted on seven managed macro-spirals, and perhaps on managing the micro-spirals as well; and probably found that that degree of control strangled the project.

Question 2.13
(Practitioners) In a software development project you were involved in, ask yourself if the development process tended to be driven by the required functionality or by a desire for as good an object architecture as possible. If you are in a position where you have witnessed the evolution of a system, how did it fare in the face of change? Did it make it “out of the door”? Did it make it to version 5? If you have witnessed the development of object-oriented systems under both a functionality-driven and an architecture-driven development process, where other factors were broadly equal (unlikely I know), ask yourself how their reactions to change compared?

I suspect that functionally-driven development processes for object-oriented software systems can produce fine products; but that those products don’t make past versions 3 or 4. I suspect that a successful and long-lived object-oriented software system will inevitably have a good, strong object architecture.

Chapter 3

Question 3.1
What packages would you use in order to organize the development of a new web browser? What influenced you in your choice of packages?

I was guided to my initial choice of packages by terminology and technology. The terminology of communications and networks is quite different to that of page rendering, as is the technology. By technology I mean that the libraries or frameworks that might help me out – where they came from, both commercially and culturally; and I also mean the “level” at which they connect to the platform – they would interact with quite different parts of the operating system. I was also influenced by Opera’s (the web browser I tend to use most) “Preferences” sections; one might as well look at the decisions of others who have done a similar development. I also considered maintenance – how browsers have changed over the years – which elements have come and gone.

The initial list of packages I might consider were:

  • Communication
    • Security and privacy
    • Internet
    • Local file system
  • Provision
    • Parsing
    • Plug-ins and players
    • Page rendering
    • Printing
  • Management
    • Users and preferences
    • Bookmarks

[I decided that web browser meant exactly that. You may have decided that, to be competitive, you would need to offer mail and newsnet handling as well, and certainly in packages of their own. JD]

[Which would be the worse mistake? Too many packages that were too small, or too few packages that were too big? I think that it’s the same as with classes. It’s better to err on the side of too fine a granularity. If one finds oneself correcting mistakes, it’s easier to amalgamate than to split. JD]

Chapter 4

Question 4.2
If you are a computer science student, expecting to work in systems development, you will find yourself in the minority in three-quarters of project developments where the majority of developers will be from the embedding world (see Section 4.3, on page 64) rather than computer science. What kind of competition is that going to present you with? What will you have to do to compete successfully?

Such a new hire would not have the domain, the context, the subject matter experience, of course. So computer science graduates would need to ask themselves what their USPs (unique selling points) would be, especially if there was a good chance that the incumbents might lack them. People who have come to computing from banking, from science, from engineering, frequently lack knowledge or have patchy knowledge about the technical issues of software systems. So a computer science graduate should ensure that (s)he has a thorough and insightful knowledge of a programming language, a comprehensive awareness of algorithms, and a “why as well as what” knowledge of the UML and design patterns. If there’s the slightest chance one will be working with real-time software or software that’s embedded in systems other than human systems, one should ensure that one knows state machine theory, state machine minimization and verification and higher-order logic.

[Of course, you’re working your way through Object-Oriented Analysis and Design: A Pragmatic Approach, so you will bring an unusually keen awareness of and insight into analysis and design. 🙂 JD]

Chapter 5

Question 5.4
“We would typically call up yesterday’s menu. We would check with Chef to see if any particular stock items need using up via any particular dishes. I guess that maybe the system could help us with alerts as to any expensive stock approaching its use-by date. We would amend the menu to remove dishes not on offer today and to add the new dishes like the stock-using dishes and any other dishes that the manager or Chef have planned.”

(You) “Would you type up the details of each new dish?”

“Well I guess there might be totally new dishes; but mostly we would want to call up some kind of overall dish list, where the typical price, description, etc. was already entered. Sometimes we would have to amend the defaults – for expensive ingredients whose prices fluctuate wildly, for example.”

(You) “And would you be changing yesterday’s menu to become today’s? Or would you be leaving yesterday’s menu on record and creating today’s from it?”

“Oh, we would definitely want to keep a record of previously used menus; we’d simply be using yesterday’s as a typical starting point. I imagine there would be times, though, when we’d create a menu completely from scratch.”

Given the above dialog, what extra questions would you have asked if you had actually been there?

  • How are the dishes assigned to menu sections and departments?
  • Might you create dishes by copying old dishes?
  • Might the system help you find the dishes that use particular ingredients?

[This question, of course, is an open question. Those were just the questions I’d have liked to have asked. You may have others. JD]

[As noted in question 3, the last one is doubtful. Sadly, sociology and the accounting considerations tell us “never volunteer” unless it improves your chance of success, and your system’s chance of success. JD]

Question 5.5
Rewrite the following requirements of POIROT and ALICE to be clearer and more precise. They don’t necessarily have to be correct. In other words, your job is to make them less ambiguous, you won’t necessarily have the information to make them more correct.

  • “The system must accept crimes.”
    “The system must register the details of a reported crime, typically including, but not limited to, the name and address of the person reporting the crime, and the date and time the reporter reported the crime.”
  • “Match fingerprints.”
    The system must locate and identify all recorded fingerprints available within the [censored] database list with greater than 9 points of similarity, listing the databases that were accessed and the accessible databases that were not searched.
  • “Produce bills.”
    The system must compute the current bill for a selected order, part of order or group of orders.

Question 5.7
You have limited time (as ever). Using your own knowledge of staying at hotels (or using your imagination), write up two important and illustrative use case scenarios for POLLY, the hotel system development mentioned in Exercise 3.3.

Use case name:
   Successfully checking in having already booked but not having preselected room
Use case reference number:
Initiating event:
  Guest succeeds in attracting the attention of a member of staff serving on reception.
Key outputs: Room entry card produced and room door programmed
Key state changes:
  Guest and room status updated
  The receptionist is enters the guest’s family name into the system, no booking reference number being available (as is typically the case).
  The system successfully locates and displays the booking.
  The receptionist confirms the recorded departure date with the guest. In this instance it is correct.
  The receptionist asks the system to suggest a room, given the party size (one in this instance), length of stay, smoking preference and discount given (the bigger the discount the worse the room.)
  The receptionist (in this instance) OKs the system’s room suggestion.
  The receptionist asks the guest if a newspaper or an alarm call is required.
  Both are requested and the receptionist informs the system.
  The system updates the room’s status to “occupied” and also records the guest to booking allocation.
  The system updates the occupancy’s status to “checked in”.
  The system prompts the receptionist to prime the key-creating system (put a key-card in the reader/writer in this instance).
  The system transmits sufficient information to the key-creating system, which report successful key creation and door programming.

[If the book’s primary focus were requirements, we could of course go deeper into all of this. We could look at Cockburn’s forms for use cases. We could consider goals instead of outputs and state changes. We could specify preconditions. We could enumerate stakeholder interests.
One thing I thoroughly disagree with, at the moment, and using use cases the way I use them – to illustrate and enliven the requirements rather than attempting the impossible by attempting to make use cases constitute the whole of the requirements – is putting in branches and alternatives. A use case should not be yet another flowchart in yet another form.
Something, however, that I do thoroughly agree with is factoring out sub use cases when things are starting to settle down, relating use cases via the includes (or “calls”) relationships and being very sparing with the much more confusing and fragile UML extends and generalizes relationships amongst use cases. JD]

Use case name:
   Successfully checking out on the morning of departure
Use case reference number:
Initiating event:
  Guest reaches the head of the checking-out queue at long last.
Key outputs: Invoice and room door programmed
Key state changes:
  Guest and room status updated, and payment recorded
  The receptionist identifies the room and confirms the guest’s identity (in this instance with their name).
  The receptionist adds the missing mini-bar items the guest has consumed.
  The receptionist requests an invoice printout.
  The receptionist confirms the invoice with the guest. In this instance it is deemed correct.
  The receptionist informs the system that the room is vacated.
  The system updates the room’s status to “dirty” and the occupancy’s status to “checked out”.
  The receptionist informs the system that payment has been successful, when (s)he has determined that to be the case.
  The system updates the occupancy’s status to “paid”.
  The system transmits sufficient information to the key-creating system that the room’s door can be reprogrammed if necessary.

[As we have limited time, we have been careful to choose critically important and highly illustrative use cases. JD]

Question 5.9
Think about and write up a SWOT (strengths, weaknesses, opportunities and threats – essentially an enhanced version of pros and cons) analysis of prototyping as a technique in software engineering.

SWOT analysis of Prototyping
Strengths Weaknesses
A cost-effective exploration technique
Software prototypes can easily [and mistakenly JD] be made to look like a finished product
Software prototypes resist being thrown away
The term "prototype" has perhaps lost its connotation of "mock-up" in software engineering
Software prototyping gets confused with staged delivery
 – in the minds of management
 – and in the minds of developers
Software prototypes were (are?) one of our "silver bullets"
Opportunities Threats
Validating crucial design decisions/possibilities
Answering crucial questions
Evaluating crucial technologies
Customer getting wrong impression of progress
Management getting wrong impression of progress
Developers getting wrong impression of progress
Surreptitious mutation into version 0.9 or version 1
Prototypes particularly GUI/VB becoming design drivers (RAP/RAD)

Chapter 6


Question 6.1
Consider a music player such as a CD, MD or MP3 player. Consider the random or shuffle play function that they often provide. As an exercise in abstraction, how would you describe the meaning of shuffle, in words (after the next chapter, you can try it as an activity diagram).

The temptation is to say pick a track at random. But that won’t do: some tracks wouldn’t get played and some tracks would get played more than once. What you want to do is pick at random an as yet unplayed track from the tracklist, play it and mark it as played. When all the tracks are discovered to be marked as played, clear all the marks.

Question 6.2
The text mentioned (page 103) that one shouldn’t confuse the one instance you can easily see for the set that it is an instance of. The example question was whether Perpetrator was an entity set, or whether it was a particular instance of a Suspect entity set that the model would be better off having. How would you answer that question?

We would first check that the names “Perpetrator” and “Suspect” were good names, otherwise the following test wouldn’t work. Good names would be complete, accurate, honest, colorful and reasonably concise.

We only need to do what we would usually do when considering the classification of entity instances into entity sets: ask ourselves what the characterizing properties are. What would be the characterizing properties of a Perpetrator entity set? What would be the characterizing properties of a Suspect entity set? Would one be a proper subset of the other? Would the fact that some particular instance was a “perpetrator” instance naturally and adequately be modeled by its particular values for Suspect characteristics? Or would there be no characteristics of Suspect that weren’t also Perpetrator characteristics?

Question 6.4
(Moderately difficult) If you work in, or know something about, a subject matter like the following, list the entities you think might be relevant to a typical piece of software that concerned itself with that subject matter?

  • weather reporting and forecasting
    Forecast, Observation, Front, Cline, Station, Satellite, Cell, …
  • fingerprint matching
    Surface, Developer, Lifter Tape, Officer, Location, Date and Time, Feature, Point of Similarity, …
  • radar operator training screen simulator
    Beam, Obstruction, Reflection, Failure, …
  • congestion charging
    (Congestion charging is where, as you enter the center of London for example, your vehicle’s number plate or “license plate” is read by a camera and those who have not paid their congestion charge by the end of the day, at a newsagent shop say, are sent a notice of a penalty fine.)
    Exemption, Observation, Fine, Letter, Conviction, …

Question 6.7
Figure 6.25 had an example of an association relationship named with a single identifier “in the middle”. The advice that accompanied it was to use role names at the association ends instead. Do that, recording any assumptions you make.

figure 6.25

I assumed that a crime would potentially have several officers assigned to it, but that if the model doesn’t separate out crimes that are no longer under active investigation, a crime might have no officers assigned to it. I assumed that if an officer is active in some investigation at some particular point in time, the officer will be investingating one crime.

[As per the book’s observations and recommendations, I have named the “moment of time” relationships with a present participle. JD]

Question 6.10
In the UML appendix (Appendix C) there is a section on generalization sets. We haven’t covered them in the main text because they are not really object-oriented. However, the three classifications illustrated by Figure C.38, on page 496, give us interesting things to try to model. How did we, and how would you model those classifications?

[The first printing had an error. The reference there was to Figure C.40 which wasn’t even about generalization sets! JD]

Our model used menu sections for modeling whether a dish was considered to be a starter, a main or a dessert course. What would we use for the other two classification schemes of “spicyness” and “morality”? “Course” was modeled via a menu section entity because of the open-ended nature of menu sections. What one restaurant calls a starter, another might call an entrée, and so forth. With “spiciness” and “morality”, it would seem reasonable to assert a fixed number of possibilities, and thus to be able to use dish attributes with enumerated values: {spiced, bland} and {meaty, fishy, vegetarian}, for example.

Chapter 7

Question 7.3
In the context of financial accounting what might Customer, Investment, Cruise Ship and Tanker have in common?

Two are ocean-going vessels and all are assets.

Question 7.4
In the context of a mathematics package, what might Circle and Ellipse have in common?

They are both conic sections.

[This was mentioned in the text as a question that is perpetually circulating in the object world. “Is circle a kind of ellipse or is an ellipse a kind of circle?” And the answer is, “Tell me what they both do and then I’ll figure it out. (And I already suspect that neither is a subtype of the other; rather that they are both subtypes of some third supertype.)” JD]

In the context of CAM axle-grinding, what might Circle and Ellipse have in common?

Very little.

Question 7.5
In the context of a fighter-pilot training simulator, what might Bird Flock, Detonation and Cannon Round have in common?

They might all be threats.

Question 7.6
(Moderately difficult) Write a short essay comparing and contrasting the generalization relationships that one might find and model in subject matters (“the real world”) with the inheritance mechanism in the programming language you know best.

Most modeler’s use of the generalization relationship is for taxonomy. Blackmail and robbery are both crimes. Electrons and muons are both leptons. Gilts and bunds are both kinds of bonds, and bonds and shares are both kinds of investments. Some kind of abstraction is being performed: if I ignore this, this and this, then I see that these things have something in common.

The inheritance relationship found in object-oriented programming languages often involves the acquisition of something. This is particularly true in languages like Java and C# where there is a way of acquiring extra types without using inheritance. And this quality of acquisition accords with the natural use of the word inheritance, of course.

When we ask the question, “How does similarity in subject matter entities manifest itself?”, we usually find nothing more than, “They have subsets of properties in common.” So the word inheritance, in its natural sense, could also be used. However, subject matter modelers usually feel able to portray generalization relationships without actually haven fastened upon the properties to be modeled, so perhaps “generalization” is the more appropriate term for the subject matter relationship.

Does the term “generalization” have an obvious corresponding term in programming languages? Not really. In Java, the term used is probably closest in semantics – “extends” – whereas the C++ term, “derived from”, is probably closer to the semantics of “inheritance”. But it’s neither clear nor obvious.

Are we merely worrying that the terms are different when the semantics are actually the same? No, because the inheritance mechanism in languages like C++ and Java can do two quite distinct things. The inheritance relationship can give an object extra types, which is an externally manifest quality, an interface quality; and the inheritance mechanism can give a class extra instance variables (data members), which are not manifest externally provided one follows the ubiquitous advice to keep them private, and extra methods (member functions), which are not manifested externally in languages like C++ and Java. (Method signatures might be manifested externally, that though is what we deem type; methods, that is to say the code, are not manifested. One can call a function but one cannot ever call a member function or method, one messages the object whose method it is.) This separation of interface from implementation, of “is a kind of” from “works like”, is one of the most powerful features of object technology, whereas such a separation is almost never found in subject matters.

Java and C# handle this stuff quite differently to C++. In Java the inheritance mechanism must always at least include an “is a kind of” relationship, i.e. type inheritance, whereas in C++ the programmer can (although in object-oriented C++ is not encouraged to) elect to only inherit implementation, i.e. only the “works like” relationship, using non-public inheritance. (Java only has the equivalent of public inheritance.) This reflect the common perception, today, that type is the strategically important thing, that there are alternatives to implementation inheritance (i.e. composition and delegation)

Do the generalization relationships in subject matter models tend to indicate type relationships to designers or implementation relationships to designers? Given that implementation is not manifest and is more arbitrary, or one could say more technical, one would have to suspect that the generalization relationship of subject matter models does not suggest inheritance of implementation as well as it suggests inheritance of interface (type).

One must also point out a big difference even between generalization and inheritance of type: type in subject matter models is typically determined by attributes and relationships and perhaps state-transition patterns, whereas type in object-oriented programming is usually determined solely by message signatures.

Question 7.8
Briefly describe all the reasons why we might need to be more careful with generalization relationships than with associations and aggregations.

  • Generalization relationships couple entire sets of things together, whereas characterizing relationships (and use relationships) potentially couple only individual instances together.
  • The coupling of generalization relationships is stronger for another reason. Three things traverse a generalization relationship: sharing of attributes, sharing of relationships and sharing of state-transition patterns. (Or you could say more than three things because there is more than one kind of relationship being shared.) In a characterizing relationship only identity traverses the link.
  • Because generalization’s differences as to meaning and functioning are greater between the analysis and design than are the differences for association and aggregation, the difficulties of getting good predictions are greater and even more care in getting correct relationships is required.
  • Some developers’ education channels might have over-emphasized the importance of generalization, over-emphasized the usefulness of generalization, encouraged “top-down suspicions” rather than “bottom-up determination”, anticipated too great a similarity with inheritance and anticipated an unrealistic payoff from inheritance. For several cultural reasons, then, we have to be very careful. (It’s a judgement as to whether said care is greater than the care required over other traditional misdirections, such as association directionality.)

Question 7.9
Here is a simple exercise to get the hang of state machines. Recall the state machine that recognized certain binary number representations (Figure 7.23, on page 195). Create a state machine that recognizes when an odd number of 0 digits and an even number of 1 digits have been seen. (By “recognize”, we mean that being in certain states indicate that the pattern has been seen, whereas being in all the other states indicate that it has not.)

Assuming, as the majority of mathematicians seem to, that zero is an even integer:

odd ones, even zeroes

[I find this an interesting example. Even though is “simple”, it seems to me to illustrate that one cannot read a state machine’s correctness; one must somehow run it or come up with an insight that helps verify it’s correctness. Now it may be because I’m not terribly bright, but my first effort looked correct and wasn’t; a couple of test cases soon established that.

The above solution passed all my test cases. I was nervous though. (For a moment I had wondered if I had set a problem that a state machine couldn’t solve. But it is a partitioning problem, and not a counting problem, so a state machine can do it.) There was no-one around for a walkthough, so I did a “cardboard cut-out review“. The above solution passed. I was still nervous, however. Then I found the right way to look at it. The state machine above oscillates up and down on 1s, and left and right on 0s. With that picture I was finally happy. But what if I’d drawn it in a different orientation? Would I have found the right way of looking at it? Can I ever expect to find the right way of looking at a state machine with more than nine states? JD]

Question 7.11
Here is a simple exercise to get the hang of activity diagrams. Recall the algorithm described in Exercise 6.1, on page 163. Present it in the form of an activity diagram.

shuffled play list

Chapter 8

Question 8.2
Can you think of an element of a typical restaurant system that our computer system would definitely make redundant? (One example of such a thing will come to light in the CRC case study that’s coming up soon.)

The diary is one example; and the manually-written bill would be another.

[The interesting thing about the diary is that it very often surfaces as a candidate entity in exercises; and is quite frequently kept as an entity in the analysis model. However, when it comes to design time – in the book it happens during the CRC workshop – the idea of a diary causes as many problems as it solves. It is when (perhaps) the invented notion of a diary-per-table surfaces, that the diary starts to show its worth. But why was the diary not a direct clue, only “half a clue”? Because it is existing-solution-up-for-replacement, rather than subject matter. JD]

Question 8.3
It is many years ago and you are doing the analysis for some accounting software that will run on a standalone PC. In an investigation of purchase accounting, you encounter some supplier invoices and a rubber stamp that is applied to a supplier invoice such that an authorizing signature can be obtained from the person who placed the order. Would the suggestions made here lead you to consider the invoice and the stamp as part of the subject matter, or as a part of the existing system that’s up for replacement? Record any assumptions you make.

The invoice would seem clearly to be a part of the subject matter. It will still be there when the new system is in place, and it will be an important thing, whose existence and state the new system is very likely to model. Human authorization will still be there. I would classify of these as subject matter. The rubber stamp? There or not, potentially subject matter or existing system up for replacement, I’d deem it irrelevant in either case, and thus not include it.

Assumption 1: All those years ago, one could not have expected one’s suppliers to stop sending purchase invoices, even if this were some kind of corporate group where the supplier and the customer were part of the same group.

Assumption 2: A standalone PC would not facilitate electronic authorization of purchase invoices.

Assumption 3: Investigation has shown that the rubber stamp itself is of no consequence. It could use a different ink color. It could be completely redesigned. It could be replaced by penciled scribbles. And the system-to-be wouldn’t “give a damn” about any of these changes.

Question 8.4
The time is today and your world famous accounting packages are being updated for the paperless offices of electronic data interchange. Would the suggestions made here lead to you to consider the invoice and the rubber stamp mentioned in the previous question as part of the subject matter, or as a part of the existing system that’s up for replacement? Record any assumptions you make.

It’s possible, now, that authorization and invoice provision no longer need to be done physically. We can treat both as existing system up for replacement.

Assumption 1: There is a possibility that some suppliers can be persuaded to submit invoices electronically.

Assumption 2: It is not infeasible that authorization can be done electronically in both a convenient and trustworthy way.

Question 8.5
You are an analyst working on the development of a computer system for high street insurance brokers’ offices. Describe the advantages and disadvantages of studying an existing clerical (people and forms) system.

It’s eminently doable. Forms are easily understood, even if they’re terribly badly designed. People can be interviewed and asked to introspect on what they do and why they do it. If the requirements indicate that the system-to-be is intended to do the same as the existing, clerical system, but perhaps faster and more reliably, i.e. computerization is what is required, then a systems analysis would make a lot of sense. We have a lot more experience of systems analysis than we do of object-oriented systems development.

On the other hand, the existing system may have flaws or may be doing things in a less than optimal way. Or the system-to-be may be required to accomplish things that the existing system doesn’t address at all. If that were the case, and the only activity prior to design (invention) were existing systems analysis, we would surely have missed some valuable, extra, definitive input to the design. Also, such a system tempts one to consider a description using dataflow and dataflow diagrams. However, experience (and reason (in hindsight)) shows us that a dataflow picture (functions activated by the arrival of dumb data) isn’t very amenable to objects being designed from it. Finally there is the problem of “blinkers”. Once an existing systems has been extensively studied, it can be difficult to conceive of new ways and means. Of course the job of “systems analyst” was usually taken to include the skills to suggest improvements and to suggest new and possibly more appropriate approaches.

Question 8.6
You are an analyst working on the development of a better computerized records system for a high street video and DVD rental shop. Describe the advantages and disadvantages of studying the existing computer system, which was developed by the proprietor’s next door neighbor computer enthusiast using a visual version of the BASIC programming language from 1998. Describe any (reasonable or unreasonable) assumptions you make.

Given the ominous description of the existing system, one must expect just about no advantages to studying the existing computer system. The disadvantages are that it would be extremely difficult to discover useful input to the development of the replacement system, and thus the very poor return on large, and painful, investment. This is the reverse engineering problem. There are perils in any reverse engineering – “Let’s take apart one of our competitors washing machines and copy what they did.” With software engineering, the “soft” amplifies the perils, and, along with being unable to use one’s senses on software, hugely amplifies the difficulties of software engineering.

Assumption 1: The BASIC is all we have. There is no other documentation, specification or explanation.

Assumption 2: The BASIC syntax is difficult to understand in the large because it has no singular underlying conceptual paradigm and because there is little in the way of modularization apart from some dubious function mechanisms (the BASIC I remember didn’t even have recursive function calls).

Assumption 3: The BASIC code is difficult to understand because the comments (if any) are only of typical (i.e. poor) quality.

Assumption 4: The BASIC code is difficult to understand because Visual BASICs tended to encourage developers to develop a nice GUI (view), and then to just tack the essential application logic (model) onto the GUI “objects” (possibly even then being led to claim that the system was “object-orientated”.

[Ouch – I seem to be in a bitter mood this morning. Surely it won’t be that bad! JD]

Question 8.7
(Moderately difficult) You have decided to analyze that existing, clerical system in a high street insurance broker’s office. What kinds of UML diagrams do you suspect you might find useful?

  • Structure diagrams (“class” diagrams)
  • Activity diagrams, perhaps in their flowchart profile, but possibly in their dataflow profile

I suspect that the dataflow diagrams would look like the easiest place to start. My experience tells me, however, that I should model as much as I can with entities and relationships before I start to supply any crucial processing perspectives. The later that one begins to orient around objects, the worse those objects seem to be.

Question 8.8
(Moderately difficult) You have decided to analyze that existing computer system written in BASIC. What kinds of UML diagrams do you suspect you might find useful?

  • Activity diagrams, hopefully in their structure chart profile, but perhaps, sadly, in their flowchart profile, assuming that I make the same assumptions as before.

Question 8.9
You are a team leader and the following memoranda have been exchanged between you and your boss.

“Your team is going to carry out the analysis for the replacement of the investment analysis software we inherited from Ripe For Plucking Inc. Do you think five weeks will be enough?”

“How easy is it going to be finding a couple of investment and portfolio experts for us to talk to?”

“Ah… You can’t talk them. They’re over the other side of the world and it’s all rather sensitive anyway; they mustn’t know just yet that the replacement system is being developed here. You’ll just have to look at the listings of the current system.”

“But it was written in WIZFL 3 and what few comments there are, are out of date. And as far as I know, the original design documentation was “lost” when the disks were shipped to us.”

“Well, what about that reverse engineering tool I bought you last year, surely you can just use that.”

Write your reply.

“You can’t reverse the sausage machine and get the pig back.” Saint Gregory Thaumaturgus, AD 271.

While a reverse engineering tool can illuminate a little of the structure of a software system, albeit in a somewhat trivial way, it cannot tell one anything about why that structure was chosen; and, most importantly for us, it tells one very little about nature the problem that the system was solving. At each stage of transformation towards eventual code and compilation, structure and information are lost.

Surveying reverse engineering success stories via Google, we found that the vast majority of the first 200 were all from vendor sites. Developer postings regarding reverse engineering successes were conspicuously thin on the ground. There were several horror stories, however. I’ve attached one such from Acme Broking Systems’ chief architect. Perhaps you recall that project; they were one of our competitors. It was that project where the user group successfully mounted a class action against Acme, and where the project manager had their stock options revoked.

In software trials run at the Govgravytrain Institute on 382K of executable program, where groups of approximately 115 subjects from the the top quartile of graduate computer science students of several nearby universities were shown memory bit patterns, none of them could figure out what the software would do; when shown assembler printouts with address mnemonics of average quality, only 2 students correctly deduced what the software would do, taking on average 19 hours each to come to their conclusions; when shown BASIC code of average quality, 3 students made correct deductions after 15 hours study; and when shown Smalltalk code of average quality, 5 students made correct deductions after an average of 10 hours study. The conclusion was there was no magic point at which the semantics could be deduced from the code.

[None of these arguments succeeded. The reverse engineering tools were used. The analysts tried their best over the next three months, but to no avail. Things were starting to look shaky, so the boss managed to get h(er/im)self promoted to another project that was just starting up. The project was cancelled a few weeks later. And so another project was added to the pile of those that didn’t make it out of the door. JD] [And this is just an illustration of a possible answer, of course. Very little of this actually took place. JD]

Chapter 9

Question 9.2
You have been asked to help defend your team’s request for a development budget increase by eloquently and succinctly describing the benefits of correctly and adequately done analysis and design.

[JD. The eloquence is down to you, dear reader. Some of the points you might have covered are:]

  • Without a design there is a greater likelihood that building begins with insufficient thought (conceiving and planning).
  • Without a design it’s not possible to apportion work successfully, so the optimal number of implementers is just one, and it’ll have to take as long as it takes.
  • Without a design perhaps no thought will be given to modularity and structure and, thus, no maintenance will be possible. The impact of change will be large at the start and will worsen rapidly. And let us not forget that maintenance begins when compiler errors are dealt with, so software corrosion will begin instantly and the product might not make it out of the door. It certainly won’t make it past version 2 or version 3.
  • Many other things will not be possible without some kind of design documentation: testing, requirements coverage, impact analysis, …
  • Without a design, perhaps some thought will be given to structure by the implementer(s); however, it will be difficult to achieve coherence or elegance.
  • Without an appropriate structure, it may not even work properly.
  • Without some strategic design thinking, beneficial aspects of the platform may be underused, and deficient aspects of the platform might be overused.
  • Without a design, if it should ever come to pass that a re-implementation, say in another language, is required, then it is highly likely that the same amount of work will be necessary as was necessary the first time. With a documented design (especially if it was kept up-to-date) a re-implementation should require significantly less time.
  • Although reuse is somewhat difficult to achieve locally (most successful reuse is via non-local frameworks), there is almost no chance of reuse, at the component level or at the framework level, without a quality, documented design.
  • Without an analysis, the design has no input apart from technology skills, technology documentation, requirements and previous designs (unless designs weren’t done). Planning and execution of the design activity will be more haphazard. And let’s not forget that a 300 KDSI project (1 KDSI = a thousand deliverable source instructions) might have a requirements document that correctly consists of a single paragraph. [It does depend on how you define analysis and requirements, of course. Naturally, this is using the book’s definitions. JD]
  • The beginnings of a defined and repeatable process are not obvious if the analysis does not take place. Pragmatically, analysis gives a place to start and something we can definitely do in order to get going.
  • Without an analysis, any correspondence between the nature of the problem and the architecture of the solution is coincidental. Thus the impact of changes in the subject matter upon the design and implementation will be higher than it need be. (There might be cohesion (if a design was done) but it will merely be technical cohesion; conceptual cohesion will be absent or reduced.) Analysis can begin a model, an architecture, and ensure that there will be correspondence between the problem and its solution.
  • Without a documented analysis, the subject matter might be misunderstood. If there is understanding, it might not be consensus understanding.
  • [I might have put down re-use of analysis models or model elements. However, there are so many other factors mitigating against that, that in all fairness, we can’t claim that a good analysis will amplify reuse. JD]

Chapter 11

Question 11.4

In the early stages of the CRC session described in the case study, Booking was considered for the placeBooking responsibility. Write down at least two good reasons why you might turn down the responsibility if you were playing Booking.

  • One is in the text – which booking am I? We can’t be messaging the new booking to make itself. Taken to extremes, this is sometimes known as the “magic constructor”. “Let’s just instantiate a valid booking in the right place if these ‘ere objects are so all-fired wonderful.” One ends up with all the logic in a constructor; constructors aren’t run by objects against their own state, so we wouldn’t be being object-oriented and such a constructor would be huge, complicated and unmaintainable – no progress. And we can’t be messaging another booking instance to place the new booking instance. How would this other booking instance be chosen? What singles it out? Another way of looking at this objection would be instantiation – I might not exist yet.
  • Another reason for refusal would be that too much knowledge of restauranting would be required on the part of the message sender – a view (GUI) object at this juncture. If the interface/view/GUI object were to message a creature as simple as a booking (or a table) then surely there would be lots of work left for the interface/view/GUI object to do; and, inevitably, being able to carry out that work would place a lot of restauranting logic in the interface/view/GUI. Imagine porting the application from one GUI to another, and picture the large quantity of logic would be “left behind”.
  • One could also invoke the “can’t see me” reason. There are a strictly limited number of mechanisms by which one object is able to get a message to another. The typical six mechanisms are listed in the text. None would be reasonable here. The booking definitely shouldn’t be global; there’s no way that the GUI could have received an appropriate booking as argument or as return; and it’s quite unreasonable for some GUI object to hold an instance variable (data member) expressly for being able to message some particular booking.

Question 11.6

The Booking object type was described in terms of its message-accepting interface toward the end of the case study section. Present it as a UML classifier symbol (a multibox).

alice booking type multibox

[Note that these are types, so visibility marks and other implementation details are inappropriate. It’s a good idea to give formal names for the parameters. The text left undecided details of the “suitability” enumeration; I’ve filled in some example detail. JD]

Question 11.7

Checking the requirements, as one must from time to time, you realize that you have overlooked floating bookings. If a member of the restaurant staff is convinced that they can take a booking because they are sure at least one table will finish in time, the system should accept the booking to the restaurant or to a zone rather than to a particular table. The final table allocation will take place on the night. For safety, you learn, there is a policy maximum on the maximum number of floating bookings that can be taken.

What do you think is the impact on the emerging design: a few simple changes in some obvious places, or a major reworking of the design? Have our efforts given us a flexible design after all?

Bookings are currently accepted by dairies that belong to tables. In the process of being accepted they seem to successfully participate in finding destinations that are suitable for them. I see no extra, impossibly difficult questions that a floater needs to be asked. And I can easily picture a dialog ensuing when no table has been able to accept the booking, wherein a restaurant is asked, or a room (also known as “area” or “zone”) is asked, if it can accept the booking. Restaurant and room objects could quite reasonably have knowledge as to policy and limits, or knowledge of the objects that do have such knowledge, and could take a decision on whether or not to accept the floater. It would also be quite feasible for booking dialog objects, in the GUI, say, to check for floaters and keep a warning visible that they floaters are present and that the staff of the shift must ensure they are dealt with and homes eventually found, typically by a table booking turning out to have an earlier departure time than the one that originally anticipated.

[This activity is sometimes known as “change case”. One saves up speculative requirements – requirements not destined for implementation in any of the planned stages of incremental development and delivery – stage n requirements, where n might be infinite. JD]

Chapter 12

Question 12.1

In Choosing abstract types on page 340, we mentioned a change case where House instances, acting under the type Dwelling were joined, later, by Apartment instances. Then I casually threw in Caravan (or Trailer) instances. Sketch out some simple Dwelling message signatures, and assure yourself that House instances would happily implement responses to them. Now picture Caravan (Trailer) instances joining in. Are you happy that the Dwelling type survives this change case or might it be broken?

One must ensure that the messages we try out are truly messages that a dwelling could be expected to accept. Obviously fourWheelsOrTwo() is an unfair test. So what types of messages are as specific as “dwelling” but no more specific than that? Mine were:
int occupants() [the UML would say occupants() : int]
Occupant eldest()
Occupant youngest()
Date lastCensus()

I am happy that these are as appropriate for trailers (caravans) as they are for apartments or houses.

Question 12.2

In Figure 12.20 an InterviewTape class was depicted with the method:
lengthInMins() : int

Write a few words on the units problem suggesting alternatives to the above.

We can reasonably complain that a date is a simple concept that ought to be simply measurable, but that the length and variety of human history has produced many, many ways of indicating the value of a date. However we measure it, though, one aspect will involve an arbitrary unit of measurement, be it the time a cesium atom takes to execute a few quantum thingamabobs or be it the duration of the king’s sneeze.

In addition to time, however, there are several other dimensions of measurement (the study of which is known as dimensional analysis), length and mass being the two others of the three most basic. Then there are combinations like speed or acceleration. Thus when something hands over a simple, primitive number as the answer to a question, we must wonder whether or not it’s in seconds, or grams or meters per second per second.

The adjective “primitive” above gives a clue as to one way of keeping the answer simple (low coupling) while handing over the extra necessary information:

  • use a Duration object instead.

The other possibilities are:

  • as it began, the method name can indicate the unit;
  • there can be an underlying default unit for each kind of quantity;
  • there can be an underlying default unit for each kind of quantity, along with a bunch of constant, symbolic multipliers, such that one can write things like:
    currentTape.length() * minutes
    if the base unit happened to be minutes then the “minutes” constant would be 1; if the base unit happened to be hours then the “minutes” constant would be 60. One gains flexibility and readability.

Question 12.5
Describe the advantages and disadvantages of deferring the planning of implementation inheritance relationships until late in the design.

There aren’t really many disadvantages. I only buy into one:

  • Poor notes, or poor attention to tricks such as using #include, could lead to missed opportunities for factoring out common implementation.

The advantages of doing the implementation inheritance as late as possible are many (only the optimization comes later):

  • Implementation inheritance will be based on evidence rather than supposition and surmise;
  • Many of the changes that would have eroded away at similarities should have already happened;
  • I think it’s a good idea to do the easy, fact-based stuff before the difficult, speculative stuff; and it seems to me that the evidence for types and concrete classes arrives earlier, and is clearer, than that for superclasses (base classes);
  • Developers are unable to build superclass (base class) names into their own source if those names don’t exist until the very end of the development; and it’s a very good thing if superclass names are mentioned just once, in subclass (derived class) declarations.

Question 12.7
Compare and contrast overloading and overriding in languages like Java, C++ and C#.

Overloading is a fairly trivial convenience feature, albeit one that we are grateful for most of the time. It simply means that we don’t have to invent unique names for every single method, even methods within a single class. There are more features than just its name that contribute to specifying a particular method or function being messaged for or called. In most languages the ordered types of the method’s or function’s parameters are matched (bound) with the ordered types of the method’s or call’s argument types.

Other things might also contribute to identification (binding). In C++, for example, the const-ness of an object helps determine whether a const member function, otherwise identical to another non-const member function, should be used.

Overloading has been around since before object-orientation.

Overriding, on the other hand, is more specifically an object-orientation feature. Overriding concerns superclass (base class) method (member function) declarations and subclass (derived class) decisions as to what to do about them. If a superclass has an available (e.g. non-private in C++), non-abstract method then a subclass can simply do nothing at all, whereupon a message that was declared in the superclass, being received by an instance of a subclass, will be answered by the superclass method. A subclass can choose to do something rather than nothing. A subclass can provide a method with the same distinguishing characteristics as the superclass method in question, whereupon the subclass method is said to override the superclass method, and upon receipt of an appropriate message it would be the subclass method that would be used to answer the message rather than the superclass method. (The distinguishing characteristics referred to a moment ago are often called the “signature”. The signature of a message is matched to the signature of an available method.)

There is a more subtle, and very important, variety of overriding – compulsory overriding. This concerns abstract methods, or pure virtual member functions as they are known in C++. If a superclass declares a message rather than a method, i.e. it declares what starts off looking like a method but there is, and there is declared to be, no code, then we often call that an abstract method. The more abstract declarations that a class makes, then the less concrete and more abstract the class. A concrete subclass (one that can be instantiated) of a superclass with abstract methods, must code up the abstract methods, i.e. there is compulsory overriding going on.

C++ does provide us with some headaches in this area because overloading and overriding interact with a much older and inconvenient concept: name hiding. Older languages, including Pascal and C, had the idea that it would be useful to allow programmers to employ another kind of name reuse – to allow a nested scope block to use, and hide, a name that was already in use in a nesting scope block. When C++ comes along and considers that a derived class is a nested scope, the name hiding inherited from C and the overloading added by C++ interact in ways that can be surprising and confusing.

Java, rightly in my opinion, says that name hiding is more of an irritation than a convenience, and makes it illegal: names must be capable of being distinguished by more than just their scope in Java.

Question 12.8
I have in front of me some object-oriented programming notes that I claim I wrote long ago when I didn’t know any better. They talk about a vegetable superclass with a cook method, and a root vegetable subclass with an overriding cook method. They then go on to talk about sending the cook message first to an instance of the vegetable class and then to an instance of the root vegetable class. How many things can you find wrong with that example?

Well first-off it’s a rather silly example, typical of textbooks, and one that I feel thoroughly ashamed of having used myself (long ago, honestly). I am hard-pressed to think of any system in which a vegetable object is going to be likely. However, that could just be my lack of imagination. If we assume that a vegetable object was indeed necessary, then an even bigger leap of the imagination is required to justify sending it a cook() message. [You should be similarly suspicious of examples concerning Camel and Mammal classes, Panda and Bear classes or Car and Boat classes.] Are we talking about embedded software here? Are we considering a microprocessor embedded in a vegetable and with a heater attached, in order that we can have self cooking vegetables? Or should we have sent the cook() message to an object embedded in a saucepan or an oven, with a vegetable as argument?

That’s rather a subjective objection, however, so onto a more objective objection. It’s not a good idea to instantiate superclasses (base classes) even if one could. Theoretically in many languages it would be possible to create an instance of a superclass if it had no abstract methods. There are good reasons not to do so under normal circumstances, however. Superclasses by their very nature take a long time to stabilize. Allowing another part of your code to create an object instance from an unstable class isn’t a good idea. Some of the characteristics of implementation inheritance that make superclasses slow to stabilize have been discussed in the answer to question 12.5. It’s best to keep superclass names out of parameter, return and variable declarations and out of new statements. The only place where a superclass name should normally be uttered is in the superclass declaration of a subclass definition.

[Use interfaces or pABCs for types (parameter, return and variable declarations), use concrete classes or factories to get objects, and keep the superclasses secret from all but their subclasses.]

Question 12.9
What was your conclusion about whether the CriminalRecord class should inherit from the LinkedList class, or whether CriminalRecord instances should contain a LinkedList instance (Section 12.9.8)? Why?

The CriminalRecord class should define that its instances contain a list class instance. Why?

First of all note that we don’t have to say what kind of list class. Whatever it is, it will be in a private instance variable and will not (should not) affect the interface of the CriminalRecord class. Inheriting from LinkedList would be a much more difficult decision to undo, as it would have an effect on the inheriting class’ interface.

Use of inheritance here would fail the substitutability test (sometimes known as PoS, the Principle of Substitutability; or LSP, Liskov’s Substitutability Principle): someone (some object) expecting a list to turn up, and finding instead that a criminal record had turned up would be somewhat disconcerted.

Another way of phrasing the above objection is that inheritance gives the CriminalRecord class the LinkedList type along with list mechanisms when it is actually just the mechanisms that are wanted. One could argue that, in C++ at least, it is possible to use a variety of inheritance (private inheritance) that doesn’t donate type; but doing that means that the alternatives of composition (“has a”) and inheritance (“works like” – remember we’ve switched off “is a kind of” in this kind of inheritance) demonstrate no unique gains; and since inheritance has several unique drawbacks, composition is preferable.

The biggest objection to the use of unnecessary inheritance is the fairly massive increase in coupling – class coupling. We can’t even talk about instance coupling because the two classes are producing a single object. Imagine that highly-likely scenario in which the superclass turns out to be not quite right. Rats! we should have used a hash table and not a linked list. Unless no code anywhere happens to have used the CriminalRecord class yet, making such a change is highly likely to break things. Or imagine that a superclass requires some maintenance. Again, any changes are likely to break subclasses. And in a large, or library, or framework development, one can’t even be sure what those subclasses are, and where they are. And that’s just the method impact. No maintenance at all would be possible in the face of non-private instance variables in the superclass. I.e. one effect of this coupling is that superclasses are fragile creatures. Contrast all this dire stuff with a use of component instances. If a composite instance contains a component instance, they retain their separate existences, their separate interfaces and their separate identities. And the interaction between them is explicit rather than implicit, and it uses only the normal, minimal coupling, object-oriented coupling – messages. If one wanted to change or maintain the component, one’s only dependence is on its interface.

Question 12.12
Summarize the Law of Demeter. Picture that you are adding a few paragraphs about the Law to a developers’ handbook you are writing for your team.

Don’t have your objects asking to access objects whose location or existence they shouldn’t know about.

That was the very short version. A longer version might talk about empowerment. One of the most frequent mistakes of even long-term, object-oriented developers is making their objects too dumb; one suspects that they are still hankering after dumb data structures. Instead of saying, “Give me your real part and your imaginary part so that I can calculate your inverse”, ask a complex number object to simply give you its inverse. Instead of asking a student object to give you its record object in order that you can add an event; give the event to the student and ask it to remember it. Instead of asking a table how big it is and what kind of table it is, present the table to the booking and ask the booking if a table is suitable.