1 2 Lecture 23: Introduction to Programming An example: undo-redo Bertrand Meyer Last revised 13 January 2005 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 The problem Working example: text editor 3 4 � Enabling users of an interactive system to Notion of “current line”. Assume commands such as: cancel the effect of the last command. � Insert line after current position � Insert line before current position � Often implemented as “Control-Z”. � Delete current line � Replace current line � Swap current line with next if any � Should support multi-level undo-redo, with � ... no limitation other than a possible maximum set by the user This is a line-oriented view for simplicity, but the � A good review of O-O techniques discussion applies to more sophisticated views Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Underlying class (from “business model”) Key step in devising a software architecture 5 6 class EDIT_CONTROLLER feature Finding the right abstractions text: LI NKED_LIST [ STRING ] remove is -- Remove line at current position. (Interesting object types) require not off do text.remove end Here: put_right ( line: STRI NG ) is -- Insert line after current position. require not after � The notion of “command” do text.put_right ( line ) end ... end Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 1
Keeping the history of the session What’s a “command” object? 7 8 The history list: A command object (instance of the class COMMAND ) includes inform ation about one execution of a command by the user, sufficient to: � Execute the command Insert Insert Remove Insert Swap � Cancel the com mand if requested later For example, in a delete command (as implemented by Oldest Most recent remove ), we need: • The position of the line being deleted history : LINKED_LIST [ COMMAND ] • The content of that line! Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 A general notion of command A general notion of command 9 10 deferred class COMMAND feature deferred class COMMAND feature done: BOOLEAN is -- Has this command been executed? execute is execute is -- Carry out one execution of this command. -- Carry out one execution of this command. deferred deferred ensure ensure done: done done: done end end undo is undo is -- Cancel an earlier execution of this command. -- Cancel an earlier execution of this command. require require already: done already: done deferred deferred end end end end Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Command class hierarchy A command class (sketch, no contracts) 11 12 class DELETION inherit COMMAND feature ∗ execute ∗ controller: EDIT_CONTROLLER ∗ -- Access to business m odel COMMAND deferred undo * line: STRING + effective -- The line being deleted index : INTEGER -- Position of line being deleted + + execute is … -- Remove current line and remember it. DELETION INSERTION do line : = controller.item ; index : = controller.index controller.remove ; done : = True execute + execute + end undo + undo + undo is -- Re-insert previously removed line. line index do index controller.go_ith ( index) ... controller.put_left ( line ) end ... end Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 2
Executing a user command Underlying class (from “business model”) 13 14 class EDIT_CONTROLLER feature The history list: text: LI NKED_LIST [ STRING ] remove is -- Remove line at current position. require not off do Insert Insert Remove Insert Swap text.remove end put_right ( line: STRI NG ) is Oldest Most recent -- Insert line after current position. require not after do text.put_right (line) history : LINKED_LIST [ COMMAND ] end ... Also item, index, go_ith, put_left ... end Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Executing a user command Conditional creation (1) 15 16 decode_user_request a1 : A if “Request is normal command” then A if condition_1 then -- “Create command object c corresponding to user request” -- “Create a1 as an instance of B” history.extend ( c ) elseif condition_2 then c .execute … -- “Create a1 as an instance of C” Remove Insert Insert Insert elseif “Request is UNDO” then ... etc... if not history.before then B C item history.item.undo history.back -- We ignore excessive requests a1 : A; b1: B; c1: C; d1: D; ... end if condition_1 then … elseif “Request is REDO” then create b1.make (...) if not history.is_last then D a1 := b1 history.forth elseif condition_2 then history. item.undo -- We ignore excessive requests create c1.make (...) end a1 := c1 end ... etc... Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Conditional creation (2) Executing a user command 17 18 decode_user_request a1 : A A if “Request is normal command” then if condition_1 then -- “Create command object c corresponding to user request” -- “Create a1 as an instance of B” history.extend ( c ) elseif condition_2 then c .execute … -- “Create a1 as an instance of C” Insert Insert Remove Insert elseif “Request is UNDO” then ... etc... B if not history.before then C item history.item.undo history.back -- Ignore excessive requests a1 : A end … if condition_1 then elseif “Request is REDO” then create { B } a1.make (...) if not history.is_last then D elseif condition_2 then history.forth create { C } a1.make (...) history. item.undo -- Ignore excessive requests ... etc... end end Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 3
Creating command objects (1) Command class hierarchy 19 20 ∗ execute ∗ c : COMMAND ∗ COMMAND deferred undo * ... + effective decode_user_request + + if “Request is delete ” then … DELETION INSERTION create { DELETION } c elseif “Request is insert ” then execute + execute + undo + undo + create { INSERTION } c index line index ... ... etc... ... Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Creating command objects (2) The undo-redo pattern 21 22 � Give each com mand type a number (or other key) � Has been extensively used (e.g. in Eiffel � Initially, fill in a table (e.g. an array), with one tools) instance of each command type. � Fairly easy to implement ... � Details must be handled carefully (e.g. ... some commands may not be undoable) Swap � Elegant use of O-O techniques Insertion � Disadvantage: explosion of small classes � To get a new command object: Deletion “Determine command_type ” � In Java, can use “inner” classes. c : = clone ( COMMAND_TABLE.item ( command_type )) Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Using agents The history list in the undo-redo pattern 23 24 For each user command, have two routines: history : LINKED_LIST [ COMMAND ] � The routine to do it � The routine to undo it! Insert Insert Remove Insert Swap Oldest Most recent Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 Chair of Softw are Engineering I ntroduction to Programming – Lecture 23 4
Recommend
More recommend