Copyright © Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy. All rights reserved.
Architectural Middleware
Eric M. DashofyCSCI 578 at the University of Southern
CaliforniaMarch 24, 2011
Software Architecture: Foundations, Theory, and Practice
Review: From Architecture to Design to Implementation
ProblemSpace
SolutionSpace
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 abstractionsof systems We can take the modeled
parts and map those,especially with domainknowledge
A
I
Limit/prevent architectural erosion
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 frameworksare a special typeof middleware
Application
Programming Language & OS
“Middleware”
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
request-response 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, 8500lines of code
Uses interfacesrather than baseclasses
Threading policyfor applicationis pluggable
Message queuing policy isalso 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 anyinter-brickcommunication
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.
<<interface>>
IMyxRuntime
<<interface>>
IMyxBrick
<<interface>>
IMyxProvidedServiceProvider
<<interface>>
IMyxRequiredServiceProvider
1
*
1
1
<<interface>>
IMyxContainer
1
*
<<interface>>
IMyxBrickLoader
<<interface>>
IMyxBrickFactory
1
creates*
1
*
<<interface>>
IMyxLifecycleProcessor
+init()+begin()+end()+destroy()
1*
<<create>>
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
Bundleclass class
Exposed Pkgs
class class
Bundleclass class
Exposed Pkgs
class class
Software Architecture: Foundations, Theory, and Practice
Simplified view of OSGi
Bundleclass class
Exposed Pkgs
class class
Bundleclass class
Exposed Pkgs
class class
Software Architecture: Foundations, Theory, and Practice
Simplified view of OSGi
Bundleclass class
Exposed Pkgs
class class
Bundleclass class
Exposed Pkgs
class class
Software Architecture: Foundations, Theory, and Practice
Simplified view of OSGi
Bundleclass class
Exposed Pkgs
class class
Bundleclass 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
ArchEditxArchADT
ArchEditEclipseView
myx.fw architecture implementation framework
Eclipse framework
communication
Instantiates and controls
Instantiates and controlsEclipseLayer
MyxLayer
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
class class
“Common” Bundle
class class
“Core” Bundle
class class
“Common” Bundle
class class
Software Architecture: Foundations, Theory, and Practice
Integration Attempt #2 (AS5)
“Core” Bundle
class class
“Common” Bundle
class class
“Core” Bundle
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 developersConcurrency 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 inter-component 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: LightweightC2 framework
Each component has itsown thread of control
Components receiverequests or notificationsand respond with newones
Message routing followsC2 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
Clock Component
47
import c2.framework.*;
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); } } };
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
Clock Component
48
import c2.framework.*;
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); } } };
clockThread.start(); }
protected void handle (Notification n) { // This component does not handle notifications }
protected void handle (Request r) { // This component does not handle requests }}
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: GameStateComponent
Receives request to updateinternal state
Emits notifications of newgame state on requestor when state changes
Does NOT compute newstate 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
50
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;
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
51
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;
protected void handle (Request r) { if (r.name().equals("updateGameState")) { // Update the internal game state if (r.hasParameter("altitude")) { this.altitude = ((Integer)r.getParameter("altitude")).intValue(); } if (r.hasParameter("fuel")) { this.fuel = ((Integer)r.getParameter("fuel")).intValue(); } if (r.hasParameter("velocity")) { this.velocity = ((Integer)r.getParameter("velocity")).intValue(); } if (r.hasParameter("time")) { this.time = ((Integer)r.getParameter("time")).intValue(); } if (r.hasParameter("burnRate")) { this.burnRate = ((Integer)r.getParameter("burnRate")).intValue(); } if (r.hasParameter("landedSafely")) { this.landedSafely = ((Boolean)r.getParameter("landedSafely")) .booleanValue(); } // Send out the updated game state Notification n = createStateNotification(); send(n); }
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
52
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;
protected void handle(Request r){ if(r.name().equals("updateGameState")){ //Update the internal game state if(r.hasParameter("altitude")){ this.altitude = ((Integer)r.getParameter("altitude")).intValue(); } if(r.hasParameter("fuel")){ this.fuel = ((Integer)r.getParameter("fuel")).intValue(); } if(r.hasParameter("velocity")){ this.velocity = ((Integer)r.getParameter("velocity")).intValue(); } if(r.hasParameter("time")){ this.time = ((Integer)r.getParameter("time")).intValue(); } if(r.hasParameter("burnRate")){ this.burnRate = ((Integer)r.getParameter("burnRate")).intValue(); } if(r.hasParameter("landedSafely")){ this.landedSafely = ((Boolean)r.getParameter("landedSafely")) .booleanValue(); } //Send out the updated game state Notification n = createStateNotification(); send(n); }
else if (r.name().equals("getGameState")) { //If a component requests the game state //without updating it, send out the state
Notification n = createStateNotification(); send(n); } }
protected Notification createStateNotification() { // Create a new notification comprising the // current game state
Notification n = new Notification("gameState"); n.addParameter("altitude", altitude); n.addParameter("fuel", fuel); n.addParameter("velocity", velocity); n.addParameter("time", time); n.addParameter("burnRate", burnRate); n.addParameter("landedSafely", landedSafely); return n; } protected void handle (Notification n) { // This component does not handle notifications }}
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 stateand 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
54
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); }
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
55
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); }
protected void handle (Notification n) { if (n.name().equals("gameState")) { if (n.hasParameter("altitude")) { this.altitude = ((Integer)n.getParameter("altitude")).intValue(); } if (n.hasParameter("fuel")) { this.fuel = ((Integer)n.getParameter("fuel")).intValue(); } if (n.hasParameter("velocity")) { this.velocity = ((Integer)n.getParameter("velocity")).intValue(); } if (n.hasParameter("time")) { this.time = ((Integer)n.getParameter("time")).intValue(); } if (n.hasParameter("burnRate")) { this.burnRate = ((Integer)n.getParameter("burnRate")).intValue(); } }
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
56
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); }
protected void handle(Notification n){ if(n.name().equals("gameState")){ if(n.hasParameter("altitude")){ this.altitude = ((Integer)n.getParameter("altitude")).intValue(); } if(n.hasParameter("fuel")){ this.fuel = ((Integer)n.getParameter("fuel")).intValue(); } if(n.hasParameter("velocity")){ this.velocity = ((Integer)n.getParameter("velocity")).intValue(); } if(n.hasParameter("time")){ this.time = ((Integer)n.getParameter("time")).intValue(); } if(n.hasParameter("burnRate")){ this.burnRate = ((Integer)n.getParameter("burnRate")).intValue(); } }
else if (n.name().equals("clockTick")) { // Calculate new lander state values int actualBurnRate = burnRate; if (actualBurnRate > fuel) { //Ensure we don’t burn more fuel than we have actualBurnRate = fuel; }
time = time + 1; altitude = altitude - velocity; velocity = ((velocity + GRAVITY) * 10 – actualBurnRate * 2) / 10; fuel = fuel - actualBurnRate;
// Determine if we landed (safely) boolean landedSafely = false; if (altitude <= 0) { altitude = 0; if (velocity <= 5) { landedSafely = true; } }
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
57
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); }
protected void handle(Notification n){ if(n.name().equals("gameState")){ if(n.hasParameter("altitude")){ this.altitude = ((Integer)n.getParameter("altitude")).intValue(); } if(n.hasParameter("fuel")){ this.fuel = ((Integer)n.getParameter("fuel")).intValue(); } if(n.hasParameter("velocity")){ this.velocity = ((Integer)n.getParameter("velocity")).intValue(); } if(n.hasParameter("time")){ this.time = ((Integer)n.getParameter("time")).intValue(); } if(n.hasParameter("burnRate")){ this.burnRate = ((Integer)n.getParameter("burnRate")).intValue(); } }
else if(n.name().equals("clockTick")){ //Calculate new lander state values int actualBurnRate = burnRate; if(actualBurnRate > fuel){ //Ensure we don’t burn more fuel than we have actualBurnRate = fuel; }
time = time + 1; altitude = altitude - velocity; velocity = ((velocity + GRAVITY) * 10 – actualBurnRate * 2) / 10; fuel = fuel - actualBurnRate;
//Determine if we landed (safely) boolean landedSafely = false; if(altitude <= 0){ altitude = 0; if(velocity <= 5){ landedSafely = true; } }
Request r = new Request("updateGameState"); r.addParameter("time", time); r.addParameter("altitude", altitude); r.addParameter("velocity", velocity); r.addParameter("fuel", fuel); r.addParameter("landedSafely", landedSafely); send(r); } }
protected void handle (Request r) { //This component does not handle requests }}
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 themup as requests
Receives notifications ofgame state changes andformats 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
59
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(); }
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
60
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(); }
public void processInput() { System.out.println("Welcome to Lunar Lander"); try{ BufferedReader inputReader = new BufferedReader( new InputStreamReader(System.in));
int burnRate = 0; do { System.out.println("Enter burn rate or <0 to quit:"); try { String burnRateString = inputReader.readLine(); burnRate = Integer.parseInt(burnRateString);
Request r = new Request("updateGameState"); r.addParameter("burnRate", burnRate); send(r); } catch (NumberFormatException nfe) { System.out.println("Invalid burn rate."); } } while(burnRate >= 0); inputReader.close(); } catch (IOException ioe) { ioe.printStackTrace(); } }
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
61
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(); }
public void processInput(){ System.out.println("Welcome to Lunar Lander"); try{ BufferedReader inputReader = new BufferedReader( new InputStreamReader(System.in));
int burnRate = 0; do{ System.out.println("Enter burn rate or <0 to quit:"); try{ String burnRateString = inputReader.readLine(); burnRate = Integer.parseInt(burnRateString);
Request r = new Request("updateGameState"); r.addParameter("burnRate", burnRate); send(r); } catch(NumberFormatException nfe){ System.out.println("Invalid burn rate."); } }while(burnRate >= 0); inputReader.close(); } catch(IOException ioe){ ioe.printStackTrace(); } }
protected void handle (Notification n) { if (n.name().equals("gameState")) { System.out.println(); System.out.println("New game state:");
if (n.hasParameter("altitude")) { System.out.println(" Altitude: " + n.getParameter("altitude")); } if (n.hasParameter("fuel")) { System.out.println(" Fuel: " + n.getParameter("fuel")); } if (n.hasParameter("velocity")) { System.out.println(" Velocity: " + n.getParameter("velocity")); } if (n.hasParameter("time")) { System.out.println(" Time: " + n.getParameter("time")); } if (n.hasParameter("burnRate")) { System.out.println(" Burn rate: " + n.getParameter("burnRate")); }
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
62
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(); }
public void processInput(){ System.out.println("Welcome to Lunar Lander"); try{ BufferedReader inputReader = new BufferedReader( new InputStreamReader(System.in));
int burnRate = 0; do{ System.out.println("Enter burn rate or <0 to quit:"); try{ String burnRateString = inputReader.readLine(); burnRate = Integer.parseInt(burnRateString);
Request r = new Request("updateGameState"); r.addParameter("burnRate", burnRate); send(r); } catch(NumberFormatException nfe){ System.out.println("Invalid burn rate."); } }while(burnRate >= 0); inputReader.close(); } catch(IOException ioe){ ioe.printStackTrace(); } }
protected void handle(Notification n){ if(n.name().equals("gameState")){ System.out.println(); System.out.println("New game state:");
if(n.hasParameter("altitude")){ System.out.println(" Altitude: " + n.getParameter("altitude")); } if(n.hasParameter("fuel")){ System.out.println(" Fuel: " + n.getParameter("fuel")); } if(n.hasParameter("velocity")){ System.out.println(" Velocity: " + n.getParameter("velocity")); } if(n.hasParameter("time")){ System.out.println(" Time: " + n.getParameter("time")); } if(n.hasParameter("burnRate")){ System.out.println(" Burn rate: " + n.getParameter("burnRate")); }
if (n.hasParameter("altitude")) { int altitude = ((Integer)n.getParameter("altitude")).intValue(); if (altitude <= 0) { boolean landedSafely = ((Boolean)n.getParameter("landedSafely")) .booleanValue(); if (landedSafely) { System.out.println("You have landed safely."); } else { System.out.println("You have crashed."); } System.exit(0); } } } }
protected void handle (Request r) { //This component does not handle requests }}
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
Main Program
64
import c2.framework.*;
public class LunarLander {
public static void main(String[] args) { // Create the Lunar Lander architecture Architecture lunarLander = new SimpleArchitecture("LunarLander");
// Create the components Component clock = new Clock(); Component gameState = new GameState(); Component gameLogic = new GameLogic(); Component 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);
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
Main Program
65
import c2.framework.*;
public class LunarLander{
public static void main(String[] args){ //Create the Lunar Lander architecture Architecture lunarLander = new SimpleArchitecture("LunarLander");
//Create the components Component clock = new Clock(); Component gameState = new GameState(); Component gameLogic = new GameLogic(); Component 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);
// Create the welds (links) between components and // connectors lunarLander.weld(clock, bus); lunarLander.weld(gameState, bus); lunarLander.weld(bus, gameLogic); lunarLander.weld(bus, gui);
//Start the application lunarLander.start(); }}
Software Architecture: Foundations, Theory, and Practice; Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy; (C) 2008 John Wiley & Sons, Inc. Reprinted with permission.
Top Related