500 likes | 661 Views
Programmering af Store OO Sys. Programmeringsprojekt. Henrik Bærbak Christensen Department of Computer Science University of Aarhus Denmark. Assignment 4a. Integrate your variants with a GUI. Based on MiniDraw. MiniDraw is a JHotDraw clone made for supporting board games mainly
E N D
Programmering af Store OO Sys.Programmeringsprojekt Henrik Bærbak Christensen Department of Computer Science University of Aarhus Denmark
Assignment 4a • Integrate your variants with a GUI. Henrik Bærbak Christensen
Based on MiniDraw • MiniDraw is a JHotDraw clone made for • supporting board games mainly • cut down detail for teaching purposes • one day convert to C# • MiniDraw is black-box whereas JHotDraw is white-box • Main JHotDraw architecture remains • Model-View-Controller • Drawing-DrawingView-Tool Henrik Bærbak Christensen
MiniDraw: Static View Henrik Bærbak Christensen
MiniDraw: Patterns Object Server View Controller Model Henrik Bærbak Christensen
Default Implementations • Most MiniDraw roles have default implementations: • Interface X has default implementation StandardX • Drawing -> StandardDrawing • There are also some partial implementations: • Interface X has partial implementation AbstractX • Tool -> AbstractTool Henrik Bærbak Christensen
MiniDraw: Tool Interaction • Basic paradigm: Direct Manipulation • [Demo: b3] Henrik Bærbak Christensen
View -> Controller interaction • Mouse events do hit the JPanel, but MiniDraw simply delegate to its active tool... Henrik Bærbak Christensen
MiniDraw: Dynamic View • Scenario: User drags image figure around. • Then a DragTracker is the active tool: Henrik Bærbak Christensen
MiniDraw: Graphics rendering • But how does the view get repainted? • Double observer chain • Figure notifies drawing notifies drawing view. Henrik Bærbak Christensen
HotTargui GUI • Three layers MiniDraw HotTargui: HotSpots for figures, tools, drawing and drawingview. Your production code Henrik Bærbak Christensen
Central Protocol • The protocol between GUI and Domain: • GUI Domain • Facade pattern (Game interface) • A tool translate mouse clicks to proper method • UnitMoveTool: ‘move’ or ‘buy’ • TurnTribeCardTool: turnCard • etc. • GUI Domain • Observer pattern (GameListener interface) • Drawing and DrawingView must react upon events • updateTile • updatePlayer (note: has been renamed!!!) • etc. Henrik Bærbak Christensen
Example: Moving Units • Moving units means invoking game’s “move” • The Drawing update is brute-force! • erase all – rebuild all – repaint! Henrik Bærbak Christensen
Example: Moving Units Facade Observer GUI Domain GUI Henrik Bærbak Christensen
Challenges in 4a • Comprehension and overview • of a somewhat larger system • Using pattern protocols • to properly make subsystems collaborate • Making new tool • use the state pattern to make a ‘GameStateTool’ that delegate to proper tool depending on game state... Henrik Bærbak Christensen
Assignment 4b • Make it distributed! • Or – rather – ensure that the distributed architecture will work... Henrik Bærbak Christensen
DistTargui – Architecture 1 Targui Server Where are components deployed? What is communicated? client 2 client 1 Henrik Bærbak Christensen
DistTargui – Architecture 2 Where are components deployed? What is communicated? host client Henrik Bærbak Christensen
DistTargui – Architecture 3 Where are components deployed? What is communicated? peer peer Henrik Bærbak Christensen
Next Step? • The question posed here is: How do I proceed make a reliable distributed HotTargui when I want to keep focus and take small steps? And I do not know which of the three architecture proposals is the better one? Henrik Bærbak Christensen
Model 1: • Model 1: • I begin pulling my HotTargui implementation into 1000 pieces – forgetting all about the JUnit test cases • I pump socket communication and/or RMI into the code • ... and hope I some day will be able to assemble it again. Henrik Bærbak Christensen
Model 2: • Model 2: • I experiment safely in a realistic sand-box that I denote architectural prototypes... Henrik Bærbak Christensen
[Jump to the AP slides here!] Henrik Bærbak Christensen
APs in Practice • How can I use APs in HotTargui? • I will exemplify by a project I defined and ran from my “parallel” universe: Backgammon. • Same problem statement: • Given large Backgammon production code – how do I refactor it to become distributed. Henrik Bærbak Christensen
Refactoring Process DistHotTargui HotTargui HT-AP1 ... HT-AP2 HT-APn Henrik Bærbak Christensen
The Challenge Facade Observer GUI Domain GUI Client Client Server Henrik Bærbak Christensen
Conclusion • We need to experiment with • Java Remote Method Invocation (RMI) for the client server protocol: • Facade pattern • Observer pattern • But do not want to fiddle with all the HotTargui code (Backgammon code) Henrik Bærbak Christensen
Harvesting • The main observation: • The domain code and GUI code are irrelevant! • The only interesting aspect is the connectors The flow of control and data (the protocol) over the network between the client and the server! Henrik Bærbak Christensen
Harvesting • Thus we can simply make an AP that only is concerned with the protocol! • why not simply write method names invocated on standard output? • But • we have to be sure our AP is faithful to the original call sequence... Henrik Bærbak Christensen
For real systems: Use a trace tool • JSeq can make sequence diagrams in SVG and Argo UML – but I actually like text. backgammon.domain.ConfigurableGame.newGame backgammon.domain.AbstractGame.newGame backgammon.domain.ConfigurableGame.getBoard backgammon.domain.strategies.StandardBoard.reset backgammon.domain.strategies.StandardBoard.putCheckerOntoBoard (x 8) backgammon.domain.Color.getSign backgammon.domain.strategies.AbstractBoard._notify backgammon.domain.ConfigurableGame$LocalBoardListener.update backgammon.view.AbstractBackgammonApplication.boardChange Henrik Bærbak Christensen
Conclusion: Harvesting • Harvesting dictate that we • extract the minimal architecture system that faithfully mimics the architectural behaviour of focus of experimentation in the original system • that is we need • just to be able to send information between GUI and Game instance • about checkers on board, die values, movement, next turn, etc. Henrik Bærbak Christensen
Step 0 • Make a AP in new package: archproto. • initiate main program to simulate GUI manipulations • move Game and GameListener to AP • slimming the interface to just the bare bones • changing the package assignment • Experience: • Location and Color must be moved as well • But they can simply be serializable objects (value passing) in the final architecture • Success: compile and execute Henrik Bærbak Christensen
Step 0 package archproto; public class ArchProto { public static void main(String[] args) { GUI gui = new GUI(); gui.simulateUserClickingDie(); } } class GUI { public void simulateUserClickingDie() { System.out.println("User clicking die..."); } } Henrik Bærbak Christensen
Step 1: Analysing dice rolling • What is the protocol between GUI and Domain when user clicks a die? JSeq gives the answer. backgammon.view.tools.DieRollTool.mouseDown backgammon.view.AbstractBackgammonApplication.getGame backgammon.domain.ConfigurableGame.nextTurn ... backgammon.domain.ConfigurableGame.fireDieRollChange backgammon.view.AbstractBackgammonApplication.diceRolled backgammon.domain.ConfigurableGame.diceThrown backgammon.domain.ConfigurableGame.getRolledDiceManager backgammon.domain.strategies.StandardRolledDiceManager.diceThrown backgammon.view.AbstractBackgammonApplication.getEditor backgammon.view.figures.DieFigure.<init> (x 2) , backgammon.view.tools.GameStateTool.mouseUp Henrik Bærbak Christensen
Step 1: Scenario replication • Create stub classes for the two important architectural run-time components • backgammon.view.AbstractBackgammonApplication GUI • backgammon.domain.ConfigurableGame APGame • Write just enough stub code to perform the scenario architecturally faithful (Rev. 180) Henrik Bærbak Christensen
AP harvesting literally means harvesting - you take (very small!) pieces of the original code. All the game listener registration and handling code as cut’n’pasted from the original project. Scenario code simply ensures the proper sequencing of method call. Step 1: Implementation class APGame implements Game { public APGame() { gameListener = new ArrayList(); } public void nextTurn() { System.out.println("backgammon.domain.ConfigurableGame.nextTurn " ); fireDieRollChange(); } public int[] diceThrown() { System.out.println("backgammon.domain.ConfigurableGame.diceThrown"); return null; } public void newGame() {} public boolean move(Location from, Location to, Color s) { return true; } public Color getPlayerInTurn() { return Color.RED; } public int getNumberOfMovesLeft() { return 1; } public int[] diceValuesLeft() { return null; } public Color winner() { return Color.RED; } // code below directly taken from main project List gameListener; public void addGameListener(GameListener gl) { gameListener.add(gl); } public void fireDieRollChange() { System.out.println("backgammon.domain.ConfigurableGame.fireDieRollChange"); Iterator i = gameListener.iterator(); while (i.hasNext()) { GameListener gl = (GameListener) i.next(); gl.diceRolled(); } } } Henrik Bærbak Christensen
GUI code Step 1: Implementation class GUI implements GameListener { private Game game; public GUI(Game game) { this.game = game; } public void simulateUserClickingDie() { System.out.println("User clicking die..."); /* backgammon.view.AbstractBackgammonApplication.getGame backgammon.domain.ConfigurableGame.nextTurn */ game.nextTurn(); } public void boardChange() { System.out.println( "Call back: Board changed..." ); } public void diceRolled() { System.out.println( "backgammon.view.AbstractBackgammonApplication.diceRolled" ); int [] thedice = game.diceThrown(); } } Henrik Bærbak Christensen
And the main public class ArchProto { public static void main(String[] args) { Game game = new APGame(); GUI gui = new GUI(game); game.addGameListener( gui ); gui.simulateUserClickingDie(); } } Step 1: Implementation Henrik Bærbak Christensen
Step 1: Conclusion • What do we have? • AP version 1 [Harvesting] • Effort: About 4 hours including • installing JSeq • analysing sequences • writing slides for this presentation • writing the code • LOC: 75 lines including blanks • Files: 1 file • Behaviour: Architecturally mimics user clicking die correct. • Next step • A: Add more scenarios or • B: Make this scenario distributed ! Henrik Bærbak Christensen
Step 2: RMI-ing • RMI contains a long list of tedious setting up: • Remote objects must implement interface Remote • adding ‘throws RemoteException’ to all methods that are direct remote method invocations • either throwing remote exceptions or handling them in all methods that transitively call remote methods • value objects must be ‘Serializable’ (Color and Location). • Create a server that binds the domain object • Create a client create gui and lookup domain object • run with rmiregistry and proper policy file • (and make your firewall shut up!) Henrik Bærbak Christensen
Step 2: Result Only view objects Only domain objects Henrik Bærbak Christensen
Step 2: Conclusion • What do we have? • AP version 2 [Increment] • Effort: About 1.5 hours • modularisation (one class per file) • RMI introduced • server programs • build (policy files, run targets) • [Had similar code setup to “look at”] • LOC: ~500 lines (16,4 KB source code) • Files: 9 files • Behaviour: Die click over RMI on localhost Henrik Bærbak Christensen
Step 3: Just curious • Does it also work over LAN? • Same AP but different parameter sets • After 2 hours it still does not work • Finally made it work [Rev 194] • problem related to setting the codebase property • Conclusion: • A: Back to the books / tutorials on RMI and code bases • B: A lot of code experiments have been conducted in a safe ‘sandbox’ instead of messing up the real backgammon project !!! Henrik Bærbak Christensen
Next iterations • Plausible steps: • Add the ‘user move checker’ scenario • Testing two concurrent gui clients (concurrency issues !) • Reduce cross-wire communication Henrik Bærbak Christensen
Retrofitting • Retrofitting is the last step • based on the knowledge gained • technological (RMI, setup, TCP, or whatever you use) • improved separation between domain and gui • changes to lessen communication between the two • design flaws, like logic in gui that should be in domain, etc. • the real backgammon project is • refactored design- and architecture wise • distribution introduced Henrik Bærbak Christensen
Recap • The basic advantages of APs • small code base ease overview during experimentation • no fear of introducing defects caused by “long tracking nasty defects” sessions where a lot of code is often added/removed to gain insight • experiment cheaply with architectural changes • new problems arising during retrofitting should again be tested and solved in the AP Henrik Bærbak Christensen
Couple of RMI hints • Some of my own experiences • read the tutorial carefully, there are a lot of steps involved and lot of detail to pay attention to • when defect hunting across two machines be careful to base your conclusions on the right basis !!! • keep the two code bases in sync at all times • rebuild everything from scratch often • kill and rerun the rmi registry • keep an eye on concurrency (“syncronized”) • “change the code on machine A and run on machine B does not change anything ” Henrik Bærbak Christensen
Back to Assignment 4b • If you want to take a shot at it I advice • 1) Analyse the MoveUnits scenario call sequence • 2) Make a simple AP for this scenario only • for instance using std output for method calls • but ensure that the proper objects are in play: StandardTile, etc. • 3) RMI it • be sure to run not only on localhost • 4) Stress it • two clients trying to drown the server • to find concurrency issues. Henrik Bærbak Christensen