Architectural Middleware Eric M. Dashofy CSCI 578 at the University of Southern California March 24, 2011 Copyright © Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy. All rights reserved. Software Architecture: Foundations, Theory, and Practice Review: From Architecture to Design to Implementation Problem Space Solution Space A D I Software Architecture: Foundations, Theory, and Practice Mapping Architecture to Implementation There is a community who advocates Model-Driven Architecture or Model-Driven Development Ideal: fully generate implementations from architectural models This ideal is rarely feasible Models are necessarily abstractions of systems We can take the modeled parts and map those, especially with domain knowledge Limit/prevent architectural erosion A I Software Architecture: Foundations, Theory, and Practice The Gap to Bridge Architecture Concepts Application: Components, connectors, interfaces (at component level), high-level behaviors Style: Connection rules, communication rules, concurrency rules… Programming language concepts Functions, conditionals, variables, structures, assignments, classes and objects… Operating system concepts Threads, mutexes, sockets, files and filesystems, IPC mechanisms… Software Architecture: Foundations, Theory, and Practice The Key Question How do we take architectural concepts and realize them using the elements that we have in the implementation world? Software Architecture: Foundations, Theory, and Practice A Discussion About Mapping Architectural Concept Implementation Concepts Components ? Connectors ? Interfaces ? Configurations ? Design Rationale ? Behavior ? Concurrency Rules ? NFPs ? Software Architecture: Foundations, Theory, and Practice A Discussion About Mapping Architectural Concept Implementation Concepts Components Classes, packages, modules, … Connectors Software buses, middleware; others? Interfaces APIs, protocols Configurations Module dependencies, possibly supported by reflection Design Rationale Comments, documentation Behavior Translated algorithms Concurrency Rules Design patterns using OS-level concurrency constructs NFPs Verified separately through testing, inspections, etc. Software Architecture: Foundations, Theory, and Practice Middleware, Frameworks, and Mappings (oh my!) Middleware has a lot of broad definitions My definition: any software that sits in between your application and your Programming Language/OS to provide services not provided by PL/OS Architectural frameworks are a special type Application of middleware “Middleware” Programming Language & OS Software Architecture: Foundations, Theory, and Practice So what’s the difference? There’s no clear, bright line Middleware is designed based on services Architectural concerns are secondary Frameworks are designed based on architectural styles and patterns Services are secondary Software Architecture: Foundations, Theory, and Practice Traditional Middleware Traditional middleware may be based on services, but it induces an architectural style (Di Nitto and Rosenblum) Consider CORBA Services: Network transparency, language transparency, OS transparency Induced properties: (primarily) synchronous requestresponse point-to-point communication, hiding of network properties, OO-style topologies Software Architecture: Foundations, Theory, and Practice Middleware is Everywhere Software reuse is alive and well, but perhaps thriving most at the middleware layer Software systems today are increasingly built on growing stacks of underlying middleware – whether we call it “Middleware” “Frameworks” “Component Libraries” “Toolkits” All of it has architectural implications Who is really designing your software? Software Architecture: Foundations, Theory, and Practice Let’s Discuss some Middleware “Distributed Systems Middleware” DCE, Courier, CORBA, (D)COM(+), RMI, Web Services Message-Oriented Middleware MQ Series, MSMQ, JMS implementations “Enterprise Service Buses” Web Application Middleware Server-side: JSP, Spring, JSF, Rich Faces, Rails, Grails, Pylons, TurboGears Client-Side: YUI, JQuery, JQuery UI, Dojo, Prototype Software Architecture: Foundations, Theory, and Practice Architecture Frameworks Start from an architectural style (or specific architecture) Pipe-and-filter Web Services C2 Prism Myx Develop middleware that supports (not necessarily enforces) the constraints of the style, tailored to support Desirable NFPs Additional desirable properties/services Software Architecture: Foundations, Theory, and Practice A Tale of Four Frameworks Supporting the evolution of one system (ArchStudio) over four versions. Through a fundamental change in architectural style (C2Myx) Three research-based (Lightweight C2, Flexible C2, Myx) One off the shelf (OSGi) Software Architecture: Foundations, Theory, and Practice Review: C2 Style Software Architecture: Foundations, Theory, and Practice Framework #1: Lightweight C2 Framework 16 classes, 3000 lines of code Components & connectors extend abstract base classes Concurrency, queuing handled at individual comp/conn level Messages are request or notification objects 16 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Lightweight C2 Framework Advantages Simple, small Control concurrency (or not) at brick level Disadvantages Fixed top, bottom interfaces Potential for deadlock Single-inheritance limitation of Java Software Architecture: Foundations, Theory, and Practice ArchStudio 2 Software Architecture: Foundations, Theory, and Practice Framework #2: Flexible C2 Framework 73 classes, 8500 lines of code Uses interfaces rather than base classes Threading policy for application is pluggable Message queuing policy is also pluggable 19 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Framework #2: Flexible C2 Framework 20 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Flexible C2 Framework Advantages Ability to implement and change out message queuing, threading policies …but it turned out not to matter However, it did enable the “Steppable Engine” Reduced dependency on base classes Flexible interfaces permit non-C2-topologies Synchronous call support Fully serializable control interface Disadvantages Complexity Performance Certain threading policies (e.g., shepherd threads) difficult to implement Software Architecture: Foundations, Theory, and Practice ArchStudio 3 Software Architecture: Foundations, Theory, and Practice The Myx Style Combines useful qualities of C2, Weaves (C2) All communication through interfaces (C2) No assumption of shared state (C2) Substrate Independence Top, bottom interfaces, enforced layering (C2) Asynchronous eventing (Weaves) Synchronous invocations (Weaves) Connectors create threading policy Relatively hard to deadlock Software Architecture: Foundations, Theory, and Practice Myx: Synchronous Patterns Direct Call With Proxy Software Architecture: Foundations, Theory, and Practice Myx: Asynchronous Patterns Downward Event Upward Event Software Architecture: Foundations, Theory, and Practice Myx: Nifty Patterns Software Architecture: Foundations, Theory, and Practice Framework #3: Myx Framework 62 classes, 2600 lines of code Minimal required support for brick classes Pluggable brick loaders Framework does not get involved in any inter-brick communication 27 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Myx Framework Advantages Performance: all communication between bricks direct Library of reusable connectors Pluggable brick loaders permit operation in different contexts This becomes important later Can support non-Myx topologies Fully serializable control interface Flexible dynamism Disadvantages Complexity (sorta) Monitorability Software Architecture: Foundations, Theory, and Practice ArchStudio 4 Software Architecture: Foundations, Theory, and Practice Worlds are Mixing! OSGi and Myx Myx was developed as a general-purpose architectural style But was specifically built to support ArchStudio 4 ArchStudio 4 was going to be built in Eclipse Considered AS3+Myx but rejected Eclipse has its own framework (OSGi), inducing a style Software Architecture: Foundations, Theory, and Practice Simplified view of OSGi Bundle class Bundle class Exposed Pkgs class class class class Exposed Pkgs class class Software Architecture: Foundations, Theory, and Practice Simplified view of OSGi Bundle class Bundle class Exposed Pkgs class class class class Exposed Pkgs class class Software Architecture: Foundations, Theory, and Practice Simplified view of OSGi Bundle class Bundle class Exposed Pkgs class class class class Exposed Pkgs class class Software Architecture: Foundations, Theory, and Practice Simplified view of OSGi Bundle class Bundle class Exposed Pkgs class class class class Exposed Pkgs class class Software Architecture: Foundations, Theory, and Practice OSGi Why? Provide a system with deployable and undeployable units With well-known, manageable lifecycles Permit lazy loading of bundles Permit dynamism In a limited way Software Architecture: Foundations, Theory, and Practice Integration Attempt #1 (AS4) Bundle (all exposed) Software Architecture: Foundations, Theory, and Practice Handling the Master of the Universe problem Eclipse framework Instantiates and controls ArchEdit Eclipse View Eclipse Layer communication xArchADT ArchEdit Myx Layer Instantiates and controls myx.fw architecture implementation framework Software Architecture: Foundations, Theory, and Practice Approach #1: Evaluation (+) “Hatting” solution solves MOU problem (-) But it’s a dirty dirty hack (+) Requires no Eclipse-specific code in Myx framework (+) Otherwise works OK with Eclipse and permits deploy/undeploy through the Eclipse Update system (-) But the unit of deployment is the whole app! Software Architecture: Foundations, Theory, and Practice Integration Attempt #2 (AS5) “Core” Bundle “Core” Bundle class class class “Common” Bundle class class class “Common” Bundle class class Software Architecture: Foundations, Theory, and Practice Integration Attempt #2 (AS5) “Core” Bundle “Core” Bundle class class class “Common” Bundle class class class “Common” Bundle class class Software Architecture: Foundations, Theory, and Practice Approach #2: Evaluation (+) “Hatting” solution still solves MOU problem (-) But it’s still a dirty dirty hack (+) Eclipse-specific code in Myx framework can be written entirely as extensions in a separate bundle (+) Deploy/undeploy at the level of an individual component/connector Software Architecture: Foundations, Theory, and Practice Takeaways Middleware is Everywhere and Everyware May have more influence on your architecture than you do! Beware middleware that gives you enticing services, but does not improve your cognitive control over your system Frameworks are tricky to build But well-built frameworks can substantially reduce the burden on app developers Concurrency is an area where this can be especially true Software Architecture: Foundations, Theory, and Practice Takeaways (cont.) Efficient frameworks stay out of the way of intercomponent communication Component granularity matters for efficiency The difficulty in elegantly merging an architecture framework with existing middleware is very high This may be the biggest barrier to the adoption of strong architectural styles. Software Architecture: Foundations, Theory, and Practice BACKUP CHARTS Software Architecture: Foundations, Theory, and Practice Implementing Lunar Lander in C2 Framework: Lightweight C2 framework Each component has its own thread of control Components receive requests or notifications and respond with new ones Message routing follows C2 rules This is a real-time, clock-driven version of Lunar Lander 45 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Implementing Lunar Lander in C2 (cont’d) First: Clock component Sends out a ‘tick’ notification periodically Does not respond to any messages 46 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice import c2.framework.*; Clock Component public class Clock extends ComponentThread { public Clock() { super.create("clock", FIFOPort.class); } public void start() { super.start(); Thread clockThread = new Thread() { public void run() { // Repeat while the application runs while (true) { // Wait for five seconds try { Thread.sleep(5000); } catch (InterruptedException ie) {} //Send out a tick notification Notification n = new Notification("clockTick"); send(n); } } }; 47 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice import c2.framework.*; Clock Component public class Clock extends ComponentThread{ public Clock(){ super.create("clock", FIFOPort.class); } public void start(){ clockThread.start(); super.start(); } Thread clockThread = new Thread(){ void handle (Notification n) { publicprotected void run(){ // This does notruns handle notifications //Repeat whilecomponent the application } while(true){ //Wait for five seconds protected void handle (Request r) { try{ // This component does not handle requests Thread.sleep(5000); }} }catch(InterruptedException ie){} //Send out a tick notification Notification n = new Notification("clockTick"); send(n); } } }; 48 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Implementing Lunar Lander in C2 Second: GameState Component Receives request to update internal state Emits notifications of new game state on request or when state changes Does NOT compute new state Just a data store 49 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice GameState Component import c2.framework.*; public class GameState extends ComponentThread{ public GameState() { super.create("gameState", FIFOPort.class); } // Internal game state and initial values int altitude = 1000; int fuel = 500; int velocity = 70; int time = 0; int burnRate = 0; boolean landedSafely = false; 50 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice protected void handle (Request r) { GameState Component if (r.name().equals("updateGameState")) { // Update the internal game state if (r.hasParameter("altitude")) { import c2.framework.*; this.altitude = ((Integer)r.getParameter("altitude")).intValue(); } public class GameState extends ComponentThread{ if (r.hasParameter("fuel")) { this.fuel = ((Integer)r.getParameter("fuel")).intValue(); public GameState(){ } super.create("gameState", FIFOPort.class); if (r.hasParameter("velocity")) { } this.velocity = ((Integer)r.getParameter("velocity")).intValue(); } //Internal game state and initial values if (r.hasParameter("time")) { int altitude = 1000; = ((Integer)r.getParameter("time")).intValue(); int fuel this.time = 500; } int velocity = 70; if =(r.hasParameter("burnRate")) { int time 0; this.burnRate = ((Integer)r.getParameter("burnRate")).intValue(); int burnRate = 0; boolean} landedSafely = false; if (r.hasParameter("landedSafely")) { this.landedSafely = ((Boolean)r.getParameter("landedSafely")) .booleanValue(); } // Send out the updated game state Notification n = createStateNotification(); send(n); 51 } Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice GameState Component (r.name().equals("getGameState")) { protected else void if handle(Request r){ //If a component requests the game state if(r.name().equals("updateGameState")){ //without updating send out the state //Update the internal gameit, state if(r.hasParameter("altitude")){ import c2.framework.*; Notification n = createStateNotification(); this.altitude = ((Integer)r.getParameter("altitude")).intValue(); send(n); } public class GameState extends ComponentThread{ } if(r.hasParameter("fuel")){ } this.fuel = ((Integer)r.getParameter("fuel")).intValue(); public GameState(){ } super.create("gameState", FIFOPort.class); protected Notification createStateNotification() { if(r.hasParameter("velocity")){ } // Create a =new notification comprising the this.velocity ((Integer)r.getParameter("velocity")).intValue(); // current game state } //Internal game state and initial values if(r.hasParameter("time")){ int altitude = 1000; Notification n = new Notification("gameState"); this.time = ((Integer)r.getParameter("time")).intValue(); int fuel = 500; n.addParameter("altitude", altitude); } int velocity = 70; n.addParameter("fuel", fuel); if(r.hasParameter("burnRate")){ int time = 0; n.addParameter("velocity", velocity); this.burnRate = ((Integer)r.getParameter("burnRate")).intValue(); int burnRate = 0; n.addParameter("time", time); boolean} landedSafely = false; n.addParameter("burnRate", burnRate); if(r.hasParameter("landedSafely")){ n.addParameter("landedSafely", landedSafely); this.landedSafely = ((Boolean)r.getParameter("landedSafely")) return n; .booleanValue(); } } protected void handlegame (Notification n) { //Send out the updated state // This component does not handle notifications Notification n = createStateNotification(); } send(n); 52 } } Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Implementing Lunar Lander in C2 Third: GameLogic Component Receives notifications of game state changes Receives clock ticks On clock tick notification, calculates new state and sends request up 53 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice GameLogic Component import c2.framework.*; public class GameLogic extends ComponentThread { public GameLogic() { super.create("gameLogic", FIFOPort.class); } // Game constants final int GRAVITY = 2; // Internal state values for computation int altitude = 0; int fuel = 0; int velocity = 0; int time = 0; int burnRate = 0; public void start() { super.start(); Request r = new Request("getGameState"); send(r); } 54 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice GameLogic Component protected void handle (Notification n) { if (n.name().equals("gameState")) { import c2.framework.*; if (n.hasParameter("altitude")) { this.altitude = public class GameLogic extends ComponentThread{ ((Integer)n.getParameter("altitude")).intValue(); public GameLogic(){ } super.create("gameLogic", FIFOPort.class); if (n.hasParameter("fuel")) { } this.fuel = ((Integer)n.getParameter("fuel")).intValue(); //Game constants } final int GRAVITY = 2; if (n.hasParameter("velocity")) { this.velocity = //Internal state values for computation ((Integer)n.getParameter("velocity")).intValue(); int altitude } = 0; int fuel = if 0; (n.hasParameter("time")) { int velocity this.time = 0; = int time = 0; ((Integer)n.getParameter("time")).intValue(); int burnRate } = 0; if (n.hasParameter("burnRate")) { public void start(){ this.burnRate = super.start(); ((Integer)n.getParameter("burnRate")).intValue(); Request r} = new Request("getGameState"); send(r); } } 55 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice GameLogic Component protected void handle(Notification n){ if(n.name().equals("gameState")){ else if if(n.hasParameter("altitude")){ (n.name().equals("clockTick")) { import c2.framework.*; // Calculate new lander this.altitude = state values actualBurnRate = burnRate; ((Integer)n.getParameter("altitude")).intValue(); public int class GameLogic extends ComponentThread{ if (actualBurnRate > fuel) { } public GameLogic(){ //Ensure we don’t burnFIFOPort.class); more fuel than we have if(n.hasParameter("fuel")){ super.create("gameLogic", actualBurnRate this.fuel == fuel; } } ((Integer)n.getParameter("fuel")).intValue(); } //Game constants time + =1;2; if(n.hasParameter("velocity")){ finaltime int =GRAVITY altitudethis.velocity = altitude - =velocity; velocity =((Integer)n.getParameter("velocity")).intValue(); ((velocity GRAVITY) * 10 – //Internal state values for+ computation actualBurnRate * 2) / 10; } = 0; int altitude fuel ==if(n.hasParameter("time")){ fuel - actualBurnRate; int fuel 0; = int velocity this.time = 0; // Determine if we landed (safely) int time = 0; ((Integer)n.getParameter("time")).intValue(); boolean = false; } landedSafely int burnRate = 0; if (altitude <= 0) { if(n.hasParameter("burnRate")){ = 0; this.burnRate = public altitude void start(){ if (velocity <= 5) { ((Integer)n.getParameter("burnRate")).intValue(); super.start(); = true; RequestlandedSafely r} = new Request("getGameState"); } } send(r); } } 56 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice GameLogic Component protected void handle(Notification n){ if(n.name().equals("gameState")){ else if(n.name().equals("clockTick")){ if(n.hasParameter("altitude")){ import //Calculate c2.framework.*; new lander= state values this.altitude int actualBurnRate = burnRate; ((Integer)n.getParameter("altitude")).intValue(); public if(actualBurnRate class }GameLogic extends ComponentThread{ > fuel){ public //Ensure GameLogic(){ Request = newburn Request("updateGameState"); werdon’t more fuel than we have if(n.hasParameter("fuel")){ super.create("gameLogic", FIFOPort.class); r.addParameter("time", time); actualBurnRate this.fuel == fuel; } r.addParameter("altitude", altitude); } ((Integer)n.getParameter("fuel")).intValue(); r.addParameter("velocity", velocity); } //Game constants r.addParameter("fuel", fuel); time = time + 1; if(n.hasParameter("velocity")){ finalaltitude int r.addParameter("landedSafely", GRAVITY = 2; landedSafely); = altitude - =velocity; this.velocity send(r); velocity =((Integer)n.getParameter("velocity")).intValue(); ((velocity + GRAVITY) * 10 – //Internal state values for/ computation } } actualBurnRate * 2) 10; int altitude = 0; } fuel =if(n.hasParameter("time")){ fuel - actualBurnRate; int fuel = 0;this.time = int velocity = ((Integer)n.getParameter("time")).intValue(); 0; protected void handle (Request r) { //Determine if we landed (safely) int time = }0;landedSafely //This component does not handle requests boolean = false; int burnRate = 0;<= 0){ } if(altitude if(n.hasParameter("burnRate")){ } altitude = 0; this.burnRate = public if(velocity void start(){ <= 5){ ((Integer)n.getParameter("burnRate")).intValue(); super.start(); landedSafely = true; } Request r = new Request("getGameState"); } } send(r); } } 57 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Implementing Lunar Lander in C2 Fourth: GUI Component Reads burn rates from user and sends them up as requests Receives notifications of game state changes and formats them to console 58 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice GUI Component import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import c2.framework.*; public class GUI extends ComponentThread{ public GUI() { super.create("gui", FIFOPort.class); } public void start() { super.start(); Thread t = new Thread(){ public void run(){ processInput(); } }; t.start(); } 59 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice public void processInput() { System.out.println("Welcome to Lunar Lander"); try{ BufferedReader inputReader = new BufferedReader( new InputStreamReader(System.in)); import java.io.BufferedReader; import java.io.IOException; int burnRate = 0; import java.io.InputStreamReader; do { System.out.println("Enter burn rate or <0 to quit:"); import c2.framework.*; try { = inputReader.readLine(); public class GUI String extendsburnRateString ComponentThread{ public GUI(){ burnRate = Integer.parseInt(burnRateString); GUI Component super.create("gui", FIFOPort.class); Request r = new Request("updateGameState"); } r.addParameter("burnRate", burnRate); send(r); public void start(){ } super.start(); (NumberFormatException nfe) { Thread t = catch new Thread(){ burn rate."); public voidSystem.out.println("Invalid run(){ } processInput(); } while(burnRate >= 0); } inputReader.close(); }; } t.start(); catch (IOException ioe) { } ioe.printStackTrace(); } } 60 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice public void processInput(){ System.out.println("Welcome to Lunar Lander"); try{ protected void handle (Notification n) { BufferedReader inputReader = new BufferedReader( if (n.name().equals("gameState")) { import java.io.BufferedReader; new InputStreamReader(System.in)); importSystem.out.println(); java.io.IOException; System.out.println("New game state:"); import java.io.InputStreamReader; int burnRate = 0; do{ if (n.hasParameter("altitude")) { import c2.framework.*; System.out.println("Enter burn rate or <0 to quit:"); System.out.println(" Altitude: " + n.getParameter("altitude")); try{ } public class GUI String extendsburnRateString ComponentThread{ = inputReader.readLine(); if (n.hasParameter("fuel")) { public GUI(){ burnRate = Integer.parseInt(burnRateString); System.out.println(" Fuel: " + n.getParameter("fuel")); super.create("gui", FIFOPort.class); } } Request r = new Request("updateGameState"); if (n.hasParameter("velocity")) { r.addParameter("burnRate", burnRate); System.out.println(" Velocity: " + n.getParameter("velocity")); public void start(){ send(r); } super.start(); } if (n.hasParameter("time")) { Thread t = catch(NumberFormatException new Thread(){ nfe){ System.out.println(" Time: " + n.getParameter("time")); public voidSystem.out.println("Invalid run(){ burn rate."); } processInput(); } if (n.hasParameter("burnRate")) { } }while(burnRate >= 0); Burn rate: " + n.getParameter("burnRate")); }; System.out.println(" inputReader.close(); } t.start(); } } catch(IOException ioe){ ioe.printStackTrace(); } } GUI Component 61 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice public void processInput(){ System.out.println("Welcome to Lunar Lander"); try{ protectedifvoid handle(Notification n){ { (n.hasParameter("altitude")) BufferedReader inputReader = new BufferedReader( if(n.name().equals("gameState")){ int altitude = import java.io.BufferedReader; new InputStreamReader(System.in)); System.out.println(); ((Integer)n.getParameter("altitude")).intValue(); import java.io.IOException; System.out.println("New state:"); if 0)game { import java.io.InputStreamReader; int(altitude burnRate <= = 0; boolean landedSafely = do{ if(n.hasParameter("altitude")){ ((Boolean)n.getParameter("landedSafely")) import c2.framework.*; System.out.println("Enter burn rate or <0 to quit:"); System.out.println(" Altitude: " + n.getParameter("altitude")); .booleanValue(); try{ } if String (landedSafely) { public class GUI extends ComponentThread{ burnRateString = inputReader.readLine(); if(n.hasParameter("fuel")){ have landed safely."); public GUI(){ System.out.println("You burnRate = Integer.parseInt(burnRateString); System.out.println(" Fuel: " + n.getParameter("fuel")); } super.create("gui", FIFOPort.class); } else { } Request r = new Request("updateGameState"); if(n.hasParameter("velocity")){ System.out.println("You have crashed."); r.addParameter("burnRate", burnRate); System.out.println(" Velocity: " + n.getParameter("velocity")); } send(r); public void start(){ } System.exit(0); super.start(); } if(n.hasParameter("time")){ } Thread t = catch(NumberFormatException new Thread(){ nfe){ System.out.println(" Time: " + n.getParameter("time")); } public voidSystem.out.println("Invalid run(){ burn rate."); } processInput(); } } if(n.hasParameter("burnRate")){ }} }while(burnRate >= 0); Burn rate: " + n.getParameter("burnRate")); }; System.out.println(" inputReader.close(); }protected void handle (Request r) { t.start(); } //This component does not handle requests } catch(IOException ioe){ } ioe.printStackTrace(); } } } GUI Component 62 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice Implementing Lunar Lander in C2 Lastly, main program Instantiates and connects all elements of the system 63 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice import c2.framework.*; Main Program public class LunarLander { public static void main(String[] args) { // Create the Lunar Lander architecture Architecture lunarLander = new SimpleArchitecture("LunarLander"); // Create Component Component Component Component the components clock = new Clock(); gameState = new GameState(); gameLogic = new GameLogic(); gui = new GUI(); // Create the connectors Connector bus = new ConnectorThread("bus"); // Add the components and connectors to the architecture lunarLander.addComponent(clock); lunarLander.addComponent(gameState); lunarLander.addComponent(gameLogic); lunarLander.addComponent(gui); lunarLander.addConnector(bus); 64 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission. Software Architecture: Foundations, Theory, and Practice import c2.framework.*; Main Program public class LunarLander{ public static void main(String[] args){ //Create the Lunar Lander architecture Architecture lunarLander = new SimpleArchitecture("LunarLander"); // Create the welds (links) between components and // connectors //Create the components lunarLander.weld(clock, bus); Component clock = new Clock(); lunarLander.weld(gameState, bus); Component gameState = new GameState(); lunarLander.weld(bus, gameLogic); Component gameLogic = new GameLogic(); lunarLander.weld(bus, gui); Component gui = new GUI(); //Start the application //Create the connectors lunarLander.start(); Connector bus = new ConnectorThread("bus"); } } //Add the components and connectors to the architecture lunarLander.addComponent(clock); lunarLander.addComponent(gameState); lunarLander.addComponent(gameLogic); lunarLander.addComponent(gui); lunarLander.addConnector(bus); 65 Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.