Footnotes

Preface

1 The methodology is named for Sally Shlaer and Steve Mellor. This methodology was originally expounded in the early ’80s. Since then it has gone through several revisions, and there are several variations, of which MBD is one.

2 Computer languages are subdivided into generations that roughly correspond to historical innovation and increasing abstraction. The first-generation language (1GL) was machine code, bits set directly in hardware registers. The second generation (2GL) introduced symbolic names for things like instructions. Third-generation languages (3GLs) represented a major advance with notions like reusable procedures, block structure, and stack-based scope. 3GLs represented a huge advance in the size of programs that could practically be written, and they dominated software development for half a century. The fourth-generation languages (4GLs) broke with the previous generations by raising the level of abstraction to the point where the program could be specified in a manner that was essentially independent of specific computing environments.

3 That isn’t critical because the syntax is explained. In addition, books like Kendall Scott’s UML Explained (Addison-Wesley, 2001) are cheap and quick reads that provide far more information about UML than you will ever need to record MBD designs.

4 Keep It Simple, Stupid.

Introduction

1 This is a book about software, so we have to use acronyms. It is a union rule.

2 If you don’t know what this means, you need to start with a more elementary text than this book. The important factoid about this statistic is that it refers to thousands of raw lines of COBOL code, a rather wordy language.

3 Assuming each line of code is an opportunity for one or more defects, 5-sigma represents a frequency of defects that is five standard deviations from a median of one defect per line. The defect rate corresponding to that level of quality is about 230 defects per million LOC—a thousandfold improvement over the norm of the ’60s.

4 Interestingly, much of the core technology associated with the World Wide Web is really a rebirth of old technologies. I actually read an article recently in a fairly prestigious software development magazine where the author claimed the first markup language was invented in 1986. In fact, markup languages were commonly used two decades earlier. Sadly, that myopia meant that the industry learned nothing from the reasons why markup languages had been largely abandoned by the late ’70s. But that is a topic for a different book.

5 In fact, Microsoft learned its lesson well. Today’s Microsoft products have pretty much caught up on the reliability front to the point where security is probably more of a competitive issue.

6 An old but still amusing joke: What’s the difference between a terrorist and a software methodologist? You can negotiate with a terrorist.

7 The Rational Unified Process (RUP) is not really a process. It is primarily a process framework that is highly tailorable to local development environments.

8 The Capability Maturity Model (CMM) is a true process framework in that it describes only what capabilities must be in place to produce good software, not how they should be implemented. Thus compliance with the CMM is a necessary but not sufficient condition for good software development.

9 The problem was that such statements changed the flow of control of the program “on the fly” in ways that were not directly visible in the code itself. Understanding other people’s code is tough enough when sequence and branching is explicit. Such programs led to the acronym WORN—Write Once; Read Never.

Chapter 1

1 My first program was written on a plug board in 1957. A plug board is essentially an extension of the hardware whereby one grounded TTL inputs, which normally float High (logic 1), with a wire to make a Low (logic 0). One wrote every single bit directly into the hardware. My program was a hello-world class exercise, but it took me two weeks to get it to work.

2 In the days of drum memories there was a fellow writing BAL who routinely optimized for the fact that there were two heads on the drum. He wrote his programs by physically separating the logically consecutive statements in his program by a distance that mapped to nearly half the circumference of the drum in address space. The exact placement was computed based on the number of cycles that the previously executed statement would take to execute and the drum rotation speed. This allowed the statements to be executed with something approaching half the latency for the drum rotation that a sequentially ordered program would have. The mind boggles that he could write programs that way, much less debug them.

3 With the advent of the Internet in the ’80s, the term further evolved to refer to people who broke into computer systems for nefarious purposes.

4 It was more well known as Structured Programming at the time, which was a bit of a misnomer because a common theme of SD was to provide software design using notations that were quite different than the programming languages of that era.

5 The first pure OO programming language, Smalltalk, appeared in 1972, but it was developed with the goal of providing better tools for simulation, and the mapping to general computation was not intuitive. It took about a decade for OOA/D to evolve to the point where general-purpose use was feasible.

6 The empirical data from those times was pretty varied and the quality wasn’t very good, especially for the ’60s. People might argue about the specific numbers, but it is unlikely anyone familiar with the period would argue that defects/KLOC had not improved by several integer factors in that period.

7 A classical example is the zoological taxonomy that classifies all living things. Academics spent decades developing that taxonomy. Just as they were congratulating themselves on a job well done, someone brought home a duck-billed platypus from Australia. A hairy, egg-laying, web-footed marsupial with a bill simply did not fit into the taxonomy because several of its characteristics were determinants for very different limbs of the taxonomy. Modifying the tree would have been an arduous task; folklore says that zoologists at the time considered financing an expedition to Australia to exterminate the critters. Urban legends aside, to this day the placement of the critter in the tree is a matter of debate.

8 An example like this can be picked to death by bringing in other requirements that would ensure that, say, “Check eligibility” would have different requirements for different benefits. This is just an example of the structure issues, so it has been considerably simplified.

9 A short-cut for unit testing was to stub the immediate child functions so that they returned or set variables in a manner appropriate for the test case inputs. Basically, though, this is just self-delusion. All you are doing is testing the test harness.

10 E. Dijkstra, “Go To Statement Considered Harmful,” letter to the editor in Communications of the ACM, Vol. 11, No. 3 (March, 1968), pp. 147–148. It seems astonishing now that back then this letter launched a debate about whether GOTOs really were bad, one that lasted nearly a decade. A rather famous guru defended GOTOs as a columnist in Computer Language magazine, writing one of the most convoluted 15-line programs I’ve ever seen outside a coding obscurity contest. It was incorrect, and he got so soundly flamed about it by a gazillion readers that he didn’t put another code example in his articles for years.

11 The acronym KISS—Keep It Simple, Stupid—was born in the ’70s at least partially from this idea.

12 This only applies to problem space classes that were crafted specifically for the problem in hand. General-purpose computing space classes like String, Array, and Complex_number are really just standardized data structures without significant behavior. In other words, they are simply extensions of fundamental data types.

13 Though the OO paradigm is unique in this respect, that uniqueness is not without its price. OO design is not as intuitive as construction approaches that are firmly attached to hardware computational models. While anyone who can spell “C” can learn OO design techniques, there is definitely a longer learning curve.

14 This was enabled by an advance in hardware technology that allowed one to provide binary instructions on media such as paper tape and punched cards that could be loaded into memory registers automatically. The hardware to do such things were the first peripheral devices that supported the ALU to make access to it more convenient.

15 Initially this was largely driven by performance issues. The early 3GL compilers weren’t very smart. So in the 1960s experienced programmers wrote “x = a + a + a” in FORTRAN instead of “x = 3 * a” because they knew the compiler was not smart enough to realize that one multiply instruction took an order of magnitude more ALU cycles than an addition and that ALU speed was measured in KHz rather than GHz. So the early methodologists were passing on these sorts of practical tidbits to posterity. But very quickly it became apparent that performance was not the only way to shoot oneself in the foot in a 3GL, and more sophisticated design advice was needed.

16 HIPO charts were one of the earliest attempts at graphical descriptions of programs, so old that I forgot what the acronym actually means. When she reviewed this book, Rebecca Wirfs-Brock reminded me that it means Hierarchy, Input, Process, Output. Rebecca is a dear person and fine methodologist, but I am concerned that cluttering her mind with such arcane trivia might be displacing useful knowledge.

17 E. F. Codd, “A Relational Model of Data for Large Shared Data Banks,” Communications of the ACM, Vol. 13, 1970, pp. 377–387.

18 It was Nicolas Wirth who raised consciousness about the importance of data with his work on Pascal. In particular, one of his books was titled, Programs = Algorithms + Data Structures, whose egalitarian view was a quite seminal notion at the time.

19 USER = Update, Sort, Extract, Report and CRUD = Create, Retrieve, Update, Delete. All are simple operations on data.

20 This realization gave birth to data processing, which dominated the ’60s and ’70s. Later that morphed into today’s information technology.

21 Obviously that is no longer true. Many large businesses have entire departments devoted to operations research, often larger than corresponding departments in universities. My earliest practical exposure to operations research was an algorithm to allocate an advertising budget to a variety of national, regional, and local media outlets (TV, magazines, etc.) for a Fortune 500 Company in the ’70s. It was a pretty impressive linear programming application.

22 If you have led a sheltered existence and don’t know exactly what an FSM is or why it is a big deal, have patience. They are the primary topic of several later chapters. For those who have taken courses about finite state automata, it should be noted that the FSM used in software systems has added some capability over the classical theoretical machines.

Chapter 2

