16 Implementation_Techniques

Download Report

Transcript 16 Implementation_Techniques

Implementation
Techniques
Software Architecture
Lecture 16
Copyright © Richard N. Taylor, Nenad Medvidovic, and Eric M. Dashofy. All rights reserved.
Software Architecture: Foundations, Theory, and Practice
Objectives



Concepts
 Implementation as a mapping problem
 Architecture implementation frameworks
 Evaluating frameworks
 Relationships between middleware, frameworks,
component models
 Building new frameworks
 Concurrency and generative technologies
 Ensuring architecture-to-implementation consistency
Examples
 Different frameworks for pipe-and-filter
 Different frameworks for the C2 style
Application
 Implementing Lunar Lander in different frameworks
2
Software Architecture: Foundations, Theory, and Practice
Objectives



Concepts
 Implementation as a mapping problem
 Architecture implementation frameworks
 Evaluating frameworks
 Relationships between middleware, frameworks,
component models
 Building new frameworks
 Concurrency and generative technologies
 Ensuring architecture-to-implementation consistency
Examples
 Different frameworks for pipe-and-filter
 Different frameworks for the C2 style
Application
 Implementing Lunar Lander in different frameworks
3
Software Architecture: Foundations, Theory, and Practice
Recall Pipe-and-Filter



Components (‘filters’) organized linearly,
communicate through character-stream ‘pipes,’ which
are the connectors
Filters may run concurrently on partial data
In general, all input comes in through the left and all
output exits from the right
4
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 #1: stdio


Standard I/O framework used in C programming language
Each process is a filter
 Reads input from standard input (aka ‘stdin’)
 Writes output to standard output (aka ‘stdout’)
 Also a third, unbuffered output stream called standard error
(‘stderr’) not considered here
 Low and high level operations
 getchar(…), putchar(…) move one character at a time
 printf(…) and scanf(…) move and format entire strings

Different implementations may vary in details (buffering
strategy, etc.)
5
Software Architecture: Foundations, Theory, and Practice
Evaluating stdio

Platform support



Available with most, if
not all, implementations
of C programming
language
Operates somewhat
differently on OSes with
no concurrency (e.g.,
MS-DOS)
Fidelity

Good support for
developing P&F
applications, but no
restriction that apps have
to use this style

Matching assumptions


Filters are processes and
pipes are implicit. Inprocess P&F applications
might require
modifications
Efficiency

Whether filters make
maximal use of
concurrency is partially
up to filter
implementations and
partially up to the OS
6
Software Architecture: Foundations, Theory, and Practice
Framework #2: java.io



Standard I/O framework used in Java language
Object-oriented
Can be used for in-process or inter-process P&F
applications
 All stream classes derive from InputStream or
OutputStream
 Distinguished objects (System.in and System.out) for
writing to process’ standard streams
 Additional capabilities (formatting, buffering) provided
by creating composite streams (e.g., a FormattingBuffered-InputStream)
7
Software Architecture: Foundations, Theory, and Practice
Evaluating java.io

Matching assumptions


Platform support



Available with all Java
implementations on many
platforms
Platform-specific
differences abstracted
away
Fidelity

Good support for
developing P&F
applications, but no
restriction that apps have
to use this style


Easy to construct intraand inter-process P&F
applications
Concurrency can be an
issue; many calls are
blocking
Efficiency


Users have fine-grained
control over, e.g.,
buffering
Very high efficiency
mechanisms (memory
mapped I/O, channels)
not available (but are in
java.nio)
8
Software Architecture: Foundations, Theory, and Practice
Recall the C2 Style



Layered style
with event-based
communication
over two-way
broadcast
buses
Strict rules on
concurrency,
dependencies,
and so on
Many frameworks developed for
different languages; focus on two
alternative Java frameworks here
9
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 #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
10
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
Evaluating Lightweight C2
Framework
 Matching assumptions

Platform support



Available with all Java
implementations on
many platforms

Fidelity


Assists developers with
many aspects of C2
but does not enforce
these constraints
Leaves threading and
queuing policies up to
individual elements

Comp/conn main
classes must inherit
from distinguished
base classes
All messages must be
in dictionary form
Efficiency

Lightweight
framework; efficiency
may depend on
threading and queuing
policy implemented by
individual elements
11
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
12
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
13
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
Evaluating Flexible C2 Framework

Platform support


Available with all Java
implementations on
many platforms


Fidelity


Assists developers with
many aspects of C2
but does not enforce
these constraints
Provides several
alternative applicationwide threading and
queuing policies
Matching assumptions


Comp/conn main classes
must implement
distinguished interfaces
Messages can be any
serializable object
Efficiency

User can easily swap out
and tune threading and
queuing policies without
disturbing remainder of
application code
14
Software Architecture: Foundations, Theory, and Practice
Objectives



