20 Design pattern:multi-panel interactive systems oufirstxampe e will devise adesign patte which,inaddition tolusanom typical properties of the object-oriented method,provides an excellent opportunity to contrast it with other approaches,in particular top-down functional decomposition. Because this example nicely captures on a small scale some of the principal properties of object-oriented software construction,I have often used it when requested to introduce an audience to the method in a few hours.By showing concretely (even to people who have had very little theoretical preparation)how one can proceed from a classical decomposition to an O-0 view of things,and the benefits gained in this transformation,it serves as a remarkable pedagogical device.This chapter has been written so that it could play the same role for readers who have been directed to it by the reference they found in the "spoiler"chapter at the beginning of this book. To facilitate their task,it has been made as self-contained as possible;this is why you will find a few repetitions with previous chapters,in particular a few short definitions of concepts which you already know inside out if you have been reading this book sequentially and carefully from the start. 20.1 MULTI-PANEL SYSTEMS The problem is to write a system covering a general type of interactive system,common in business data processing,in which users are guided at each step of a session by a full- screen panel,with predefined transitions between the available panels. The general pattern is simple and well defined.Each session goes through a certain number of states.In each state,a certain panel is displayed,showing questions to the user. The user will fill in the required answer;this answer will be checked for consistency (and questions asked again until an acceptable answer is found);then the answer will be processed in some fashion;for example the system will update a database.A part of the user's answer will be a choice for the next step to perform,which the system will interpret as a transition to another state,where the same process will be applied again A typical example would be an airline reservation system,where the states might represent such steps of the processing as User Identification,Enquiry on Flights(for a certain itinerary on a certain date),Enquiry on Seats(for a certain flight)and Reservation
20 Design pattern: multi-panel interactive systems In our first example we will devise a design pattern which, in addition to illustrating some typical properties of the object-oriented method, provides an excellent opportunity to contrast it with other approaches, in particular top-down functional decomposition. Because this example nicely captures on a small scale some of the principal properties of object-oriented software construction, I have often used it when requested to introduce an audience to the method in a few hours. By showing concretely (even to people who have had very little theoretical preparation) how one can proceed from a classical decomposition to an O-O view of things, and the benefits gained in this transformation, it serves as a remarkable pedagogical device. This chapter has been written so that it could play the same role for readers who have been directed to it by the reference they found in the “spoiler” chapter at the beginning of this book. To facilitate their task, it has been made as self-contained as possible; this is why you will find a few repetitions with previous chapters, in particular a few short definitions of concepts which you already know inside out if you have been reading this book sequentially and carefully from the start. 20.1 MULTI-PANEL SYSTEMS The problem is to write a system covering a general type of interactive system, common in business data processing, in which users are guided at each step of a session by a fullscreen panel, with predefined transitions between the available panels. The general pattern is simple and well defined. Each session goes through a certain number of states. In each state, a certain panel is displayed, showing questions to the user. The user will fill in the required answer; this answer will be checked for consistency (and questions asked again until an acceptable answer is found); then the answer will be processed in some fashion; for example the system will update a database. A part of the user’s answer will be a choice for the next step to perform, which the system will interpret as a transition to another state, where the same process will be applied again. A typical example would be an airline reservation system, where the states might represent such steps of the processing as User Identification, Enquiry on Flights (for a certain itinerary on a certain date), Enquiry on Seats (for a certain flight) and Reservation
676 DESIGN CASE STUDY:MULTI-PANEL INTERACTIVE SYSTEMS $20.1 A typical panel,for the Enquiry on Flights state,might look like the following (only intended,however,to illustrate the ideas,and making no claim of realism or good ergonomic design).The screen is shown towards the end of a step;items in color italics are the user's answers,and items in bold color show an answer displayed by the system. -Enquiry on Flights- A panel Flight sought from: Santa Barbara To: Paris Departure on or after: 21Nov On or before: 22 Nov Preferred airline(s): Special requirements: AVAILABLE FLIGHTS:1 FIt#AA 42 Dep 8:25 Arr 7:45 Thru:Chicago Choose next action: 0一Exit 1-Help 2-Further enquiry 3-Reserve a seat The session begins in an initial state,and ends whenever it reaches a final state.We The figure also can represent the overall structure by a transition graph showing the possible states and include state num- the transitions between them.The edges of the graph are labeled by integers bers,for use later in the discussion. corresponding to the possible user choices for the next step at the end of a state.At the top of the facing page is a graph for a simple airline reservation system. The problem is to come up with a design and implementation for such applications, achieving as much generality and flexibility as possible.In particular: GI.The graph may be large.It is not uncommon to see applications with several hundred states and correspondingly many transitions. G2.The structure is subject to change.The designers are unlikely to foresee all the possible states and transitions.As users start exercising the system,they will come up with requests for changes and additions. G3.Nothing in the given scheme is specific to the choice of application:the airline reservation mini-system is just a working example.If your company needs a number of such systems,either for its own purposes or (in a software house)for various customers,it will be a big benefit to define a general design or,better yet, a set of modules that you can reuse from application to application
676 DESIGN CASE STUDY: MULTI-PANEL INTERACTIVE SYSTEMS §20.1 A typical panel, for the Enquiry on Flights state, might look like the following (only intended, however, to illustrate the ideas, and making no claim of realism or good ergonomic design). The screen is shown towards the end of a step; items in color italics are the user’s answers, and items in bold color show an answer displayed by the system. The session begins in an initial state, and ends whenever it reaches a final state. We can represent the overall structure by a transition graph showing the possible states and the transitions between them. The edges of the graph are labeled by integers corresponding to the possible user choices for the next step at the end of a state. At the top of the facing page is a graph for a simple airline reservation system. The problem is to come up with a design and implementation for such applications, achieving as much generality and flexibility as possible. In particular: G1 • The graph may be large. It is not uncommon to see applications with several hundred states and correspondingly many transitions. G2 • The structure is subject to change. The designers are unlikely to foresee all the possible states and transitions. As users start exercising the system, they will come up with requests for changes and additions. G3 • Nothing in the given scheme is specific to the choice of application: the airline reservation mini-system is just a working example. If your company needs a number of such systems, either for its own purposes or (in a software house) for various customers, it will be a big benefit to define a general design or, better yet, a set of modules that you can reuse from application to application. A panel – Enquiry on Flights – Flight sought from: Departure on or after: To: On or before: Preferred airline (s): Special requirements: AVAILABLE FLIGHTS: 1 Flt# AA 42 Dep 8:25 Arr 7:45 Thru: Chicago Choose next action: 0 — Exit 1 — Help 2 — Further enquiry 3 — Reserve a seat Santa Barbara 21 Nov Paris 22 Nov The figure also include state numbers, for use later in the discussion
$20.2 A SIMPLE-MINDED ATTEMPT 677 A transition Initial diagram Help Help 1 Help Help 3 Confirmation Enquiry 5 on flights 2 3 Reservation Enquiry on seats 2 Help Help 20.2 A SIMPLE-MINDED ATTEMPT Let us begin with a straightforward,unsophisticated program scheme.This version is made of a number of blocks,one for each state of the system:BEnuin BReseo B etc.A typical block (expressed in an ad hoc notation,not the object-oriented notation of this book although it retains some of its syntactic conventions)looks like this: BEnquir “Display Enguiry on flights panel'” repeat "Read user's answers and choice C for the next step" if“Error in answer”then“Output appropriate message”end until not error in answer end Process answer” case Cin Co:goto Exit, C:goto BHelp C2:goto BReservation end and similarly for each state
§20.2 A SIMPLE-MINDED ATTEMPT 677 20.2 A SIMPLE-MINDED ATTEMPT Let us begin with a straightforward, unsophisticated program scheme. This version is made of a number of blocks, one for each state of the system: BEnquiry , BReservation, BCancellation etc. A typical block (expressed in an ad hoc notation, not the object-oriented notation of this book although it retains some of its syntactic conventions) looks like this: BEnquiry: “Display Enquiry on flights panel” repeat “Read user’s answers and choice C for the next step” if “Error in answer” then “Output appropriate message” end until not error in answer end “Process answer” case C in C0: goto Exit, C1: goto BHelp, C2: goto BReservation, … end and similarly for each state. Initial Confirmation Reservation Enquiry_ on_flights 2 2 2 2 2 3 3 3 3 3 1 1 1 1 1 1 1 1 Enquiry_ on_seats Help Help 1 1 Help Help Help Help 1 1 1 2 3 4 5 A transition diagram
678 DESIGN CASE STUDY:MULTI-PANEL INTERACTIVE SYSTEMS $20.3 This structure has something to speak for it:it is not hard to devise,and it will do the job.But from a software engineering viewpoint it leaves much to be desired. The most obvious criticism is the presence of goto instructions (implementing conditional jumps similar to the switch of C and the"Computed Goto"of Fortran),giving the control structure that unmistakable"spaghetti bowl"look. But the gotos are the symptom,not the real flaw.We have taken the superficial structure of the problem-the current form of the transition diagram-and hardwired it into the algorithm;the branching structure of the program is an exact reflection of the structure of the transition graph.This makes the software's design vulnerable to any of the simple and common changes cited above:any time someone asks us to add a state or change a transition,we will have to change the system's central control structure.And we can forget,of course,any hope of reusability across applications(goal G3 in the above list),as the control structure would have to cover all applications. This example is a sobering reminder that we should never get carried away when we hear about the benefits of"modeling the real world"or"deducing the system from the analysis of the reality".Depending on how you describe it,the real world can be simple or messy; a bad model will give bad software.What counts is not how close the software is to the real world,but how good the description is.More on this topic at the end of this chapter. To obtain not just a system but a good system we must think a little harder. 20.3 A FUNCTIONAL,TOP-DOWN SOLUTION Repeating on this particular example the evolution of the programming species as a whole, we will go from a low-level goto-based structure to a top-down,hierarchically organized solution,analyze its own limitations,and only then move on to an object-oriented version The hierarchical solution belongs to a general style also known as "structured",although this term should be used with care. For one thing,an O-O solution is certainly structured too,although more in the sense of "structured programming"as originally introduced in the seventies by Dijkstra and others than relative to the quite distinct notion of"structured design". The transition function The first step towards improving the solution is to get rid of the central role of the traversal algorithm in the software's structure.The transition diagram is just one property of the system and it has no reason to rule over everything else.Separating it from the rest of the algorithm will,if nothing else,rid us of the goto instructions.And we should also gain generality,since the transition diagram depends on the specific application,such as airline reservation,whereas its traversal may be described generically. What is the transition diagram?Abstractly,it is a function transition taking two arguments,a state and a user choice,such that transition (s,c)is the state obtained when the user chooses c when leaving state s.Here the word "function"is used in its
678 DESIGN CASE STUDY: MULTI-PANEL INTERACTIVE SYSTEMS §20.3 This structure has something to speak for it: it is not hard to devise, and it will do the job. But from a software engineering viewpoint it leaves much to be desired. The most obvious criticism is the presence of goto instructions (implementing conditional jumps similar to the switch of C and the “Computed Goto” of Fortran), giving the control structure that unmistakable “spaghetti bowl” look. But the gotos are the symptom, not the real flaw. We have taken the superficial structure of the problem — the current form of the transition diagram — and hardwired it into the algorithm; the branching structure of the program is an exact reflection of the structure of the transition graph. This makes the software’s design vulnerable to any of the simple and common changes cited above: any time someone asks us to add a state or change a transition, we will have to change the system’s central control structure. And we can forget, of course, any hope of reusability across applications (goal G3 in the above list), as the control structure would have to cover all applications. This example is a sobering reminder that we should never get carried away when we hear about the benefits of “modeling the real world” or “deducing the system from the analysis of the reality”. Depending on how you describe it, the real world can be simple or messy; a bad model will give bad software. What counts is not how close the software is to the real world, but how good the description is. More on this topic at the end of this chapter. To obtain not just a system but a good system we must think a little harder. 20.3 A FUNCTIONAL, TOP-DOWN SOLUTION Repeating on this particular example the evolution of the programming species as a whole, we will go from a low-level goto-based structure to a top-down, hierarchically organized solution, analyze its own limitations, and only then move on to an object-oriented version. The hierarchical solution belongs to a general style also known as “structured”, although this term should be used with care. For one thing, an O-O solution is certainly structured too, although more in the sense of “structured programming” as originally introduced in the seventies by Dijkstra and others than relative to the quite distinct notion of “structured design”. The transition function The first step towards improving the solution is to get rid of the central role of the traversal algorithm in the software’s structure. The transition diagram is just one property of the system and it has no reason to rule over everything else. Separating it from the rest of the algorithm will, if nothing else, rid us of the goto instructions. And we should also gain generality, since the transition diagram depends on the specific application, such as airline reservation, whereas its traversal may be described generically. What is the transition diagram? Abstractly, it is a function transition taking two arguments, a state and a user choice, such that transition (s, c) is the state obtained when the user chooses c when leaving state s. Here the word “function” is used in its
$20.3 A FUNCTIONAL,TOP-DOWN SOLUTION 679 mathematical sense;at the software level we can choose to implement transition either by a function in the software sense(a routine returning a value)or by a data structure such as an array.For the moment we can afford to postpone the choice between these solutions and just rely on transition as an abstract notion. In addition to the function transition we also need to designate one of the states,say state initial,as the place where all sessions start,and to designate one or more states as final through a boolean-valued function is final.Again this is a function in the mathematical sense,regardless of its eventual implementation. We can picture the transition function in tabular form,with rows representing states and columns representing choices,as shown below. Conventions used in this table:there is just one Help state,0,with a special transition Return which goes back to the state from which Help was reached,and just one final state, -1.These conventions will not be necessary for the rest of the discussion but help keep the table simple. A transition Choice→ 0 2 3 table ↓State 1(Initial) -1 0 5 2 2(Flights) 0 1 3 3(Seats) 0 2 4(Reserv.) 0 3 5(Confirm) 0 4 1 (Help) Return -1(Final) The routine architecture Following the traditional precepts of top-down decomposition,we choose a "top"(the main program)for our system.This should clearly be the routine execute session that describes how to execute a complete interactive session
§20.3 A FUNCTIONAL, TOP-DOWN SOLUTION 679 mathematical sense; at the software level we can choose to implement transition either by a function in the software sense (a routine returning a value) or by a data structure such as an array. For the moment we can afford to postpone the choice between these solutions and just rely on transition as an abstract notion. In addition to the function transition we also need to designate one of the states, say state initial, as the place where all sessions start, and to designate one or more states as final through a boolean-valued function is_ final. Again this is a function in the mathematical sense, regardless of its eventual implementation. We can picture the transition function in tabular form, with rows representing states and columns representing choices, as shown below. Conventions used in this table: there is just one Help state, 0, with a special transition Return which goes back to the state from which Help was reached, and just one final state, –1. These conventions will not be necessary for the rest of the discussion but help keep the table simple. The routine architecture Following the traditional precepts of top-down decomposition, we choose a “top” (the main program) for our system. This should clearly be the routine execute_session that describes how to execute a complete interactive session. Choice → ↓ State 0 1 2 3 1 (Initial) –1 0 5 2 2 (Flights) 0 1 3 3 (Seats) 0 2 4 4 (Reserv.) 0 3 5 5 (Confirm) 0 4 1 0 (Help) Return –1 (Final) A transition table
680 DESIGN CASE STUDY:MULTI-PANEL INTERACTIVE SYSTEMS $20.3 Level3 Top-down execute session functional decomposition execute initial transition state is_final Level2 Level1 display read correct message process Immediately below (level 2)we will find the operations relative to states:definition of the initial and final states,transition structure,and execute state which prescribes the actions to be executed in each state.Then at the lowest level (1)we will find the constituent operations of execute state:display a screen and so on.Note how such a solution may be described,as well as anything object-oriented that we may later see,to "reflect the real world":the structure of the software perfectly mirrors the structure of an application,which involves states,which involve elementary operations.Real- worldliness is not,in this example and many others,a significant difference between O-O and other approaches;what counts is how we model the world. In writing execute session let us try to make it as application-independent as possible.(The routine is again expressed in an ad hoc notation imitated from the O-O notation of the rest of this book.The repeat...until...loop is borrowed from Pascal.) execute session is --Execute a complete session of the interactive system local state,choice:INTEGER do state initial repeat execute state (state,next) --Routine execute state updates the value of next. state :transition (state,next) until is final (state)end end
680 DESIGN CASE STUDY: MULTI-PANEL INTERACTIVE SYSTEMS §20.3 Immediately below (level 2) we will find the operations relative to states: definition of the initial and final states, transition structure, and execute_state which prescribes the actions to be executed in each state. Then at the lowest level (1) we will find the constituent operations of execute_state: display a screen and so on. Note how such a solution may be described, as well as anything object-oriented that we may later see, to “reflect the real world”: the structure of the software perfectly mirrors the structure of an application, which involves states, which involve elementary operations. Realworldliness is not, in this example and many others, a significant difference between O-O and other approaches; what counts is how we model the world. In writing execute_session let us try to make it as application-independent as possible. (The routine is again expressed in an ad hoc notation imitated from the O-O notation of the rest of this book. The repeat … until … loop is borrowed from Pascal.) execute_session is -- Execute a complete session of the interactive system local state, choice: INTEGER do state := initial repeat execute_state (state, →next) -- Routine execute_state updates the value of next. state := transition (state, next) until is_final (state) end end execute_session initial transition execute_ state is_final display read correct message process Level 1 Level 3 Level 2 Top-down functional decomposition
$20.3 A FUNCTIONAL,TOP-DOWN SOLUTION 681 This is a typical transition diagram traversal algorithm.(The reader who has written a lexical analyzer will recognize the pattern.)At each stage we are in a state state, originally set to initial;the process terminates when state satisfies is final.For a non-final state we executeexecute state,which takes the current state and returns the user's transition choice through its second argument next,which the function transition uses, together with state,to determine the next state. The→notation is a The technique using a procedure execute state that changes the value of one of its temporary comven- arguments would never be appropriate in good O-O design,but here it is the most tion,used only for this expedient.To signal it clearly,the notation flags an "out"argument such as next with an particular procedure and forread below. arrow-.Instead of a procedure which modifies an argument,C developers would make execute state a side-effect-producing function called as next :execute state (state )we will see that this practice is subject to criticism too. Since execute state does not show any information about any particular interactive application,you must fill in the application-specific properties appearing on level 2 in the figure:transition function;initial state;is final predicate. To complete the design,we must refine the execute state routine describing the actions to be performed in each state.Its body is essentially an abstracted form of the contents of the successive blocks in the initial goto-based version: execute state (in s:INTEGER;out c:INTEGER)is --Execute the actions associated with state s. --returning into c the user's choice for the next state. local a:ANSWER;ok:BOOLEAN do repeat display (s) read(s,→a) ok:correct (s,a) if not ok then message (s,a)end until ok end process (s,a) c :next choice (a) end This assumes level 1 routines with the following roles: display (s)outputs the panel associated with state s. read (s,-a)reads into a the user's answer to the display panel of state s. correct (s,a)returns true if and only if a is an acceptable answer to the question displayed in state s;if so,process(s,a)processes answer a,for example by updating a database or displaying more information;if not,message (s,a)outputs the relevant error message
§20.3 A FUNCTIONAL, TOP-DOWN SOLUTION 681 This is a typical transition diagram traversal algorithm. (The reader who has written a lexical analyzer will recognize the pattern.) At each stage we are in a state state, originally set to initial; the process terminates when state satisfies is_final. For a non-final state we execute execute_state, which takes the current state and returns the user’s transition choice through its second argument next, which the function transition uses, together with state, to determine the next state. The technique using a procedure execute_state that changes the value of one of its arguments would never be appropriate in good O-O design, but here it is the most expedient. To signal it clearly, the notation flags an “out” argument such as next with an arrow →. Instead of a procedure which modifies an argument, C developers would make execute_state a side-effect-producing function called as next := execute_state (state); we will see that this practice is subject to criticism too. Since execute_state does not show any information about any particular interactive application, you must fill in the application-specific properties appearing on level 2 in the figure: transition function; initial state; is_final predicate. To complete the design, we must refine the execute_state routine describing the actions to be performed in each state. Its body is essentially an abstracted form of the contents of the successive blocks in the initial goto-based version: execute_state (in s: INTEGER; out c: INTEGER) is -- Execute the actions associated with state s, -- returning into c the user’s choice for the next state. local a: ANSWER; ok: BOOLEAN do repeat display (s) read (s, →a) ok := correct (s, a) if not ok then message (s, a) end until ok end process (s, a) c := next_choice (a) end This assumes level 1 routines with the following roles: • display (s) outputs the panel associated with state s. • read (s, →a) reads into a the user’s answer to the display panel of state s. • correct (s, a) returns true if and only if a is an acceptable answer to the question displayed in state s; if so, process (s, a) processes answer a, for example by updating a database or displaying more information; if not, message (s, a) outputs the relevant error message. The → notation is a temporary convention, used only for this particular procedure and for read below
682 DESIGN CASE STUDY:MULTI-PANEL INTERACTIVE SYSTEMS $20.4 The type ANSWER of the object representing the user's answer has not been refined further.A value a of that type globally represents the input entered by the user in a given state;it is assumed to include the user's choice for the next step,written next choice (a). (ANSWER is in fact already very much like a class,even though the rest of the architecture is not object-oriented at all.) To obtain a working application,you will need to fill in the various level 1 features: display,read,correct,message and process. 20.4 A CRITIQUE OF THE SOLUTION Have we now a satisfactory solution?Not quite.It is better than the first version,but still falls short of our goals of extendibility and reusability. Statism Although on the surface it seems we have been able to separate the generic from the application-specific,in reality the various modules are still tightly coupled with each other and with the choice of application.The main problem is the data transmission structure of the system.Consider the signatures (argument and result types)of the routines: execute state n s:STATE:out c:CHOICE) display in s:STATE read in s:STATE out a:ANSWER) State intervention correct in s:STATE:a:ANSWER):BOOLEAN message in s:STATE:a:ANSWER) process in s:STATE:a:ANSWER) The observation (which sounds like an economist's lament)is that the role of the The architectural state is too pervasive.The current state appears under the names as an argument in all thefgre isonpage 680. routines,coming from the top module execute session,where it is known as state.So the hierarchical structure shown in the last figure,seemingly simple and manageable,is a lie, or more precisely a facade.Behind the formal elegance of the functional decomposition lies a jumble of data transmission.The true picture,shown at the top of the facing page, must involve the data. The background for object technology,as presented at the beginning of this book,is the battle between the finction and data(object)aspects of software systems for control of the architecture.In non-O-O approaches,the functions rule unopposed over the data; but then the data take their revenge. The revenge comes in the form of sabotage.By attacking the very foundations of the architecture,the data make the system impervious to change-until,like a government unable to handle its perestroika,it will crumble under its own weight
682 DESIGN CASE STUDY: MULTI-PANEL INTERACTIVE SYSTEMS §20.4 The type ANSWER of the object representing the user’s answer has not been refined further. A value a of that type globally represents the input entered by the user in a given state; it is assumed to include the user’s choice for the next step, written next_choice (a). (ANSWER is in fact already very much like a class, even though the rest of the architecture is not object-oriented at all.) To obtain a working application, you will need to fill in the various level 1 features: display, read, correct, message and process. 20.4 A CRITIQUE OF THE SOLUTION Have we now a satisfactory solution? Not quite. It is better than the first version, but still falls short of our goals of extendibility and reusability. Statism Although on the surface it seems we have been able to separate the generic from the application-specific, in reality the various modules are still tightly coupled with each other and with the choice of application. The main problem is the data transmission structure of the system. Consider the signatures (argument and result types) of the routines: execute_state ( in s: STATE ; out c: CHOICE) display ( in s: STATE ) read ( in s: STATE ; out a: ANSWER) correct ( in s: STATE ; a: ANSWER): BOOLEAN message ( in s: STATE ; a: ANSWER) process ( in s: STATE ; a: ANSWER) The observation (which sounds like an economist’s lament) is that the role of the state is too pervasive. The current state appears under the name s as an argument in all the routines, coming from the top module execute_session, where it is known as state. So the hierarchical structure shown in the last figure, seemingly simple and manageable, is a lie, or more precisely a façade. Behind the formal elegance of the functional decomposition lies a jumble of data transmission. The true picture, shown at the top of the facing page, must involve the data. The background for object technology, as presented at the beginning of this book, is the battle between the function and data (object) aspects of software systems for control of the architecture. In non-O-O approaches, the functions rule unopposed over the data; but then the data take their revenge. The revenge comes in the form of sabotage. By attacking the very foundations of the architecture, the data make the system impervious to change — until, like a government unable to handle its perestroika, it will crumble under its own weight. State intervention The architectural figure is on page 680
$20.4 A CRITIQUE OF THE SOLUTION 683 The flow of data execute session Level3 state initial transition execute Level 2 state is final state state state state Level 1 display read correct message process In this example the subversion of the structure comes in particular from the need to discriminate on states.All the level 1 routines must perform different actions depending on s:to display the panel for a certain state;to read and interpret a user answer(made of a number of input fields,different for each state);to determine whether the answer is correct;to output the proper error message;to process a correct answer-you must know the state.The routines will perform a discrimination of the form inspect S when Initial then when Enquiry on flights then end This means long and complex control structures and,worse yet,a fragile system: any addition of a state will require changes throughout the structure.This is a typical case of unbridled knowledge distribution:far too many modules of the system rely on a piece of information-the list of all possible states-which is subject to change. The situation is in fact even worse than it appears if we are hoping for general reusable solutions.There is an extra implicit argument in all the routines considered so far:the application-airline reservation or anything else we are building.So to make routines such as display truly general we would have to let them know about all states of all possible applications in a given computing environment!Function transition would similarly contain the transition graph for all applications.This is of course unrealistic
§20.4 A CRITIQUE OF THE SOLUTION 683 In this example the subversion of the structure comes in particular from the need to discriminate on states. All the level 1 routines must perform different actions depending on s: to display the panel for a certain state; to read and interpret a user answer (made of a number of input fields, different for each state); to determine whether the answer is correct; to output the proper error message; to process a correct answer — you must know the state. The routines will perform a discrimination of the form inspect s when Initial then … when Enquiry_on_flights then … … end This means long and complex control structures and, worse yet, a fragile system: any addition of a state will require changes throughout the structure. This is a typical case of unbridled knowledge distribution: far too many modules of the system rely on a piece of information — the list of all possible states — which is subject to change. The situation is in fact even worse than it appears if we are hoping for general reusable solutions. There is an extra implicit argument in all the routines considered so far: the application — airline reservation or anything else we are building. So to make routines such as display truly general we would have to let them know about all states of all possible applications in a given computing environment! Function transition would similarly contain the transition graph for all applications. This is of course unrealistic. execute_session initial transition execute_ state is_final display read correct message process Level 1 Level 3 Level 2 state state state state state The flow of data
684 DESIGN CASE STUDY:MULTI-PANEL INTERACTIVE SYSTEMS $20.5 20.5 AN OBJECT-ORIENTED ARCHITECTURE The very deficiencies of top-down functional decomposition point to what we must do to obtain a good object-oriented version. The law of inversion What went wrong?Too much data transmission in a software architecture usually signals a flaw in the design.The remedy,which leads directly to object-oriented design,may be expressed by the following design rule: Law of inversion If your routines exchange too many data,put your routines in your data. Instead of building modules around operations (such as execute session and execute state)and distributing the data structures between the resulting routines,with all the unpleasant consequences that we have seen,object-oriented design does the reverse:it uses the most important data types as the basis for modularization,attaching each routine to the data type to which it relates most closely.When objects take over,their former masters,the functions,become their vassals. The law of inversion is the key to obtaining an object-oriented design from a classical functional(procedural)decomposition,as in this chapter.Such a need arises in cases of reverse-engineering an existing non-O-O system to make it more maintainable and prepare its evolution;it is also frequent in teams that are new to object-oriented design and think“functional”first. It is of course best to design in an object-oriented fashion from the beginning;then no inversion is needed.But the law of inversion is useful beyond cases of reverse- engineering and novice developers.Even someone who has been exposed to the principles of object-oriented software construction may come up with an initial design that has pockets of functional decomposition in an object landscape.Analyzing data transmission is a good way to detect and correct such design flaws.If you see-even in a structure intended as O-O-a data transmission pattern similar to what happens with states in the example of this chapter,it should catch your attention.Probing further will in most cases lead you to the discovery of a data abstraction that has not received its proper due in the software's architecture. State as a class The "state"example is typical.Such a data type,appearing so pervasively in the data transmissions between routines,is a prime candidate for serving as one of the modular components of an object-oriented architecture,which must be based on classes(abstractly described data types)
684 DESIGN CASE STUDY: MULTI-PANEL INTERACTIVE SYSTEMS §20.5 20.5 AN OBJECT-ORIENTED ARCHITECTURE The very deficiencies of top-down functional decomposition point to what we must do to obtain a good object-oriented version. The law of inversion What went wrong? Too much data transmission in a software architecture usually signals a flaw in the design. The remedy, which leads directly to object-oriented design, may be expressed by the following design rule: Instead of building modules around operations (such as execute_session and execute_state) and distributing the data structures between the resulting routines, with all the unpleasant consequences that we have seen, object-oriented design does the reverse: it uses the most important data types as the basis for modularization, attaching each routine to the data type to which it relates most closely. When objects take over, their former masters, the functions, become their vassals. The law of inversion is the key to obtaining an object-oriented design from a classical functional (procedural) decomposition, as in this chapter. Such a need arises in cases of reverse-engineering an existing non-O-O system to make it more maintainable and prepare its evolution; it is also frequent in teams that are new to object-oriented design and think “functional” first. It is of course best to design in an object-oriented fashion from the beginning; then no inversion is needed. But the law of inversion is useful beyond cases of reverseengineering and novice developers. Even someone who has been exposed to the principles of object-oriented software construction may come up with an initial design that has pockets of functional decomposition in an object landscape. Analyzing data transmission is a good way to detect and correct such design flaws. If you see — even in a structure intended as O-O — a data transmission pattern similar to what happens with states in the example of this chapter, it should catch your attention. Probing further will in most cases lead you to the discovery of a data abstraction that has not received its proper due in the software’s architecture. State as a class The “state” example is typical. Such a data type, appearing so pervasively in the data transmissions between routines, is a prime candidate for serving as one of the modular components of an object-oriented architecture, which must be based on classes (abstractly described data types). Law of inversion If your routines exchange too many data, put your routines in your data