1 In fact, the early Booch notation was sometimes referred to as “Graphical C++” because it incorporated several unique features of C++, like protected.

2 The term was introduced earlier, but it referred primarily to project management activities.

3 In the late ’80s software engineering evolved into a more traditional process management view. But that’s another story. . . .

4 I’m dating myself. Vince Lombardi was a legendary football coach in the ’50s and ’60s. When asked how winning ranked against other sports goals his answer was, “There are no other goals.” Vince probably would not have been an ideal coach for Pop Warner teams.

5 A hardened 3GL programmer once said, “Give me a big enough computer and enough time and I will model the universe in real time.” Good luck with that.

6 As we shall see, the notion of customer can vary with subject matter. In this book, an unqualified reference refers to the customer initially defining the requirements for the overall application.

7 There is an adage among herpetologists that you can tell the museum guys from the field guys by counting their fingers. Clearly there are other circumstances where one wants a tad more detail about the nature of the venom of a particular flavor of snake.

8 This is why the Complex Number library class has become a de facto fundamental data type in many applications. If one overloads operators like “+” in an OOPL, the only time one has to think about the real and imaginary parts is when it is created. Typically that will be isolated to a low-level component in the application. For example, in electronic test equipment, a complex number is created when the Quadrature and Phase registers are read from the hardware but the 3+ MLOC of code on top of that manipulates it as a single, scalar value.

9 The main differences are whether one recognizes a “component” as being distinct from a “subsystem” and whether one can nest subsystems. These differences are not great because they are mainly about distinguishing really big units from not-quite-so-big units, and they mostly apply to systems engineering, which is partially addressed in Chapter 6.

10 Many OOA/D authors don’t talk about asynchronous processing. Many consider it too complex and confusing for OO novices to grasp, so they just provide guidelines and rules that, if practiced properly, will hopefully get to the same place that thinking about asynchronous processing would. As an aside, I feel strongly that this view is both condescending and dangerous because it is difficult to practice those rules and guidelines properly if one doesn’t know why they are really there.

11 This is another reason that many OOA/D authors avoid talking about asynchronous processing. There is less to teach and learn if one assumes a simple, synchronous world. That view even had merit through the ’70s when virtually all applications were monolithic, stand-alone processes. Why confuse everyone with issues that only a small niche of computing (R-T/E) cared about? It is still relevant today for CRUD/USER applications, though the RAD IDEs tend to be very inefficient as they serialize networks and DB access. But that attitude just doesn’t make sense in today’s complex, interoperable application environments once one is beyond CRUD/USER processing.

12 We are talking here about OOA/D, not OOP. In very rare situations, tactical resolution for performance requirements can dictate that one limit the number of collaborations, so in OOP one may combine method invocation with knowledge access by passing data. But when one does that it must be an informed decision, and one may need to provide additional infrastructure to ensure the data is still timely by the time it is actually processed.

13 Functional programming relies on passing all state data as arguments. But functional programming limits the scope of data integrity issues in a different way through the concept of closure combined with the lack of persistent data. The passed data then represents the state of the entire problem solution at the moment the procedure was called, so the issue of timeliness effectively goes away.

14 The ability to turn maintenance that quickly on the pilot project was even more impressive for a number of reasons: We were new to OT, none of us had built an application before for the operating system (MS-DOS), the hardware we were controlling was analog and we had only done digital previously, and most of us had not previously used the implementation language (C++).

15 It has far more important implications for DbC because of the convenient direct mapping between triggering conditions and responses. Peer-to-peer collaboration enables DbC techniques for rigorously defining correct flow of control in the overall solution. But that is a topic for Part III.

16 This might seem extraordinary, but it makes sense when one thinks about it. If the OOA model is rigorous enough for a transformation engine to generate correct optimized code, it must be rigorous enough to execute in an unoptimized, interpreted mode. All translation tools support such a mode and provide a test harness for applying the same test case data to either the model or the final executable.

17 Firesmith, Donald and Eykholt, Edward, Dictionary of Object Technology, SIGS Books, New York, 1995, pp. 271–285.

18 In the context of OOA/D, all 3GLs, including OOPLs, are regarded as implementation languages that implement the OOA/D specification.

Chapter 3

1 A personal pet peeve of mine is that most OOA/D authors never mention sets and Venn diagrams. Instead, they leap directly to extracting generalizations from the problem space and generalize the structure rules from there. The result is that many novices have difficulty understanding it. But this is not rocket science, and you don’t need a graduate course in set theory to understand what is actually going on. Once one understands the basic set/ subset relation in terms of membership in class sets, the interpretation of generalization in the problem space becomes much easier.

2 That’s true for MBD, but things get slightly more complicated for methodologies that allow implementation inheritance combined with overrides. To support that, the rule needs to be modified so that one uses the first concrete implementation encountered while ascending the tree. We will talk about what implementation inheritance is and why MBD does not support it in Chapter 12.

3 As we shall see later in Chapter 12, managing observable results is what the Liskov Substitution Principle (LSP) is all about.

4 The 3GL type mavens have usurped this term to apply to a very special sort of type substitution. This book uses the traditional software definition that dates from long before formal type theory.

Chapter 4

1 Through the ’60s computer science referred exclusively to designing computer hardware. There were no CS departments in universities; computer science was a specialty of the EE department. This still prevails in some schools, such as my alma mater (MIT), where a computer science degree is awarded from the EE department to this day.

2 To this day, that is a reviewer criteria for MBD OOA models. An unambiguous implementation path to a manual solution should be possible without altering the OOA model.

3 This is commonly called a platform. This word traditionally has been referred to as simply the hardware and operating system. In a translation context a much broader definition is needed, so this book will usually refer to environment to convey that.

4 This separation of concerns is so important to MBD that all MBD model reviewers carry a kit containing garlic cloves, wooden stakes, and kindling so that they can properly dispose of any heretical application developer who includes implementation details in an OOA model. Implementation pollution of an OOA model is regarded as a mortal sin when practicing MBD.

5 This book subscribes to a set of handy definitions stolen from Doug Rosenberg: A customer is whoever defines requirements; a client is whoever pays for the software; and a user is whoever actually uses the software. They may be, but are usually not, the same person.

6 Some software, like a heat-seeking missile controller, provides functionality that would be difficult for a human to do. A human might be able to do the computations on an abacus, but probably not before the missile missed and ran out of fuel—not to mention the implications of success for an on-board human doing the computations. But that just makes a manual solution infeasible in practice. The problem space and the computations still exist, at least conceptually.

7 In fact, UML can be and is used for both OOA models and Domain Models.

8 The relatively recent advent of systems engineering as a discipline of software development addresses this by including the specification of requirements as one of the key activities. This just recognizes the practical reality that most customers can’t or won’t provide requirements at the level of detail software developers need. So one of the hats the systems engineer wears is that of the old systems analyst.

9 Well, duh. It might seem this is being an apostle of the obvious, but the sad reality is that most software applications make very little use of invariants. That’s not really surprising because there is precious little reference to invariants in the software literature, aside from the relatively recent introduction of design patterns. As you shall see when we talk about them in detail, there is no rocket science here, and it is very difficult to explain why so few software gurus seem to have seen value in them.

10 In MBD uses cases are viewed as an input to design rather than an element of design.

11 If you look at the bookshelves of engineers in other disciplines, you will find at least one entire shelf devoted just to standards manuals. Those manuals provide rules on how to do things in excruciating detail. But you should probably not tell those engineers that their designs are not creative because they have too many standards.

Chapter 5

1 Sorry about getting carried away with the metaphors. Sometimes when I think of Clara Pellor I get carried away with the lunacy of presidential campaigns. For those of you who are too young to remember, Clara did commercials. In one about fast food products she played a doughty old lady who asked in a strident voice about a competitor’s product, “Where’s the beef?” In a memorable moment in a campaign debate among Presidential candidates one candidate asked the other, “Where’s the beef [in your position]?” In no small part, that irrelevant sound byte contributed to that opponent’s loss. You really had to have been there.

2 If you don’t know what design patterns are, I refer you to the GoF (Gang of Four) book: Gamma, Erich, Richard Helm, Ralph Johnson, and John Vlissides, Design Patterns, Reading, MA: Addison-Wesley, 1995. This book is required reading for anyone who wants to do serious OO development.

3 If you actually read the introductory chapters you might be tempted to view this repetition as a one-trick pony. I repeat things to make sure that important points sink in properly. Rest assured that if this is a one-trick pony, MBD has a lot of ponies—each with its own unique trick.

