700 INHERITANCE CASE STUDY:"UNDO"IN AN INTERACTIVE SYSTEM $21.2 What do such classes represent?An instance of LINE DELETION,as illustrated below,is a little object that carries with it all the information associated with an execution of the command:the line being deleted (deleted line,a string)and its index in the text (deleted line index,an integer).This is the information needed to undo the command should this be required later on,or to redo it deleted line index 45 A command "Some text" object deleted line The exact attributes-such as deleted line and deleted line index here -will See“Requirements differ for each command class,but they should always be sufficient to support the local on the solution”", variants of execute and undo.Such objects,conceptually describing the difference page 697. between the states that precede and follow the application of a command,will enable us to satisfy requirement U3 of the earlier list-storing only what is strictly necessary. The inheritance structure of command classes may look like this: execute* Command undo* COMMAND class hierarchy LINE LINE STRING INSERTION DELETION REPLACE The graph shown is flat (all proper descendants of COMMAND at the same level), but nothing precludes adding more structure by grouping command types into intermediate categories;this will be justified if such categories make sense as abstract data types,that is to say,have specific features. When defining a notion,it is always important to indicate what it does not cover. Here the concept of command does not include Undo and Redo;for example it would not make sense to undo an Undo(except in the sense of doing a Redo).For this reason the discussion uses the term operation for Undo and Redo,reserving command for operations which can be undone and redone,such as line insertion.There is no need for a class covering the notion of operation,since non-command operations such as Undo have only one relevant feature,their ability to be executed. This is a good example of the limitations of simplistic approaches to "find the objects", “The nous and the such as the famous "Underline the nouns"idea studied in a later chapter.In the verbs",page 720. specification of the problem,the nouns command and operation are equally important; but one gives a fundamental class,the other does not give a class at all.Only the abstract data type perspective-studying abstractions in terms of the applicable operations and their properties-can help us find the classes of our object-oriented systems
700 INHERITANCE CASE STUDY: “UNDO” IN AN INTERACTIVE SYSTEM §21.2 What do such classes represent? An instance of LINE_DELETION, as illustrated below, is a little object that carries with it all the information associated with an execution of the command: the line being deleted (deleted_line, a string) and its index in the text (deleted_line_index, an integer). This is the information needed to undo the command should this be required later on, or to redo it. The exact attributes — such as deleted_line and deleted_line_index here — will differ for each command class, but they should always be sufficient to support the local variants of execute and undo. Such objects, conceptually describing the difference between the states that precede and follow the application of a command, will enable us to satisfy requirement U3 of the earlier list — storing only what is strictly necessary. The inheritance structure of command classes may look like this: The graph shown is flat (all proper descendants of COMMAND at the same level), but nothing precludes adding more structure by grouping command types into intermediate categories; this will be justified if such categories make sense as abstract data types, that is to say, have specific features. When defining a notion, it is always important to indicate what it does not cover. Here the concept of command does not include Undo and Redo; for example it would not make sense to undo an Undo (except in the sense of doing a Redo). For this reason the discussion uses the term operation for Undo and Redo, reserving command for operations which can be undone and redone, such as line insertion. There is no need for a class covering the notion of operation, since non-command operations such as Undo have only one relevant feature, their ability to be executed. This is a good example of the limitations of simplistic approaches to “find the objects”, such as the famous “Underline the nouns” idea studied in a later chapter. In the specification of the problem, the nouns command and operation are equally important; but one gives a fundamental class, the other does not give a class at all. Only the abstract data type perspective — studying abstractions in terms of the applicable operations and their properties — can help us find the classes of our object-oriented systems. "Some text" deleted_line_index deleted_line 45 A command object See “Requirements on the solution”, page 697. Command class hierarchy * LINE_ … execute* undo* INSERTION LINE_ DELETION COMMAND STRING_ REPLACE “The nouns and the verbs”, page 720
$21.2 FINDING THE ABSTRACTIONS 701 The basic interactive step To get started we will see how to support one-level undo.The generalization to multi-level undo-redo will come next. In any interactive system,there must be somewhere,in a module in charge of the communication with users,a passage of the form basic interactive step is --Decode and execute one user request. do "Find out what the user wants us to do next" “Doit(if possible)” end In a traditionally structured system,such as editor,these operations will be executed as part of a loop,the program's"basic loop": from start until quit has been requested and confirmed loop basic interactive step end whereas more sophisticated systems may use an event-driven scheme,in which the loop is external to the system proper (being managed by the underlying graphical environment).But in all cases there is a need for something like basic interactive step. In light of the abstractions just identified,we can reformulate the body of the procedure as "Get latest user request" "Decode request" if "Request is a normal command (not Undo)"then "Determine the corresponding command in our system" "Execute that command" elseif“Request is Undo”then if“There is a command to be undone”then Undo last command'” elseif"There is a command to be redone"then “Redo last command'" end else "Report erroneous request" end
§21.2 FINDING THE ABSTRACTIONS 701 The basic interactive step To get started we will see how to support one-level undo. The generalization to multi-level undo-redo will come next. In any interactive system, there must be somewhere, in a module in charge of the communication with users, a passage of the form basic_interactive_step is -- Decode and execute one user request. do “Find out what the user wants us to do next” “Do it (if possible)” end In a traditionally structured system, such as editor, these operations will be executed as part of a loop, the program’s “basic loop”: from start until quit_has_been_requested_and_confirmed loop basic_interactive_step end whereas more sophisticated systems may use an event-driven scheme, in which the loop is external to the system proper (being managed by the underlying graphical environment). But in all cases there is a need for something like basic_interactive_step. In light of the abstractions just identified, we can reformulate the body of the procedure as “Get latest user request” “Decode request” if “Request is a normal command (not Undo)” then “Determine the corresponding command in our system” “Execute that command” elseif “Request is Undo” then if “There is a command to be undone” then “Undo last command” elseif “There is a command to be redone” then “Redo last command” end else “Report erroneous request” end
702 INHERITANCE CASE STUDY:"UNDO"IN AN INTERACTIVE SYSTEM $21.2 This implements the convention suggested earlier that Undo applied just after Undo means Redo.A request to Undo or Redo is ignored if there is nothing to undo or redo.In a simple text editor with a keyboard interface,"Decode request"would analyze the user input,looking for such codes as control-I (for insert line),control-D (for delete line)and so on.With graphical interfaces you have to determine what input the user has entered, such as a choice in a menu,a button clicked in a menu,a key pressed. Remembering the last command With the notion of command object we can be more specific about the operations performed by basic interactive step.We will use an attribute requested:COMMAND --Command requested by interactive user representing the latest command that we have to execute,undo or redo.This enables us to refine the preceding scheme of basic interactive step into: "Get and decode latest user request" if“Request is normal command(not Undo)”then "Create appropriate command object and attach it to requested" --requested is created as an instance of some -descendant of COMMAND,such as LINE DELETION --(This instruction is detailed below.) Dynamic requested.execute;undoing mode :False Binding elseif "request is Undo"and requested /Void then if undoing mode then "This is a Redo;details left to the reader" else equested.undo undoing mode:=True end else "Erroneous request:output warning,or do nothing" end The boolean entity undoing mode determines whether the last operation was an Undo.In Exercise E21.2. this case an immediately following Undo request would mean a Redo,although the page 716. straightforward details have been left to the reader;we will see the full details of Redo implementation in the more interesting case of a multi-level mechanism. The information stored before each command execution is an instance of some See“Requirements descendant of COMMAND such as LINE DELET/ON.This means that,as announced,the on the solution”, solution satisfies the property labeled U3 in the list ofrequirements:what we store for each page 697. command is the difference between the new state and the previous one,not the full state
702 INHERITANCE CASE STUDY: “UNDO” IN AN INTERACTIVE SYSTEM §21.2 This implements the convention suggested earlier that Undo applied just after Undo means Redo. A request to Undo or Redo is ignored if there is nothing to undo or redo. In a simple text editor with a keyboard interface, “Decode request” would analyze the user input, looking for such codes as control-I (for insert line), control-D (for delete line) and so on. With graphical interfaces you have to determine what input the user has entered, such as a choice in a menu, a button clicked in a menu, a key pressed. Remembering the last command With the notion of command object we can be more specific about the operations performed by basic_interactive_step. We will use an attribute requested: COMMAND -- Command requested by interactive user representing the latest command that we have to execute, undo or redo. This enables us to refine the preceding scheme of basic_interactive_step into: “Get and decode latest user request” if “Request is normal command (not Undo)” then “Create appropriate command object and attach it to requested ” -- requested is created as an instance of some -- descendant of COMMAND, such as LINE_DELETION -- (This instruction is detailed below.) ; undoing_mode := False elseif “request is Undo” and requested /= Void then if undoing_mode then “This is a Redo; details left to the reader” else ; undoing_mode := True end else “Erroneous request: output warning, or do nothing” end The boolean entity undoing_mode determines whether the last operation was an Undo. In this case an immediately following Undo request would mean a Redo, although the straightforward details have been left to the reader; we will see the full details of Redo implementation in the more interesting case of a multi-level mechanism. The information stored before each command execution is an instance of some descendant of COMMAND such as LINE_DELETION. This means that, as announced, the solution satisfies the property labeled U3 in the list of requirements: what we store for each command is the difference between the new state and the previous one, not the full state. requested ● execute Dynamic Binding requested ● undo Exercise E21.2, page 716. See “Requirements on the solution”, page 697