Concepts
 Implementation as a mapping problem
 Architecture implementation frameworks
 Evaluating frameworks
 Relationships between middleware, frameworks,
component models
 Building new frameworks
 Concurrency and generative technologies
 Ensuring architecture-to-implementation consistency
Examples
 Different frameworks for pipe-and-filter
 Different frameworks for the C2 style
Application
 Implementing Lunar Lander in different frameworks
15
Software Architecture: Foundations, Theory, and Practice
Implementing Pipe and Filter
Lunar Lander




Framework: java.io
Implementing as a multi-process application
 Each component (filter) will be a separate OS process
 Operating system will provide the pipe connectors
Going to use just the standard input and output streams
 Ignoring standard error
Ignoring good error handling practices and corner cases for
simplicity
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
Implementing Pipe and Filter
Lunar Lander

A note on I/O:
 Some messages sent from components are intended for output
to the console (to be read by the user)
 These messages must be passed all the way through the
pipeline and output at the end
 We will preface these with a ‘#’
 Some messages are control messages meant to communicate
state to a component down the pipeline
 These messages are intercepted by a component and
processed
 We will preface these with a ‘%’
17
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 Pipe and Filter
Lunar Lander

First: GetBurnRate component
 Loops; on each loop:
 Prompt user for new burn rate
 Read burn rate from the user on standard input
 Send burn rate to next component
 Quit if burn rate read < 0