4 To defray visions of getting the customer to do all the work, there is no free lunch. The customer is not going to be keen on that unless you provide some very user-friendly tools. Configuration management of data may be easier but it won’t go away, and synchronizing with customer activities may introduce a new suite of problems. There will also be a learning curve, and you better have a Plan B in case the customer screws up. In other words, the work hasn’t gone away, you’ve just shifted into a more productive mode.

5 To do this we need to provide bit-level masks and use arcane bitwise operators like XOR. That’s why R-T/E people can do mental arithmetic in base 8 or 16. I actually knew a guy who could read aloud ASCII text in a hex memory dump as fast as I could read it aloud from a normal ASCII printout. R-T/E people definitely live in a different world.

6 “Artwork” refers to providing electrical connections between various points on the circuit board. Even a medium-sized board will have thousands of connections to make. Today most circuit boards have multiple layers so that the lands (thin conductive strips that make connections) can “cross over” other lands without shorting. In addition, land length is a problem because today’s circuits run at such high clock rates that even a few inches can result in race conditions (synchronization problems for parallel signals). Long lands can also pick up noise at very high frequencies. Trying to find short, unobstructed paths is a very large np-Complete problem for circuit design, and often the hardware guy will have to move things around just to be able to provide feasible connections.

7 This wasn’t mentioned in the bit sheet description, but hardware control registers are invariably integer values and almost always unsigned. One only sees floating- point register formats on computer CPUs and then usually on a dedicated FPU. So if the interface provides the values as a real number, it will also have to be converted to integer.

8 Note that this allowed the hardware guys to validate that we had captured the bit sheet data correctly in a very straightforward and reliable fashion.

9 Note the recurring theme in these examples of addressing requirements changes by modifying external configuration data rather than the application. This just reflects the fact that recognizing invariants goes hand-in-hand with parametric polymorphism. You will find that as you recognize more and more problem space invariants, you will be moving more and more of the maintenance out of the application. And that is a Very Good Thing.

Chapter 6

1 You will note the emphasis on dealing with changes in the above commentary. Good partitioning is really a developer issue because the main justification is to ensure long-term maintainability. That is why the supplementary documentation that supports the component diagram and describes invariants in the problem space is more important than the diagram itself. When developers spend time on partitioning, they are doing themselves (and their progeny who will replace them on the project) a favor.

2 I was once hoisted on my own petard for this very reason by a Group VP. He announced a group development effort with another division on the other side of the continent. Several years previously we did a common project with that division, and it was a disaster because of logistics and different development cultures. So after the presentation I greeted him with, “Hi, Joe. Long time, no see. You know you haven’t got a prayer in hell of carrying this off, right?” A year later we delivered the megabuck product with three days of effort required for integrating our stuff, and we didn’t even have anyone on site for it! The reason was that Joe insisted that the project be run exactly as I had been preaching for years. The subsystems were defined and each division developed individual subsystems that were glued together by interfaces at system integration time. Interestingly, Joe was a Hardware Guy rather than a Software Guy. But he was also very sharp and could see the value of good application partitioning and how it could be mapped to mega project management. He was also a nice guy, so he didn’t chortle too much.

3 In fact, this view underlies a great deal of the dependency management employed during OOP to make OOPL code more maintainable. The notion of client/service also has familiar manifestations in things like client/server architecture and Service-Oriented Architecture (SOA).

4 An application can have several different problem spaces, each with their own domain experts. Some, like networking and database access, may be unknown to the application’s end users. Thus, in a hybrid hardware/software system the hardware engineers become customers of the application because they define requirements for interacting with the hardware.

5 An acronym for Kawakita, Jiro. The diagrams are a technique for building a high-level, summary consensus from a collection of low-level, individual statements that are related in varying degrees. A crucial initial step is to ensure that everyone understands each statement in exactly the same way. Invariably, at least half of the original statements will have to be modified in some manner to reach consensus.

6 For those of you who have led a sheltered development existence, SOA = Service Oriented Architecture. SOA is a popular modern paradigm for defining software architecture. The parallels to MBD application partitioning are striking to the point of suspecting plagiarism in the origins of SOA. However, SOA infrastructures tend to address a number of issues that are unique to IT (e.g., the ubiquitous dominance of the client/server DBMS model).

7 Note the emphasis on “problem space.” There are lots of computing space data holder entities like String, Array, and ComplexNumber that we find convenient, and we even pass them across subsystem boundaries. But, as we shall see, these are usually abstracted as abstract data types (ADTs) for knowledge responsibilities. Here we are interested in problem space entities that have unique behavior responsibilities.

8 When objects that implement different subsystems share knowledge responsibilities, there is a need for explicit synchronization between those subsystems to ensure data integrity. Typically that will be implemented by the “owner” subsystem notifying other subsystems when its data changes. It is trivial to implement in an attribute setter, but somebody needs to “register” the subsystems that care.

9 In my experience most customers are not idiots. They realize that when they can’t agree on what rules and policies go in what conceptual bins, they have a problem that will affect their own processes beyond the software in hand. So however grumpy they may be in the short term, they will appreciate your raising the issue in the long term.

10 The PLA is something marketeers love. It enables them to provide a coherent message around disparate products. If you have never seen a PLA diagram, it is basically a tree viewed horizontally that has a main product line with branches for variants on the main product. The marketeers with MBAs from better schools will also use the PLA to create products to address different markets.

11 The devil made me do it. Steve and I go back a long time. When he reviewed a chapter from the book proposal for Addison-Wesley, his comment was, “It is a book that needs to be written. But I would hate to read it.” Steve is a master of left-handed compliments as well as modeling.

12 If you are not sure what we are talking about here, try this analogy. Write exactly the same program in C and in FORTRAN. The semantics of the problem solution that executes on the computer is exactly the same. However, the 3GL syntax used to represent that solution is quite different. If you want to solve that particular problem but you only have a C compiler and the program is written in FORTRAN, you’ve got a problem even though the FORTRAN program is quite capable of solving the problem. As another example, we just need to look at OTS class libraries for things like String and Array. The semantics is essentially identical because of the underlying mathematics, but different library vendors provide different interfaces to the classes, so we usually cannot swap library vendors without doing surgery on the applications.

13 Random factoid: Some modern archaeologists now believe the Oracle’s cave was a source of hallucinatory natural gases.

14 Not to mention being much more efficient. The canned interoperability interfaces offer developers tremendous convenience by supporting things like remote object access and RPCs. However, that convenience comes at a horrendous price in performance. It takes a lot of sophisticated code to support that kind of stuff across distributed boundaries.

15 In the book draft, the example was a Pet Euthanasia Center because I was seeking an example so far off the charts that no one could argue that OO techniques only apply to niches. However, every reviewer commented that it was in bad taste despite the fact that such centers already exist (in Southern California, of course). For the record, I am currently a cat owner and have owned a variety of turtles, hamsters, cats, and snakes, some of which had to be put down to eliminate suffering. So I have to wonder if those reviewers actually had pets.

16 There may not be an owner. Walk-ins without owners are processed as charity cases.

17 I strongly believe that to understand OOA/D properly one needs to understand how to think about designs. Simply presenting a fait accompli solution doesn’t explain how I got there. Throughout this book I try to focus on thought processes rather than the designs themselves. That includes making common mistakes because the design process is inherently iterative and self-correcting. But that only becomes apparent if one actually walks the path rather than taking a taxi.

18 In a more complex system we might separate hardware control from networking. Here, communications with other applications seem pretty trivial, so we lump it with hardware communications since ultimately networks are just more hardware.

19 We are cheating a bit because we haven’t shown the detailed requirements from which the “high-level” overview was abstracted. In reality, we would have become familiar enough with them to make such judgments that are argued as intuitive or “likely” here.

20 We probably don’t want janitors defining pet diets and how the facility works, so we probably need to provide some sort of user validation/privileges capability. That’s something else Pet Tracker seems suited to manage. This is good because, in case you hadn’t noticed, Pet Tracker hasn’t had a lot to do. On the other hand, subsystems almost always turn out to be more complicated than we originally guessed, so we should expect this sort of thing to fill out Pet Tracker.

21 Something of an oversimplification. So far we have not discussed things like error recovery (e.g., the staff forgets to scan the barcode to announce completion of a stage). It is a good bet that most of the code will be involved in peripheral stuff like that.

22 Note that our original concept of guiding a pet through the stages has disappeared. Once a pet has been admitted, that is an ongoing activity controlled by Scheduler now. Pet Tracker has just become an entry point for defining the infrastructure to support that ongoing process.

23 Minimum cut set is a graph theory approach where we use the call graph to identify clumps of nodes with related functionality that require a minimum number of graph edges (usually procedure calls) to be cut to isolate the module. The problem with this is that it does not reflect logical cohesion or frequency of access.

Chapter 7

