Lecture 11: Command Design Pattern Software Construction in Java for HSE Moscow Tom Verhoeff Eindhoven University of Technology Department of Mathematics & Computer Science Software Engineering & Technology Group www.win.tue.nl/ wstomv/edu/sc-hse c 2013, T. Verhoeff @ TUE.NL 1/27 Software Construction: Lecture 11
Overview Feedback on Series 10 Organization of GUI application: Model View Controller Menus and Graphics in a Java GUI Command Design Pattern: Do, Undo, Redo c 2013, T. Verhoeff @ TUE.NL 2/27 Software Construction: Lecture 11
Feedback on Simple Kakuro Helper 1 & 2 Simple Kakuro Helper : Much better: only 2 Rejected Rejected work must be improved; see FAQ Simple Kakuro Helper 2: Only 18 students obtain max score Try to improve performance: maxnumber = 30 must run 10 s c 2013, T. Verhoeff @ TUE.NL 3/27 Software Construction: Lecture 11
Feedback on Testing of KakuroCombinationGenerator (a) Why is it not a good idea to include unnecessary test cases? Costs extra test development time. Gives false impression of application code quality. Gives false impression of test quality. Costs extra test time when executing tests. Adds to the maintenance burden. c 2013, T. Verhoeff @ TUE.NL 4/27 Software Construction: Lecture 11
Feedback on Testing of KakuroCombinationGenerator (b) What would be the consequences for testing of generate(int, int) in KakuroCombinationGenerator, when the postcondition would be weakened by dropping the requirement of lexicographic order? That is, when method generate() would be allowed to generate combinations in any order. Concern With lex. order Without lex. order No missing Count, and compare with expected count No duplicates Compare with previous Store all and compare Order Compare with previous Not a concern Cost Keep track of previous Keep track of all c 2013, T. Verhoeff @ TUE.NL 5/27 Software Construction: Lecture 11
Feedback on Testing of KakuroCombinationGenerator (b) Checking lexicographic order is easy: one extra variable preceding in inner class Checker Checking for no duplicates is easy with order: Compare to preceding Checking for no duplicates is harder without order: Store all combinations, and search among stored Note: Lexicographic order was imposed on purpose to ease testing. c 2013, T. Verhoeff @ TUE.NL 6/27 Software Construction: Lecture 11
How to Organize GUI Code Separation of Concerns (decoupling): Problem-related data: Model E.g.: Abstract (mathematical) Kakuro puzzle state: cell contents Look, custom graphical output: View E.g.: Visualization of Kakuro puzzle state Feel, custom input handling: Control E.g.: Handle menu items, mouse clicks in cells, etc. c 2013, T. Verhoeff @ TUE.NL 7/27 Software Construction: Lecture 11
Model View Controller (MVC) Architecture Controller UI events User <<interacts>> Legend direct dependency, use, call commands commands queries View View View indirect dependency, callback Model change events c 2013, T. Verhoeff @ TUE.NL 8/27 Software Construction: Lecture 11
Menus and File Choosers See tutorial under Downloads For common aspects of buttons and menu items, see Eck Ch.13.3 Action and AbstractAction c 2013, T. Verhoeff @ TUE.NL 9/27 Software Construction: Lecture 11
Graphics in Java using Swing A component paints itself via its paintcomponent(graphics g). This method is called automatically whenever needed. (It is called by paint(), which itself is a callback method.) Via repaint(), the application can request a paint() call. There is no guarantee when this is request will be honored. Multiple repaint requests may get merged into one update. Override paintcomponent() to replace the default paint behavior. The new definition must first call super.paintcomponent(g). Graphics g is used for drawing: g.drawxxx(...). JFrame uses paint() instead of paintcomponent(). However, it is not recommended to override its paint() method. Instead, draw on a component (like a JPanel) inside the frame. c 2013, T. Verhoeff @ TUE.NL 10/27 Software Construction: Lecture 11
Graphics in Java using Swing There are various ways to show application-specific graphics. 1. paintcomponent() redraws the graphics from scratch. con pro Everything must be redrawn, in every call. Can be slow. Needs to store data to redraw the graphics. No need to undraw : easy to delete something. Terminology: Graphics shows a view of an abstract model. 2. Draw in a buffer and show it by paintcomponent(). con pro Must set up buffer; must undraw to delete something. No need to redraw everything; only draw the changes. Example: GraphicsExample, takes approach 1 c 2013, T. Verhoeff @ TUE.NL 11/27 Software Construction: Lecture 11
Simple Graphics on a JPanel in NetBeans 1. In Design mode, right-click on the JPanel, select Customize Code 2. Under Initialization code change default code custom creation jpanel1 = new javax.swing.jpanel(); jpanel1 = new javax.swing.jpanel() { @Override public void paintcomponent(graphics g) { super.paintcomponent(g); paintpanel1(this, g); } } ; 3. In Source mode, add the following code to the frame: private void paintpanel1(javax.swing.jpanel p, Graphics g) {... } c 2013, T. Verhoeff @ TUE.NL 12/27 Software Construction: Lecture 11
Complex Graphics on a JPanel in NetBeans 1. Create a new JPanel descendant via File > New File... > Swing GUI Forms > JPanel Form name it XxxPanel and put it in the gui package. This adds a.java and related.form file to the project. NetBeans controls the Generated Code. 2. In Design mode of the main frame, drag-and-drop XxxPanel from the NetBeans Navigator onto your JFrame. 3. In Source mode of the panel, define the data needed to render the view, and override void paintcomponent(). c 2013, T. Verhoeff @ TUE.NL 13/27 Software Construction: Lecture 11
Undo-Redo Facility User invokes commands via GUI, changing data in models: Do Various degrees of Undo : Undo last (one level of undo) Limited undo (fixed number of levels) Arbitrary undo (limited by memory only) Various degrees of Redo : Not available Redo last (one level of redo) Limited redo (fixed number of levels) Arbitrary redo (limited by memory only) c 2013, T. Verhoeff @ TUE.NL 14/27 Software Construction: Lecture 11
Implement Undo-Redo by Storing Full Model States Store full model state before executing an undoable command Organize stored states as a stack Undo: Pop state from undo stack; restore model to popped state Redo: Use a second stack for undone model states Model needs ability to clone, and to restore a given state Pro: Simple Con: Performance loss when state is large c 2013, T. Verhoeff @ TUE.NL 15/27 Software Construction: Lecture 11
Implement Undo-Redo by Storing State-changing Commands User invokes commands via GUI, changing data in models: Do. These commands can be executed right away, by calling methods. It can be useful to have the ability to call these methods later : command queuing, transaction recovery, redo after undo. Undo : use a stack of done commands. Redo : use a second stack of undone-but-redoable commands. Pro: Stores only information to change state ( deltas ) Con: Needs objects to store commands (Command pattern) c 2013, T. Verhoeff @ TUE.NL 16/27 Software Construction: Lecture 11
Command Design Pattern Command class encapsulates all data to call a method elsewhere: which method to call, including in which object: Receiver which actual parameters to supply as arguments what to do with the return value Offers method to execute the call, optionally to undo the call A command object can be created by one class: Client stored in another class executed (and optionally undone) in yet another class: Invoker Command Design Pattern decouples call data and call moment. c 2013, T. Verhoeff @ TUE.NL 17/27 Software Construction: Lecture 11
Command Design Pattern: Class Diagram Client Invoker «interface» Command execute() undo() Receiver Concrete Command Concrete Command' action() execute() undo() execute() undo() c 2013, T. Verhoeff @ TUE.NL 18/27 Software Construction: Lecture 11
Command Design Pattern: Sequence Diagram : Client r: Receiver : Invoker create(r) c: Concrete Command setcommand(c) action() execute() c 2013, T. Verhoeff @ TUE.NL 19/27 Software Construction: Lecture 11
Undo via Command Pattern Provide each concrete Command with an undo method to revert the effect of execute. It can be necessary to equip the model with extra operations. Introduce a command stack : Stack<Command> undostack; The Controller creates Command objects, executes them, and pushes them onto undostack. Undo is implemented by popping a command from undostack, and invoking its undo method. See: example NetBeans project CommandPattern c 2013, T. Verhoeff @ TUE.NL 20/27 Software Construction: Lecture 11
Redo via Command Pattern Introduce another command stack : Stack<Command> redostack; The Controller creates Command objects, executes them, pushes them on undostack, and clears redostack. Undo is implemented by popping a command from the stack, invoking its undo method, and pushing it onto redostack. Redo is implemented by popping a command from redostack, invoking its execute method, and pushing it onto undostack. Concern: Ensure precondition of method executed by a command c 2013, T. Verhoeff @ TUE.NL 21/27 Software Construction: Lecture 11
Encapsulate Undo-Redo Facilities In example CommandPattern: Undo incorporated into Controller Better: Encapsulate Undo-Redo in separate class Representation: Stack<Command> undostack, redostack Preserve rep invariant for undostack and redostack Commands on undostack have been executed and can be undone Commands on redostack are unexecuted and can be re-executed Operations: did(command), undo(), redo(), etc. c 2013, T. Verhoeff @ TUE.NL 22/27 Software Construction: Lecture 11
Compound Commands A compound command consists of a sequence of commands. Contained commands can be compound: nesting, hierarchy It can be defined via the Composite Pattern. It does not need a receiver. It provides an add method to add commands. Its execute method executes the contained commands, in order. Its undo method undoes the contained commands, in reverse order. c 2013, T. Verhoeff @ TUE.NL 23/27 Software Construction: Lecture 11
Compound Command Design Pattern: Class Diagram Client Invoker «interface» Command execute() undo() 0..* list { ordered } Receiver action() Concrete Command execute() undo() Concrete Command' execute() undo() Compound Command execute() undo() 0..1 c 2013, T. Verhoeff @ TUE.NL 24/27 Software Construction: Lecture 11
Backtracking Speculative technique to search through a state space. Recursive implementation for Loop Puzzle Assistant: 1. Find an undetermined edge e. 2. For each possible edge state s, set e to s, apply strategies, and if state still valid, solve remainder recursively. Implementation variations: Copy entire state (onto the stack) for each recursive call. Undo is automatic by falling back to earlier stored state. Maintain state in global variable, and modify it: do-undo. Here, the Command Pattern can be used. c 2013, T. Verhoeff @ TUE.NL 25/27 Software Construction: Lecture 11
Homework Series 11 Inspect peach 3 feedback on Simple Kakuro Helper 2 Modify CommandPattern demo program to include Redo Modify Kakuro Puzzle Assistant to include Undo/Redo c 2013, T. Verhoeff @ TUE.NL 26/27 Software Construction: Lecture 11
Summary Also see Wikipedia: en.wikipedia.org/wiki/command_pattern The Command design pattern provides a way of capturing the data needed to call a method later elsewhere ( Do facility). Can be extended to offer an Undo facility, optionally with Redo. See example NetBeans project CommandPattern. Backtracking can be based on a Do-Undo mechanism. c 2013, T. Verhoeff @ TUE.NL 27/27 Software Construction: Lecture 11