18
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
GetBurnRate Filter
//Import the java.io framework
import java.io.*;
public class GetBurnRate{
public static void main(String[] args){
//Send welcome message
System.out.println("#Welcome to Lunar Lander");
try{
//Begin reading from System input
BufferedReader inputReader =
new BufferedReader(new InputStreamReader(System.in));
//Set initial burn rate to 0
int burnRate = 0;
do{
//Prompt user
System.out.println("#Enter burn rate or <0 to quit:");
. . .
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
GetBurnRate Filter
//Import the java.io framework
import java.io.*;
. . .
public class GetBurnRate{
//Read user response
public static void
try{main(String[] args){
String burnRateString = inputReader.readLine();
//Send welcome message
burnRate = Integer.parseInt(burnRateString);
System.out.println("#Welcome to Lunar Lander");
//Send user-supplied burn rate to next filter
try{
System.out.println("%" + burnRate);
//Begin reading
from System input
}
BufferedReader
inputReader =
catch(NumberFormatException
nfe){
new BufferedReader(new
InputStreamReader(System.in));
System.out.println("#Invalid burn rate.");
}
//Set initial
burn rate to>=0 0);
}while(burnRate
int burnRate
= 0;
inputReader.close();
do{
}
//Prompt
user
catch(IOException
ioe){
System.out.println("#Enter
burn rate or <0 to quit:");
ioe.printStackTrace();
}
. . .
}
}
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
Implementing Pipe and Filter
Lunar Lander

Second: CalcNewValues Component
 Read burn rate from standard input
 Calculate new game state including game-over
 Send new game state to next component
 New game state is not sent in a formatted string;
that’s the display component’s job
21
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
CalcBurnRate Filter
import java.io.*;
public class CalcNewValues{
public static void main(String[] args){
//Initialize values
final int GRAVITY = 2;
int altitude = 1000;
int fuel = 500;
int velocity = 70;
int time = 0;
try{
BufferedReader inputReader = new
BufferedReader(new InputStreamReader(System.in));
//Print initial values
System.out.println("%a"
System.out.println("%f"
System.out.println("%v"
System.out.println("%t"
. . .
+
+
+
+
altitude);
fuel);
velocity);
time);
22
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
CalcBurnRate Filter
import java.io.*;
String inputLine = null;
do{
public class CalcNewValues{
inputLine = inputReader.readLine();
if((inputLine != null) &&
public static void
(inputLine.length()
main(String[] args){
> 0)){
//Initialize values
final int GRAVITY
if(inputLine.startsWith("#")){
= 2;
int altitude = 1000;
//This is a status line of text, and
int fuel = 500; //should be passed down the pipeline
int velocity = 70;
System.out.println(inputLine);
int time = 0; }
else if(inputLine.startsWith("%")){
try{
//This is an input burn rate
BufferedReadertry{
inputReader = new
BufferedReader(new
int burnRate
InputStreamReader(System.in));
= Integer.parseInt(inputLine.substring(1));
if(altitude <= 0){
//Print initial values
System.out.println("#The game is over.");
System.out.println("%a"
}
+ altitude);
System.out.println("%f"
else if(burnRate
+ fuel); > fuel){
System.out.println("%v"
System.out.println("#Sorry,
+ velocity);
you don't" +
System.out.println("%t"
"have
+ that
time);
much fuel.");
}
23
. . .
. . .
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
CalcBurnRate Filter
else{ inputLine = null;
import java.io.*;
String
//Calculate new application state
do{
time = time
+ 1;
public class CalcNewValues{
inputLine
= inputReader.readLine();
altitude = altitude
- velocity;
if((inputLine
!= null)
&&
velocity
=
((velocity
+
GRAVITY) * 10 public static void
(inputLine.length()
main(String[] args){
> 0)){
burnRate * 2) / 10;
//Initialize values
fuel
==fuel
final int GRAVITY
if(inputLine.startsWith("#")){
2; - burnRate;
<=a 0){
int altitudeif(altitude
= 1000;
//This is
status line of text, and
altitude
=
0;
int fuel = 500; //should be passed down the pipeline
<= 5){
int velocity =if(velocity
70;
System.out.println(inputLine);
int time = 0; } System.out.println("#You have landed safely.");
}
else
if(inputLine.startsWith("%")){
else{
try{
//This is an input burn rate
System.out.println("#You
have crashed.");
BufferedReadertry{
inputReader = new
}
BufferedReader(new
int burnRate
InputStreamReader(System.in));
= Integer.parseInt(inputLine.substring(1));
}
if(altitude <= 0){
}
//Print initial values
System.out.println("#The game is over.");
//Print
new
values
System.out.println("%a"
}
+ altitude);
System.out.println("%a"
System.out.println("%f"
else if(burnRate
+ fuel);+> altitude);
fuel){
System.out.println("%f"
+
fuel);
System.out.println("%v"
System.out.println("#Sorry,
+ velocity);
you don't" +
System.out.println("%v"
+
velocity);
System.out.println("%t"
"have
+ that
time);
much fuel.");
System.out.println("%t"
+ time);
}
}
. . .
. . .
catch(NumberFormatException nfe){
}
24
. . .
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
CalcBurnRate Filter
else{ inputLine = null;
import java.io.*;
String
//Calculate new application state
do{
time = time
+ 1;
public class CalcNewValues{
inputLine
= inputReader.readLine();
altitude = altitude
- velocity;
if((inputLine
!= null)
&&
velocity
=
((velocity
+
GRAVITY) * 10 public static void
(inputLine.length()
main(String[] args){
> 0)){
burnRate * 2) / 10;
//Initialize values
fuel
==fuel
final int GRAVITY
if(inputLine.startsWith("#")){
2; - burnRate;
<=a}0){
int altitudeif(altitude
= 1000;
//This is
status line of text, and
altitude
=
0;
int fuel = 500; //should }be passed down the pipeline
<= 5){
}while((inputLine
!= null) && (altitude > 0));
int velocity =if(velocity
70;
System.out.println(inputLine);
have landed safely.");
inputReader.close();
int time = 0; } System.out.println("#You
}
}
else
if(inputLine.startsWith("%")){
else{
catch(IOException
try{
//This
is an input burnioe){
rate
System.out.println("#You
have crashed.");
ioe.printStackTrace();
BufferedReadertry{
inputReader
= new
}
BufferedReader(new
int} burnRate
InputStreamReader(System.in));
= Integer.parseInt(inputLine.substring(1));
}
}
if(altitude <= 0){
}
}
//Print initial values
System.out.println("#The game is over.");
//Print
new
values
System.out.println("%a"
}
+ altitude);
System.out.println("%a"
System.out.println("%f"
else if(burnRate
+ fuel);+> altitude);
fuel){
System.out.println("%f"
+
fuel);
System.out.println("%v"
System.out.println("#Sorry,
+ velocity);
you don't" +
System.out.println("%v"
+
velocity);
System.out.println("%t"
"have
+ that
time);
much fuel.");
System.out.println("%t"
+ time);
}
}
. . .
. . .
catch(NumberFormatException nfe){
}
25
. . .
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 Pipe and Filter
Lunar Lander

Third: DisplayValues component
 Read value updates from standard input
 Format them for human reading and send them to
standard output
26
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
DisplayValues Filter
import java.io.*;
public class DisplayValues{
public static void main(String[] args){
try{
BufferedReader inputReader = new
BufferedReader(new InputStreamReader(System.in));
String inputLine = null;
do{
inputLine = inputReader.readLine();
if((inputLine != null) &&
(inputLine.length() > 0)){
if(inputLine.startsWith("#")){
//This is a status line of text, and
//should be passed down the pipeline with
//the pound-sign stripped off
System.out.println(inputLine.substring(1));
}
. . .
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
DisplayValues Filter
else if(inputLine.startsWith("%")){
import java.io.*;//This is a value to display
if(inputLine.length() > 1){
public class DisplayValues{
try{
char valueType = inputLine.charAt(1);
public static void int
main(String[]
args){
value = Integer.parseInt(inputLine.substring(2));
try{
BufferedReader switch(valueType){
inputReader = new
BufferedReader(new
case InputStreamReader(System.in));
'a':
System.out.println("Altitude: " + value);
String inputLine = break;
null;
do{
case 'f':
inputLine = inputReader.readLine();
System.out.println("Fuel remaining: " + value);
if((inputLine != break;
null) &&
(inputLine.length()
> 0)){
case 'v':
System.out.println("Current Velocity: “ + value);
if(inputLine.startsWith("#")){
break;
//This is acase
status
't':line of text, and
//should be passed
down the pipeline with
System.out.println("Time
elapsed: " + value);
//the pound-sign
stripped
off
break;
System.out.println(inputLine.substring(1));
}
}
}
. . .
. . .
catch(NumberFormatException nfe){
}
28
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
DisplayValues Filter
else if(inputLine.startsWith("%")){
import java.io.*;//This is a value to display
if(inputLine.length() > 1){
public class DisplayValues{
try{
char valueType = inputLine.charAt(1);
public static void int
main(String[]
args){
value = Integer.parseInt(inputLine.substring(2));
try{
BufferedReader switch(valueType){
inputReader = new
}
BufferedReader(new
InputStreamReader(System.in));
case 'a': }
System.out.println("Altitude:
" + value);
}
String inputLine = break;
null;
}while(inputLine != null);
do{
case 'f':
inputReader.close();
inputLine = inputReader.readLine();
System.out.println("Fuel
remaining: " + value);
}
if((inputLine != break;
null) &&
catch(IOException ioe){
(inputLine.length()
> 0)){
case 'v':
ioe.printStackTrace();
System.out.println("Current
Velocity: “ + value);
}
if(inputLine.startsWith("#")){
}break;
//This is acase
status
't':line of text, and
}
//should be passed
down the pipeline with
System.out.println("Time
elapsed: " + value);
//the pound-sign
stripped
off
break;
System.out.println(inputLine.substring(1));
}
}
}
catch(NumberFormatException nfe){
. . .
}
. . .
29
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 Pipe and Filter
Lunar Lander

Instantiating the application

java GetBurnRate | java CalcNewValues | java DisplayValues
30
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 Pipe and Filter
Lunar Lander
31
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 Pipe and Filter
Lunar Lander
32
Software Architecture: Foundations, Theory, and Practice
Implementing Pipe and Filter
Lunar Lander
33
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 Pipe and Filter
Lunar Lander
34
Software Architecture: Foundations, Theory, and Practice
Takeaways




java.io provides a number of useful facilities
 Stream objects (System.in, System.out)
 Buffering wrappers
OS provides some of the facilities
 Pipes
 Concurrency support
 Note that this version of the application would not work if it
operated in batch-sequential mode
We had other communication mechanisms available, but did not use
them to conform to the P&F style
We had to develop a new (albeit simple) protocol to get the correct
behavior
35
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
36
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
37
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);
}
}
};
38
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
component
does not runs
handle notifications
//Repeat
while
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);
}
}
};
39
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
40
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;
41
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);
42
}
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
protected else
void if(r.name().equals("getGameState")){
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
handle(Notification
n){
//Send
out the
updated
game state
//This component
does not handle notifications
Notification
n = createStateNotification();
}
send(n);
43
} }
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
44
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);
}
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
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(n.hasParameter("time")){
0;
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);
}
}
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
GameLogic
Component
protected void handle(Notification
n){
if(n.name().equals("gameState")){
else
if(n.name().equals("clockTick")){
if(n.hasParameter("altitude")){
import
c2.framework.*;
//Calculate
new lander= state values
this.altitude
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);
}
}
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
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);
}
}
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



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
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
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();
}
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
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();
nfe){
Thread t = catch(NumberFormatException
new Thread(){
burn rate.");
public voidSystem.out.println("Invalid
run(){
}
processInput();
}while(burnRate >= 0);
}
inputReader.close();
};
}
t.start();
catch(IOException ioe){
}
ioe.printStackTrace();
}
}
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
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));
System.out.println();
import java.io.IOException;
game state:");
importSystem.out.println("New
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
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
public void processInput(){
System.out.println("Welcome to Lunar Lander");
try{
protectedif(n.hasParameter("altitude")){
void handle(Notification n){
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
game state:");
if(altitude
import java.io.InputStreamReader;
int burnRate<=
= 0){
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(landedSafely){
public class GUI
extendsburnRateString
ComponentThread{
String
= 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
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
Implementing Lunar Lander in C2


Lastly, main program
Instantiates and connects
all elements of the system
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
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 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);
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
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);
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
Takeaways



Here, the C2 framework provides most all of the scaffolding we
need
 Message routing and buffering
 How to format a message
 Threading for components
 Startup and instantiation
We provide the component behavior
 Including a couple new threads of our own
We still must work to obey the style guidelines
 Not everything is optimal: state is duplicated in Game Logic, for
example
57