1 In my experience all analogies applied to software development eventually fall apart. Picking such analogies to pieces wastes an enormous amount of bandwidth on software Internet forums. So if you don’t like the analogy, just kiss it off to poetic license and ignore it rather than e-mailing me with a critique.

2 Leon Starr. Executable UML: How to Build Class Models. Upper Saddle River, NJ: Prentice Hall, 2002. This is the most comprehensive book on class modeling available. IMO, it should be on every OO developer’s bookshelf.

3 Steve Mellor and Marc Balcer. Executable UML. Upper Saddle River, NJ: Addison-Wesley, 2002. Steve is the best OO modeler I have ever known. When we first started out, we had a problem with a point about the Shlaer-Mellor methodology; we could not see a way around a particular form of implementation pollution. Several very bright people puzzled over it for weeks to no avail. So I cornered Steve at a conference to present the problem, which by that time I felt was irrefutable proof that some implementation pollution was unavoidable. Steve sketched out a solution—literally on the back of an envelope—with no implementation pollution. It took him all of thirty seconds to solve a problem that I and several other people in our group couldn’t solve after weeks of effort. People like that are not good for one’s ego.

4 Merriam Webster’s Desk Dictionary. Springfield, MA: Merriam-Webster, Inc., 1995.

5 This notion is about the ability to interchange two entirely different representations of a solution based on a 1:1 correspondence of elements in each solution. The most famous example is the primal/dual approach to solving linear programming problems. We flip back and forth between representations because certain types of operations are more convenient in one representation than in the other. Later in the book we will demonstrate that often we have a choice in abstracting the problem domain in terms of knowledge or in terms of behavior.

6 A special case exists when the dynamic context happens to be the values of only the owning object’s knowledge. But even then the dependence is indirect because the results depend on the knowledge, and the knowledge depends on the object identity.

7 This comes full circle to footnote 5. We can view polymorphic substitution as a convenience of representing the solution in terms of behavior. Similarly, simple value assignment is a convenience of representing the solution in terms of knowledge.

Chapter 8

1 Webster’s New Twentieth Century Dictionary of the English Language Unabridged. New York: William Collins Publishers, 1972.

2 Actually, the computing space provides a very efficient mechanism for distinguishing individuals: memory addresses. Each instance has a unique memory address. One essentially keeps track of individuals through careful initialization of references when instances are created. This is quite generic so one does not need any intrinsic property of the entity to use for identification. Thus two distinct software entities can be identical in the values of every property yet they are still individually identifiable.

3 Rebecca Wirfs-Brock and Alan McKean. Object Design: Roles, Responsibilities, and Collaborations. Upper Saddle River, NJ: Addison-Wesley, 2003.

4 This represents a typical test instrument driver interface for the VXI standard. Such a low-level interface is necessary for complex rack-and-stack test systems. If several instruments will be used concurrently, they must all be initialized prior to initiating any of their tests.

5 In fact, almost all analysis and design patterns in the literature involve some kind of delegation. In Chapter 5, the specification objects we identified in each example illustrated delegation, where the responsibilities delegated from the original object were knowledge responsibilities.

6 More precisely, the MDA profile for using UML with MBD.

7 When we get to the dynamic description we will see that we do not define most operations directly; instead, we identify the state machine events that trigger state actions (operations). This is a convenience so that we do not clutter our Class diagrams with separate Interface model elements. The associated UML Statechart resolves the mapping of events to states and actions.

8 Those of you with passing experience with OO development will probably recognize the cards as CRC (Class Responsibility Collaborator) cards. (Providing the responsibilities will be covered in the next chapter.) Providing CRCs was one of the earliest OOA/D techniques from the late ’70s. They were adopted from the Table/Attribute cards commonly used to define RDB schemas in the mid-’70s. They went out of vogue when modern OOA/D notations were developed in the early ’80s. They were revived for the OOP-based agile processes in the late ’80s.

9 There is an added benefit to domain expert participation. Reviewing the results is not the same as participating in their development. Often the debates leading to a particular diagram can be very useful to a domain expert in determining whether the software developers are thinking about the problem space correctly. That is, the developer’s own discussions are much more indicative of their understanding of the problem space than the bubbles & arrows in the final model.

10 Some auditors are so paranoid that they want every internal message (e.g., between the Keyboard and Dispatcher) logged to the bank immediately as it happens. They may provide a special binary Keyboard driver that logs every keystroke directly to the bank so they can detect back door code in the ATM Controller and unauthorized access.

11 Staff here refers to human beings who staff the Pet Care Center. Communication with them is through a UI or printer.

12 We are not going to describe Sequence and Collaboration diagrams because they are actually redundant in MBD. The translation tools can all automatically generate them once we have defined the other diagrams. So they really aren’t part of the MBD MDA profile, and there isn’t the space to describe them in detail. But any book on UML will give you all you need to know for this sort of rough analysis if you have never seen one before. For this discussion all you need to know is that vertical lines represent classes or objects, and directed horizontal lines represent messages between them. The diagram looks a lot like a competition swimming pool from above, so the space between vertical lines are often called “swim lanes.”

13 This is not how the dynamics would actually be done, but we don’t want to get into those issues until the next section. For now, all we need is a plausible flow of control because we just need to prove that we have the right objects to solve the problem.

14 Also getting ahead of the story here because this requires OO generalization, which we haven’t talked about yet except generally. For now, just assume the Schedule object understands the steps involved in a feeding (e.g., cooking, preparation, etc.).

Chapter 9

1 Again, data carries emotional baggage. In the context of object attributes, the notions of data and even value are quite abstract. Both represent abstract views of knowledge, and the degree of abstraction is dictated by the containing subsystem.

2 For those of you that think we can ignore this because in translation we don’t need to maintain the code, note that whether an attribute should be public or private is completely deterministic when mapped to OOP. We use UML Interaction Diagrams and abstract action language to describe the dynamics of the solution and, therefore, define access to knowledge. If the solution dynamics require that someone outside the object access its knowledge, then that responsibility is a public responsibility by definition and the attribute must be public. If the attribute is not accessed externally then it may be designated as private during OOP.

3 The reason such denormalization is an idiom is that the most reasonable key for the individual elements would be the concatenation of those elements so there would be no non-key elements in the table tuples. That leads to inefficiency in size (referential attributes are the tuple) and needless overhead in forming joins between tables.

4 This is so common for text values that SQL has actually institutionalized it by providing syntax to enable us to extract substrings from RDB string fields when forming a query dataset.

5 This might seem like an insurmountable problem, but it really isn’t. That’s because MBD constructs the OOA solution specification so that it is relatively easy to do. For example, if the application is single-threaded without asynchronous events, then the engine doesn’t have to do anything at all. Because of peer-to-peer messaging, integrity comes down to putting the messages in the right order, which the developer already did. By making responsibilities self-contained and accessing attributes on an as-needed basis, it becomes relatively easy to provide blocking mechanisms based upon method scope when the environment is more complex. Finally, we are very careful to separate knowledge and behavior access. Asynchronous and multithreaded processing is more complicated but still deterministic and manageable given the limited scope of access.

6 For what it is worth, I don’t care for the term ADT precisely because it carries too much baggage from 3GL type systems. I would prefer abstract data category or abstract data class to be consistent with the rest of OOA/D. However, the term is very much entrenched in the literature. Just be aware that in OOA/D the term doesn’t mean quite the same thing as it does in the OOPLs.

7 It is quite plausible that one might want to add X and Y when both were building ADTs. Imagine urban planning software where complex building complexes are constructed by adding together multiple individual buildings.

8 One wag asserted that in the OO paradigm, flow of control could be handled by a reasonably intelligent orangutan if one had a large enough bag of bananas.

9 There is an exception that will be discussed under dynamics. When we allocate business rules and policies to state machine actions, a subset of those rules and policies may be relevant to two different states in the state machine. A synchronous service can be used to eliminate redundancy, regardless of the processing. In that case the synchronous service is equivalent to a private method in the OOPLs; it exists to simplify the object implementation and is not visible outside the object.

10 Some translation OOA profiles do not even identify operations in the Class diagram; the third box is always empty. In our opinion, that is aesthetically inconsistent with what the Class diagram is about. While the results of a behavior may change dynamically during the execution based upon context, the obligation to provide a behavior is a static property of the object that is invariant over its life, so we believe it should be identified.

11 A major advantage of the MBD approach to separation of concerns is that testing is usually quite easy to do and to automate at the class operation unit test, class unit test, and subsystem functional test levels. Providing test harnesses that are driven by external data is close to trivial, and they are usually pretty reusable across applications. (In fact, most translation IDEs provide built-in test harnesses.)

12 I once read a paper (alas, that I no longer have a reference to cite) in which the author made an interesting point about the contrast between OO development and Structured Development. The author asserted that OO development is requirements oriented while Structured Development is solution oriented. While I think that is a bit facile, I also think there is more than a little truth to it, especially when doing OOA modeling.

13 As a practical matter, life is much easier for the transformation engine when managing data integrity if writes are limited to special accessors that don’t do anything else. It is also important to providing concurrency because writes are usually critical “touch points” between threads. So we want knowledge updates to be highly isolated and readily recognized rather than nested within the scope of other operations.

14 This is not unprecedented in customer domains. For example, we say that a loom knows the pattern for a fabric. Software developers just do this sort of thing routinely.

15 Collaboration diagrams are not required in MBD because they are redundant; the translation tool can create one once the other diagrams are completed. So we won’t talk about syntax details. Basically they are just boxes for each class that are connected by arrows to reflect direct collaborations.

16 Different authors advocate more or less detail. At a minimum we want a list of objects that the object in hand collaborates with; better is some mnemonic about the nature of the collaboration (e.g., “gets sample data from” or “triggers measurement in”).

17 As it happens, I completely forgot about the entire printer in my original pass at Chapter 8! However, it is hard to miss when “walking” a Deposit use case through a Collaboration diagram.

18 With substantial justification, I might add. I happen to know the following anecdote is true because I had first-hand knowledge of it. Back in the late ’60s some customers of a bank noticed a balance creep—their accounts were accumulating more money than they deposited. On the second of two successive statements the starting balance was larger than the ending balance on their previous statement. This magically added money to their account. The developer doing this was tricking out the auditing facilities by “depositing” nonexistent money to balance out cash withdrawals. Doing it via this technique didn’t raise any flags in the existing auditing software. He was depending on the customers either not noticing or, if they did notice, not complaining. He got caught because he got greedy and started hitting up the “deposits” for significant money (i.e., $100+ at a clip). Eventually a customer, who wanted to spend this “found” money but was worried the bank might have made a mistake and would want the money back, asked if it was OK to spend it. The bank said yes because they didn’t want to publicly admit that they had been ripped off. But the magical deposits stopped, and the developer gave back most of the money and became a “security consultant” as part of a deal to avoid doing time.

19 Being slow isn’t a problem directly. But the software can’t wait forever because of the potential for database deadlocks, so there has to be some sort of time-out check. If the software decides to reset and do something else after a certain time, there could be big trouble if the response finally arrives after that point.

20 The acronym refers to Gang of Four, the four authors in Gamma, Helm, Johnson, and Vlissides. Design Patterns, Reading, MA: Addison-Wesley, 1994.

Chapter 10

1 The most underutilized—and, ironically, also one of the most powerful tools in the OO arsenal—is parametric polymorphism, as indicated in Chapter 5.

2 Leon Starr, Executable UML: How to Build Class Models. Upper Saddle River, NJ: Prentice-Hall, 2002.

3 As we shall see shortly, an association can have multiple participants (i.e., a Child has two Parents). If worse comes to worst, we can always provide multiple binary associations.

4 Why, I have no idea. In the decades I’ve been modeling I have never even been tempted to use a ternary association. There are probably a few rare problem space concepts where such an association might be plausible, but those can be expressed with multiple binary associations. The Unified Modeling Language Reference Manual, (J. Rumbaugh, I. Jacobson, and G. Booch. Addison-Wesley, 1999) cites an example involving {Team, Year, Player} for the purpose of tracking annual statistics for players on various teams. The example is, at best, contrived, because when a Player plays for multiple Teams in a Year, we would normally only be interested in the Player’s annual statistics in the Year; at worst, the example violates 3rd Normal Form. (I know because I have written sports handicapping software.)

5 This is in stark contrast to OOPL type systems where we must always know the full type of every object on the path. The ability to fully decouple associations from classes in OOA/D is one of the main reasons that physical coupling is not an issue in OOA/D.

6 In the UML meta model, an Association is composed of multiple elements, including two Association Ends. So, technically, it is the Association End with which we associate multiplicity, conditionality, and role. However, the Association End is only identifiable in the Class diagram by the relative positioning of the qualifiers in the diagram. Thus this distinction is an arcane nuance that is important only if we are writing a transformation engine and have to read the model elements from a drawing tool that is UML-compliant. So in the rest of this book we will treat an Association as if it were a monolithic artifact with a set of symmetric properties.

7 For what it is worth, I really, really dislike the way UML handles this. Conditionality and multiplicity are quite different things, and combining them is misleading. Worse, it gets us painted into corners where nothing (the absence of a conditionality prefix) actually means something specific!

8 Do not construe this argument as an advocacy for the notion that OO development is a cognitive model that somehow parallels human thought. The only point here is that recognition involves an entirely different mechanism than interaction, and the mechanisms can be instantiated at different times and in different ways. To interact we need to recognize, but don’t need to understand, the mechanism of recognition.

9 Those of you with just enough knowledge of UML modeling to be dangerous will no doubt think that some of the 1:* associations should be *:* associations (e.g., a Course has many Students and a Student takes many Courses). We’ll address that later in the chapter. For the moment, just assume the application lives to do nothing more than place Course grades on Transcripts. In this case, the fact that a Student can take many Courses is not relevant to getting a particular Course’s grades onto each of its Students’ Transcripts. Remember that we only abstract what we need to solve the problem in hand.

10 We will have more to say about this later in the chapter because it underscores a major difference between the OO and Procedural/Relational paradigms. For now just note that even though we still have searches, they will be much more efficient than for a direct connection. In effect we replace a single large search with multiple small searches. Even for O(ln N) searches, reducing N can significantly improve performance.

11 For readers not familiar with U.S. practices, most states license vehicles for one to ten years. At the end of that time we must renew the license and physically get a new set of plates to put on the car.

12 OK, nit picker, a lot of states define a special misdemeanor for driving without plates that is different than driving an unregistered vehicle. Give me a break; it’s just an example.

13 Better yet, the inventory management software will understand all of the policies related to whether a Car is available for rental and will capture that in a database attribute of Car, such as an hasPlates or isAvailable boolean. This removes the need for the fleet management software to understand all those rules and policies by distilling them down to an available versus not available view. Just thought we’d mention this as a little plug for proper abstraction and separation of concerns in subject matters.

14 This simplification is something you will probably have to demonstrate to yourself eventually by directly encoding both models in an OOPL. When we speak of simplification we are not talking about code lines—because of the class declaration boilerplate, there will probably be a lot more keystrokes in the second model’s implementation. The thing to measure is executable complexity. So when you are done doing it both ways, count the executable statements and the number of conditional statements. If the semantics of the hierarchy is at all complicated, you will be surprised at the difference. (You can also invoke code metrics like Halstead’s or McCabe’s, and they will demonstrate an even more dramatic reduction in complexity of operations.)

15 Changing a 1:1 association to a 1:* association is annoying, but it is not a major structural change because the implementation will be well-contained around instantiation. So do not expend much angst worrying about specific changes; just try to envision the general class of changes that might happen.

16 That scope and the notion of one-at-a-time processing is a direct mapping to the hardware computational models through the 3GL syntax. With very few exceptions we can describe any one-at-a-time iteration in terms of a single set operation. In fact, one AAL, SMALL, did not even support the notion of one-at-a-time iteration initially; all its operations were set operations. But Turing and von Neumann did not go that route.

17 Even if we need the Department → Student association for majors for other reasons, we do not have to use it to solve this problem. In fact, to instantiate the association collection with Students, we will probably already have a Major attribute in Student that we check when instantiating the association.

18 It would be less easy if we needed to compute the averages for individual Courses because the navigation Student → Course is in the wrong direction to summarize at the Course level.

19 This is more common than we might think. As a physics major I was required to take a special flavor of physical chemistry that was taught by the chemistry department. However, to my knowledge no chemistry major ever took that course. That was because it was an elective for them, and they knew it was taught at 8 AM in an overheated lecture hall by a professor with the most monotone presentation I have ever encountered. So the only people taking the course were physics majors for whom it was required.

20 One of my fonder undergraduate memories if of taking a graduate course in theoretical geology given by a visiting professor from Britain. Basically the course was about applying thermodynamics to geologic processes, such as mountain building (e.g., mountain building was caused by entropy changes deep in the Earth). It was way over my head, since what little I had ever learned about thermo had been long since forgotten. There were about twenty people attending the course. He used the English system, so the grade was solely based on a 3-hour final exam. I showed up for the exam and only two others were there; everyone else knew something we didn’t and had taken it as a listener. After half an hour I had irrefutably established that I didn’t even know what the questions were asking, much less the answers. About that time one of the others crumpled his answer booklet into a ball, tossed it in the waste basket, and walked out. Since the course was graded on a curve, I scribbled down a few thermo formulas and handed in my paper for a C. To quote Kenny Rogers, “Ya gotta know when to hold ’em and know when to fold ’em.”

21 This is a term borrowed from standard techniques for managing meetings. The idea is that whenever an issue arises that was not on the agenda and shows signs of generating a lengthy tangential discussion, it is set aside into a “parking lot” (usually an area of a white board where the meeting chairperson jots such issues down). At the end of the meeting the parking lot items are evaluated into four bins: further discussion if time allows in the current meeting; topics for the next meeting’s agenda; action items assigned to meeting members for outside work; and those to be ignored. The notion of a “parking lot” is a very effective tool for keeping meetings focused. In this case, it keeps the team focused on finding the obvious associations first and highlights those that may require further requirements or problem space analysis.

22 Recall that in the last chapter it was suggested that the team should employ a rough UML Collaboration Diagram to assist in organizing the team’s thoughts. That same approach may be helpful here, but a lot of caution is required because it becomes very easy to create a peer-to-peer association for every collaboration. The goal here is to identify the minimum set of intrinsic problem space connections. So we expect collaborations to follow association paths rather than direct associations that peer-to-peer collaborations suggest.

Chapter 11

1 For those who slept through freshman chemistry, standard density for a gas is defined at a particular pressure and temperature for one mole of the gas. That density has to be adjusted for the number of actual moles of gas in the Chamber using Boyle’s Law: PV = nRT, where P = pressure, V = volume, T = temperature, n = number of moles, R is a constant. (Avagadro’s Constant as I recall. If that’s not right, my excuse is that my last chemistry course was fifty years ago.)

2 Don’t forget to do that break-up in the problem space; the delegated objects must also be identifiable problem space entities.

3 As we shall see in Part III, The Dynamic Model, AALs have explicit syntax for instantiating associations that does not use referential attributes, so they aren’t used in code generation.

4 Alas, there is an entire cottage industry devoted to providing infrastructures to make query-based processing easier in OO development. That’s fine for CRUD/USER processing, but OO development is overkill in that arena in the first place. Once we are beyond CRUD/USER processing, though, the query-based model leads to reduced maintainability and abysmal performance.

5 Technically, both OO development and DBMSes make use of the same relational model. However, the common usage of the term relational is that used here: the query/join/table implementation paradigm associated with RDBs.

6 The DBA can provide optimization in the form of a special index for commonly used navigations. But then we are essentially using DBMS resources to address particular navigation problems, which defeats the goal of providing problem-independent storage and access of data. In addition, the resources needed can be nontrivial both in increased DBMS size and in overhead for adding/removing tuples since every index needs to be updated as well.

Chapter 12

1 True, that isn’t exactly the way a zoologist looks at things; we’ll address that issue a bit later. Here we are just interested in naïve plausibility at the megathinker level because the specific example is peripheral to conveying what the characteristics of a taxonomy are.

2 Biologists and paleontologists will be jumping up and down about the example because it doesn’t make sense for a purist. For one thing, it is incomplete (e.g., no Avians). More important, the criterion for distinguishing the branches is ka-ka. For example, whales are mammals and sea snakes are reptiles, but they both live in the sea. Alas, we need an example that will be plausible to everyone over the age of eight and yet remain a simple example, so consider this a first step along an evolutionary path in model development.

3 Give yourself a cookie if you noted that Reptile and Fish need additional subclasses to form complete member unions with Amphibian per the second rule of OO subclassing since there are reptiles and fish that aren’t amphibians. Good luck on finding problem space classes that aren’t thoroughly artificial, like NOT Amphibian. There are other problems that we will get to when we talk about multiple inheritance and composition.

4 Whoa! How can each superclass abstract an identifiable problem space entity if the object instantiates the whole tree? Good point, Grasshopper; you get a cookie for paying attention. Awhile back we mentioned that an OO generalization is also known as an is-a relation. An object is a member of every superclass in a direct line of ascent because the classes just define sets, not objects. Those superclasses just represent more general or abstract views of the same entity. Thus the notion of Vehicle represents a more abstract view of a given entity than a Passenger Car view of the same entity. The constraint here is that those more abstract views must be known in the problem space.

5 There are situations where this is valid, but they are uncommon enough that reviewers are going to want some darn good justification for that commonality of values.

6 As a result, we would not expect to see this particular example in an OOA model; it is used here simply because it is so familiar. It is fairly common, though, for behaviors to be selected based on problem space rules and policies.

7 If you are familiar with design patterns, this will be immediately recognized as a Strategy Pattern that enables substitution of an algorithmic strategy based on dynamic (runtime) context. If you aren’t familiar with design patterns, just note that this sort of problem is so common that it has been recognized as a reusable processing “pattern.”

8 Typically we substitute implementations without changing results to address nonfunctional requirements that are orthogonal to the functional requirements defining the behavior semantics. So at the OOA level, that sort of substitution is usually irrelevant, and we almost always want polymorphic substitution to change the results.

9 Leon Starr, Executable UML: How to Build Class Models. Upper Saddle River, NJ: Prentice Hall, 2002.

10 If you are a language maven you will no doubt point out that composition has been a stock feature of OOPLs dating back to Smalltalk. There is a big difference between being a supported language feature and being a basic construction paradigm. In this case the use of the feature needs to be seriously tempered with good methodological practice. This tempering basically says that cohesion takes precedence.

11 This example is paraphrased from Executable UML by Stephan Mellor and Marc Balcer. Boston: Addison-Wesley, 2002.

12 Barbara Liskov, Data Abstraction and Hierarchy. SIGPLAN Notices: 23, 5 (May, 1988).

13 I am actually indebted to a fellow I know only by the online appellation of “Daniel T.” for coming up with the Predator/Prey example that I have paraphrased. He originally made the point years ago on the comp.object newsgroup that many of the LSP violations people were debating simply disappeared if we weren’t constrained by defining what was done at the superclass level through the method name. That is, if we define the response as “run()” at the superclass level for Gazelles, Rabbits, and Antelopes, then we are going to have a problem adding Pheasant or Brontosaurus as a new subclass. But if we describe the message as “attacked()” at the superclass level, it is unlikely there will be a problem adding those subclasses.

14 We can also introduce LSP issues by moving the location of a concrete implementation from one superclass to another or by changing where a concrete implementation is overridden within the tree. Fortunately, MBD largely avoids these problems by not directly supporting implementation inheritance.

15 If you are wondering why I didn’t spread enlightenment into the debate, I have given up. LSP debates on OO forums are as common as spring showers, and they are conducted primarily by type mavens who didn’t bother to learn OOA/D.

16 Like maybe the superclass should be FourSidedPolygon and Rectangle should be a sibling of Square. Duh!

17 Yes, we should not pass a lot of data around in message data packets. This is just an example that needs to be familiar, so assume the new requirements demand that a snapshot of data be provided.

Chapter 13

1 In an AAL syntax we are always accessing the identified responsibility, not its implementation, so there is no need for the getter/setter subterfuge in the OOA/D. That is, the transformation engine always interprets the syntax as a getter/setter because the attribute is defined as an ADT.

2 If you are curious about how this would be handled in the implementation, that is beyond the scope of this book; it is a job for translation. However, to give you an idea of what goes on, there are actually several alternatives. The most likely is that DigitalUnitTester asks Database for the test identified as “52C.” It gets back the instance data for its DigitalTest class. In that case, the testData attribute would be a handle to a dataset extracted from the database. When it was time to execute the test, DigitalUnitTest would pass that handle in a message to the DigitalTest subsystem. The DigitalTest subsystem’s interface would pass that handle to a factory class, which would decode the dataset and instantiate the relevant Stimulus and Pattern objects and their relationships. When that was completed, an event would be generated to whatever object kicks off the execution. In effect, the dataset is reduced to a message data packet by the transformation engine behind the scenes.

3 As mentioned previously, there are other reasons why this is poor modeling. One is that gradeValue is not a simple domain; it actually combines the {pass, fail} and {A, B, C, D, F} data domains for the {0,1} values so the attribute violates 1st Normal Form when we consider the semantics of the allowed values.

4 If you answered (B), you get half credit. If you answered “(F) Anything but (C)” you get full credit for spunk, for reasons we’ll get to in a moment.

5 If it was a one-shot, you probably wouldn’t be doing OO development in the first place because volatile requirements wouldn’t be an issue.

6 Once we get there in the final draft of the model, we might consider renaming Bill Of Sale to avoid confusion with the real thing in the problem space (e.g., to Print Specification or Bill Of Sale Specification). Thus Bill Of Sale evolves from the original Object Blitz to a different abstraction in the final model as we refine our thinking about what is necessary to solve the problem. Design is an iterative process.

7 In fact, in MBD we recommend creating a very rough Collaboration diagram as part of the discovery of class abstractions. This is a throwaway and is not intended to be either rigorous or detailed. It is simply a mnemonic tool for recording the rough expectations for the overall solution.

8 In the simple-minded ATM we have been discussing, the balance is simply printed out for the user on a deposit slip or as a direct query by the user.

9 Wait a minute! Doesn’t the ATM UI have objects with persistent attributes just like the GUI? Not in today’s ATMs where the UI is a character screen. The display is literally a text string with embedded positioning characters that is sent to the display device driver. It is sent once and the display remains the same until a new string is sent. When the user supplies values, they come from the Keyboard device driver; they coincidently also get displayed.

10 If you recall the class model of an ATM controller I presented a couple of chapters ago, there was a Transaction entity. The subclasses of that entity did not include a Balance Request because nothing like the requested amount needs to be saved while processing an exchange of multiple messages with the banking subsystem. Suppose, though, that the collaboration between Dispatcher and Character Display became complicated enough for a balance display that it required executing multiple methods. Then we might need to temporarily save the value of balance we received from the banking subsystem until the Character Display was ready to receive it. Then we might need to abstract a class like Balance Request that has such an attribute.

11 This is very common in service subsystems. They provide very detailed services for client subsystems, but those details are typically confined to a narrowly defined problem space. At the same time, those service subsystems employ problem space invariants to abstract away the semantics of the client. In other words, they abstract away any business semantics not related to their own subsystem. This ability tends to make service subsystems reusable across applications. Just thought we would point this out to reinforce the value of good application partitioning.

12 It was mentioned in Part I that a good way to elicit requirements is to ask “why” repeatedly; this is true for things like abstracting attributes as well. Pushing back by asking why we need an abstraction until it is fully justified is an excellent technique for getting to the right level of abstraction, as in this case.

Chapter 14

1 Or their more general brethren, Petri Nets. We use finite state machines rather than Petri Nets because their special constraints map better into the constraints of good OOA/D practice.

2 This is another reason why we want knowledge access to be synchronous. It essentially makes attribute access indistinguishable from parameter access from the method’s perspective. However, direct attribute access makes data integrity issues much easier to manage than when data is passed via messages.

3 Fortunately for us translationists, that bootstrapping all lives in the transformation engine and supporting infrastructure.

4 So why lead with the less general notion of delays? We want to make sure that we construct our methods and collaborations in a way that decouples the message sender from the receiver. The best way to do that is by assuming an arbitrary delay between the generation of the message and the response to it. This assumption prevents us from even being tempted to make the sender dependent in any way on the response. Therefore, the best way to construct OO software at the OOA/D level is by always assuming delays.

5 The word is used advisedly. There is a tendency in the literature to equate synchronous with nonconcurrent. However, that overloading of synchronous can be confusing because they really are different things. It is convenient because they tend to map 1:1; concurrent processing is almost always implemented with asynchronous communication while nonconcurrent processing is almost always implemented with synchronous communications. Just beware of the almost.

6 That decision mechanism may be as simple as “walking” a predefined list of customers.

7 Alas, so far all that new math has not yet been implemented in the engineering of 3GL optimizing compilers except in very rudimentary ways. Instead, the developer is given constructs like threads to bootstrap the most complicated part—deciding what sequences can execute concurrently without stepping on each other.

8 Note that if the development is manual elaboration, following these practices is even more useful. They essentially enable a more cookbook approach to OOD/P that will pay dividends in productivity (less rework) and reliability (fewer defects).

9 Being self-contained means that it operates on a great gob of data that is organized in a particular way. Other than supplying the data and extracting the results, there are no other interactions with the algorithm. So, conceivably, we could encapsulate the entire algorithm in a single procedure.

10 Actually, since String is a class that would normally only appear during OOP, we would not abstract those operations in an OOA model. (Remember, a knowledge ADT is abstracted as a scalar value.) We simply used this example because it should be familiar to the reader. However, if we encounter a subject matter where the individual characters were of interest, then we might have a String class in the OOA model with those responsibilities. That class would still be a data holder and the operations would be problem independent.

11 A more practical reason is that since events connect the dots of flow of control, we want to be able to see that flow of control at a consistent level of abstraction. If all event generation is limited to state machine actions, we only need to look at those actions to follow what is going on. That is, nothing about flow of control is hidden in nested synchronous service calls. This makes the application a lot easier to debug when something goes awry with state machine interactions.

12 Obviously, you are not going to put an entire linear programming algorithm in a single synchronous service. When the processing is complex enough to warrant development outside of the application model using other techniques, then all you need to do is invoke that processing from within the model.

13 The language was augmented with preprocessor directives that linked the C++ syntax to model elements. Thus the only true code generation needed was replacement of the preprocessor directives with C++ code derived from the graphical diagram element semantics.

14 Personally I have a problem with history as well. Even though Harel actions do not directly make use of it, the notion of making use of past state history seems like a violation of the FSA idea that a state cannot know where it has been. Arguing that we are just modifying transitions and not the actions themselves strikes me as an overly facile rationalization. In addition, history makes implementation enormously complicated. For example, the UML specification of Harel history (as of v2.0) is ambiguous, so the transformation engine vendor has to make implementation assumptions to support it.

Chapter 15

1 Before you send in your cards, letters, and death threats to laud the importance of the computational models of Turing and von Neumann, note the use of the qualifier “general.” The computational models, while mathematically defined, were created specifically to address the problem of computation. The finite state automata theory that underlies FSMs was developed independently and was not applied to software development until the late ’40s.

2 Most UML drawing tools use a rectangle with rounded corners. That’s because it is user-friendly to put additional information in the state, such as a description of the condition’s rules and policies, that fits better in a rectangle.

3 This is one reason why attributes are accessed directly by methods on an as-needed basis. It ensures that the alphabet is unambiguously defined at the time the state is entered.

4 Since we are talking about 4GL PIMs primarily in this book, we are not going to go into implementation details. Note, though, that standard concurrency techniques like thread management, semaphore blocking, and whatnot are a lot easier to implement correctly when the scope of change is known to be limited to a single procedure. (Usually state machine actions conveniently map 1:1 to 3GL procedures.)

5 This notion of serialization is quite common in the RAD IDEs that largely hide asynchronous processing. Invariably, behind the scenes that infrastructure is event-based, and there is an event queue manager somewhere that enables events to be serialized. To this day many RAD tools refer to the public hooks they provide to invoke developer code “on events.”

6 In theory, we could have different actions for the same event on different transitions. (I have always suspected this was what the Mealy authors had in mind.) However, in practice, Mealy models are almost always constructed with 1:1 mapping between action and event, which is the tendency we seek to avoid by using Moore models.

7 In the test hardware industry, the Setup [the hardware] → Initiate [the test] → Fetch [the results] has become a de facto standard, and virtually all test hardware provides an interface to support it.

8 Most tools that support translation can automatically generate a Sequence diagram from the model. That diagram can be immensely helpful during maintenance to determine how the flow of control needs to be modified.

9 Unless you are a Red Belt Superstar, do not even think about entering the Sequence diagram decisions directly into the model as you make them. Everyone always screws up somewhere along the line and has to revise early sequences. That’s a lot easier to do on a white board than in the model. Making mistakes is part of modeling. Fortunately, the DbC technique will uncover them before they do any harm.

10 In fact, in R-T/E applications it is very common for the attributes of hardware surrogates to map 1:1 to register fields. The hardware surrogate is then just a dumb data holder with attribute values we get or set. That mapping can become complicated, as the example on hardware control in Chapter 5 demonstrated. The important thing is that such complexity is usually at a lower level of abstraction than the subsystem where we manage what the hardware should be doing.

11 In my experience, conversion to MBD from traditional procedural techniques resulted in roughly a 50% reduction in released defect rate. Unfortunately, the data we collected could not determine the exact reasons for the reduction, but my gut feeling is that at least half of the improvement was directly attributable to describing behavior with FSMs.

12 A common solution for this sort of notification when something changes is the Observer pattern. If there is only one client who cares, though, it can be implemented much more simply.

13 Actually, if we needed to abstract a Keyboard for a word processor context, it would probably not accumulate characters. The rules for processing tokens are very complex (e.g., underscores, slashes, etc.) and we would want to encapsulate all of them. In addition, those parsing rules are clearly more the concern of word processing than the concern of converting hardware representations. So the Keyboard would very likely provide one character at a time to someone else.

14 An exception is self-directed events, which are usually given priority over external events for a given receiver FSM. However, one goal in providing a self-directed event is almost always to ensure that the state machine does get to the right state to process external events.

15 A clearer example would be if the instruments are a function generator and an oscilloscope. Then the oscilloscope requires the proper function to be set up and generated first. In effect, this means that both instruments need to be set up before either is initiated, and they must be initiated in tandem.

16 In fact, they will probably just be data holders. To start the motor to close the door we will send a message to Controller to start the motor in a particular direction. That will map into a hardware register write. In fact, we might want to consider changing the name from Controller to Motor, since that is the only hardware that is actually being manipulated in normal operations.

17 When two aircraft are low on the horizon at a substantial distance it becomes difficult to determine which radar image belongs to which aircraft, even if they are actually several thousand feet apart.

18 My undergraduate training was in geology and I spent nearly a decade doing field geophysics, so I couldn’t resist. BTW, they never send you to Paris to look at rocks, so I have an intimate knowledge of some of the best swamps, jungles, tundras, and deserts in the world—which accounts in no small part for why I do software today.

Chapter 16

1 Which is, in turn, a subset of the overall application’s state of being. However, our encapsulation of subsystems ensures that when designing FSMs within a subsystem we only need to worry about the subsystem’s context.

2 This is a conceptual metaphor to explain how the object and application perspectives map to one another. Do not waste time trying to design big, honking application state machines. We focus solely on object state machines explicitly to avoid that level of mind-numbing complexity.

3 Rebecca Wirfs-Brock was a pioneer of role-based design. Her methodology is rather different than MBD, but her book Object Design: Roles, Responsibilities, and Collaborations (Addison-Wesley, 2003) is an excellent presentation of this perspective. Within the context of MBD I think the overall perspective on roles she presents is quite valuable, and I think the book should be on every OO developer’s reference bookshelf.

4 This notion of checking on prior design work becomes a recurring theme when dealing with dynamics. The static structure that we developed is the skeleton on which the dynamic view is hung. So it is fairly common to uncover difficulties in the static structure when focused on the dynamic description.

5 FSA gurus have a more rigorous definition that only a mathematician could love, so this is just the OOA/D spin.

6 You were probably wondering, Grasshopper, why that stilted phrase, noteworthy happening, was used. Now you know.

7 Just to be clear, Harel is actually orthogonal to OO subclassing. Harel provides a form of subclassing for a single state machine. In OO subclassing the subclasses have different state machines. However, we might be tempted to eliminate subclasses by employing Harel for a single class’ FSM.

8 Note that I am careful to refer to the object’s behavior responsibility. When we employ state machines it is fairly common for state actions to do nothing except generate an event. Object responsibilities are always implemented as actions, but some actions do not explicitly implement problem space rules and policies. Such actions are part of the implementation of constraints on the sequencing of behavior responsibilities.

9 There are situations where synchronous services can be nested, such as a subset of knowledge changes that are common to multiple actions. But reviewers will want a good justification if synchronous services are nested.

10 In reality there may be other delays, such as network delays in distributed processing. Generally, these will be manifested by things like handshaking protocols that we may have to accommodate explicitly in the model as part of the requirements. Alternatively, it may be possible to deal with them in the transformation engine. For example, we may have an infrastructure available, such as CORBA support, which will already serialize the protocols so that they seem synchronous. In that case the event is external and the subsystem will only “see” it (push it on the queue) after the serialization.

Chapter 17

1 The notion of cycle here is looser than the notion of a closed graph cycle. While most objects’ life cycles are closed because iteration is fundamental to computation, that is not necessarily the case. Thus one can think of born → live → die as an object life cycle.

2 So why did we bother defining “atomic” responsibilities in the first place? The reason is that it is much easier, conceptually, to merge them when needed than it would be to break up monolithic responsibilities later; later on we might already be biased into a false notion of what “atomic” is in the collaboration context. That is, the monolithic responsibilities might incorrectly drive our notion of the level of abstraction of collaboration.

3 That’s true once one gets a bit used to designing state machines. Don’t get bent out of shape if states of being don’t seem to pop out of thin air when you first start out. That’s normal and it takes some practice.

4 I must emphasize that all one is doing is keeping track of collaborations, not messages. At this point we just need to know roughly who is talking to whom and when they are doing so. It would be premature to try to pin things down to individual messages.

5 There’s a second reason. Recall from the last chapter that one of the rules the modeler can count on the implementation enforcing is that events between the same two sender/receiver objects will be consumed in the same order they were generated.

6 When I was first introduced to the notion of asynchronous communications my instinctive reaction was: This can’t possibly work and, if one could get it to work, one’s mind would be turned to mush in the process. I spent a lot of time in the ensuing couple of years looking for exceptions, but there was always a simple and elegant reorganization of collaborations that saved the day. So eventually I gave up looking and took it on faith.

7 Don’t ask why. Originally it had its roots in sexual innuendo. However, the phrase became part of the lexicon of R-T/E software development decades ago, probably because women R-T/E developers were about as rare as Tennessee snail darters back then.

8 If that is done, it might be convenient to make Ready a superstate where those transitions are implied, as discussed in the last chapter.

9 In practice we would be unlikely to make this mistake. That’s because when we defined the knowledge responsibilities for Display Specification, we would have been forced to think carefully about all of the possible screens. With that inventory fresh in mind, we probably would have realized managing a user value is not the only thing Character Display does.

10 We are getting pretty close to the point where we might need a separate subsystem for the UI, though. So far things are simple enough that we can hide the processing in the implementation. But if the UI gets more complicated with things like nonnumeric fields and several ways for the user to navigate between fields, the mechanisms and mapping through Display Specification become complicated enough that we might want to design them explicitly as a separate problem from controlling the ATM hardware.

11 When dealing with relationship connectivity, one shouldn’t be overly concerned with physics. When dealing with logical connectivity, such navigation is entirely possible, especially in this case where Card Reader is really a surrogate for hardware. Nonetheless, one should avoid major Acts of Faith when thinking about relationship navigation. Here the problem space perspective of logically connecting through the hardware just doesn’t feel quite right.

12 To Dispatcher for reasons that will become clearer in a moment when we talk about the Main Menu.

13 Actually, error processing (displays, hardware resets, etc.) is something we would probably like to centralize, and Dispatcher might be convenient for that. That would be an entirely different functionality than our current view, so we will ignore it for the moment. But hold that thought because we will be back to it in a couple of paragraphs.

14 We could have named the state Transaction Display Initiated and I wouldn’t get bent out of shape over it. However, one can easily get carried away trying to put too much information in a name. In this case there are other possible screens that might be triggered from Display Initiated, as in the next paragraph.

15 Use case purists would probably get uptight about this being a stand-alone use case. They would argue that it is really just a variant, along with Withdrawal, of a single use case because of the similarities. Well, that’s just tough. The point of use cases is to cast the requirements into a form that is readily understood, and this is the best form for my exposition.

16 In this case there is a subtle trap when interpreting the use case. These three “states” were activities in the same line in the use case and were associated with a single decision, suggesting an “atomic” requirement. Don’t combine activities into a single action just because the use case puts them together. You need to validate the order independence explicitly rather than relying on the cosmetics of the use case organization.

17 But be sure to keep in mind that in MBD we use the superclass state machine as a notational convenience to avoid duplication in the subclasses. That is, there is no Harel-like inheritance.

Chapter 18

1 In MDA terms, the model is a Platform Independent Model (PIM). This is essentially OMG’s name for an OOA model. The basic idea is that the model describes the solution in such a fundamental way that we should be able to provide a mapping from that specification to any specific implementation environment. That, in turn, depends on the existence of metamodels for both the PIM representation and the specific computing environment.

2 There were some other bells and whistles, but these are the important ones for mapping to text-based AALs.

3 Curently most AALs are proprietary because they were developed for specific tools. As of this writing a battle is raging within OMG as the various vendors attempt to get their AAL blessed by OMG as the “official” AAL. I have chosen the high road and don’t want to get involved.

4 In practice, there are likely to be two write-only registers for start and stop. Simply writing to the registers will cause the motor to start or stop, respectively. But that’s a level of detail only a hardware guy could love. As stated our example enables us to use some of those neat bitwise operations to complicate the AAL.

5 If it doesn’t, then somebody will have to write one. Since such code is low-level implementation code, it would probably be done as realized code outside the scope of this problem design. (We could do it in AAL, but that would be much like writing a square root routine in Access macros.) It would clearly be reusable for any other application that needed to talk to a character display using this particular RTOS. So we are just doing what the RTOS vendor should have done in the first place.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.78.237