Вы находитесь на странице: 1из 57

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

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  Matching assumptions
 Available with most, if  Filters are processes and
not all, implementations pipes are implicit. In-
of C programming process P&F applications
language
might require
 Operates somewhat modifications
differently on OSes with
no concurrency (e.g.,  Efficiency
MS-DOS)  Whether filters make
 Fidelity maximal use of
 Good support for concurrency is partially
developing P&F up to filter
applications, but no implementations and
restriction that apps have partially up to the OS
to use this style 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 Formatting-
Buffered-InputStream)
7
Software Architecture Foundations, Theory, and Practice

Evaluating java.io  Matching assumptions


 Easy to construct intra-
 Platform support and inter-process P&F
 Available with all Java applications
implementations on many  Concurrency can be an
platforms issue; many calls are
 Platform-specific blocking
differences abstracted
 Efficiency
away
 Fidelity  Users have fine-grained
 Good support for control over, e.g.,
developing P&F buffering
applications, but no  Very high efficiency
restriction that apps have mechanisms (memory
to use this style 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  Comp/conn main


 Available with all Java classes must inherit
implementations on from distinguished
many platforms base classes
 Fidelity  All messages must be
in dictionary form
 Assists developers with
many aspects of C2  Efficiency
but does not enforce  Lightweight
these constraints framework; efficiency
 Leaves threading and may depend on
queuing policies up to threading and queuing
individual elements 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  Matching assumptions
 Available with all Java  Comp/conn main classes
implementations on must implement
many platforms distinguished interfaces
 Fidelity  Messages can be any
 Assists developers with serializable object
many aspects of C2  Efficiency
but does not enforce  User can easily swap out
these constraints and tune threading and
queuing policies without
 Provides several disturbing remainder of
alternative application- application code
wide threading and
queuing policies
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
ioe.printStackTrace();burn rate or <0 to quit:");
}
. . . }
} 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" + altitude);
System.out.println("%f" + fuel);
System.out.println("%v" + velocity);
System.out.println("%t" + 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
public class CalcNewValues{
inputLine + 1;
= inputReader.readLine();
altitude = altitude
if((inputLine - velocity;
!= null) &&
velocity
public static void = ((velocity
(inputLine.length() +
main(String[] args){ GRAVITY) * 10 -
> 0)){
burnRate * 2) / 10;
//Initialize values
fuel
final int GRAVITY ==fuel
2; - burnRate;
if(inputLine.startsWith("#")){
int altitudeif(altitude
= 1000;
//This is<=a 0){
status line of text, and
altitude = 0;
int fuel = 500; //should be passed down the pipeline
int velocity =if(velocity
70; <= 5){
System.out.println(inputLine);
int time = 0; } System.out.println("#You have landed safely.");
}
else if(inputLine.startsWith("%")){
try{ else{
//This is an input burn rate
System.out.println("#You
BufferedReadertry{
inputReader = new have crashed.");
}
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
System.out.println("%a"
} values
+ altitude);
System.out.println("%a"
System.out.println("%f" + fuel);+> altitude);
else if(burnRate fuel){
System.out.println("%f"
System.out.println("%v" + fuel);
System.out.println("#Sorry,
+ velocity); you don't" +
System.out.println("%v"
System.out.println("%t""have
+ that
time);+ velocity);
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
public class CalcNewValues{
inputLine + 1;
= inputReader.readLine();
altitude = altitude
if((inputLine != null)- velocity;
&&
velocity
public static void = ((velocity
(inputLine.length()
main(String[] args){ + GRAVITY) * 10 -
> 0)){
burnRate * 2) / 10;
//Initialize values
fuel
final int GRAVITY ==fuel
2; - burnRate;
if(inputLine.startsWith("#")){
int altitudeif(altitude
= 1000;
//This is <=a}0){
status line of text, and
altitude = 0;
int fuel = 500; //should }be passed down the pipeline
int velocity =if(velocity
70; <= 5){
}while((inputLine != null) && (altitude > 0));
System.out.println(inputLine);
int time = 0; } System.out.println("#You
inputReader.close(); have landed safely.");
}
else }
if(inputLine.startsWith("%")){
try{ else{ catch(IOException
//This is an input burnioe){
rate
System.out.println("#You
BufferedReadertry{ ioe.printStackTrace();
inputReader = new have crashed.");
} int} burnRate
BufferedReader(new InputStreamReader(System.in));
= Integer.parseInt(inputLine.substring(1));
} }
if(altitude <= 0){
} }
//Print initial values
System.out.println("#The game is over.");
//Print new
System.out.println("%a"
} values+ altitude);
System.out.println("%a"
System.out.println("%f" + fuel);+> altitude);
else if(burnRate fuel){
System.out.println("%f"
System.out.println("%v" + fuel);
System.out.println("#Sorry,
+ velocity); you don't" +
System.out.println("%v"
System.out.println("%t""have + that
time); + velocity);
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()
case 'v':> 0)){
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
break; off
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()
case 'v':> 0)){
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
break;stripped off
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(){
publicprotected void handle(Notification n){
void run(){
//This
//Repeat component
while does not runs
the application handle notifications
}
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

GameState Component
protected void handle(Request r){
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;
int fuel this.time
= 500; = ((Integer)r.getParameter("time")).intValue();
}
int velocity = 70;
if(r.hasParameter("burnRate")){
int time = 0;
this.burnRate
int burnRate = 0; = ((Integer)r.getParameter("burnRate")).intValue();
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")){
//If
handle(Request r){
a component requests the game state
if(r.name().equals("updateGameState")){
//Update//without updating
the internal gameit, send out the state
state
if(r.hasParameter("altitude")){
import c2.framework.*;
Notification
this.altitude n = createStateNotification();
= ((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
this.velocity notification comprising the
= ((Integer)r.getParameter("velocity")).intValue();
} //current game state
//Internal game state and initial values
if(r.hasParameter("time")){
int altitude = 1000;
Notification
this.time n = new Notification("gameState");
= ((Integer)r.getParameter("time")).intValue();
int fuel = 500;
} n.addParameter("altitude", altitude);
int velocity = 70;
n.addParameter("fuel",
if(r.hasParameter("burnRate")){fuel);
int time = 0;
n.addParameter("velocity",
this.burnRate velocity);
= ((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",
this.landedSafely landedSafely);
= ((Boolean)r.getParameter("landedSafely"))
return n;
.booleanValue();
} }
protected
//Send void
out the handle(Notification
updated game state n){
//This component
Notification does not handle notifications
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
import if(n.name().equals("clockTick")){
if(n.hasParameter("altitude")){
c2.framework.*;
//Calculate new lander= state values
this.altitude
public int
classactualBurnRate
GameLogic = burnRate;
((Integer)n.getParameter("altitude")).intValue();
extends ComponentThread{
if(actualBurnRate
}
public GameLogic(){ > fuel){
//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
finaltime
int =GRAVITY
time + =1;2;
if(n.hasParameter("velocity")){
altitudethis.velocity
= altitude - =velocity;
velocity
//Internal =((Integer)n.getParameter("velocity")).intValue();
state ((velocity
values for+ computation
GRAVITY) * 10 –
actualBurnRate
int altitude } = 0; * 2) / 10;
fuel ==if(n.hasParameter("time")){
int fuel fuel - actualBurnRate;
0;
int velocity this.time
= 0; =
//Determine
int time if we landed (safely)
= 0; ((Integer)n.getParameter("time")).intValue();
boolean
int burnRate } landedSafely
= 0; = false;
if(altitude <= 0){
if(n.hasParameter("burnRate")){
public altitude = 0;
this.burnRate
void start(){ =
if(velocity
super.start(); <= 5){
((Integer)n.getParameter("burnRate")).intValue();
RequestlandedSafely = true;
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> fuel){ComponentThread{
public //Ensure
GameLogic(){
Request werdon’t
= newburn
Request("updateGameState");
more fuel than we have
if(n.hasParameter("fuel")){
super.create("gameLogic",
r.addParameter("time",
actualBurnRate
this.fuel == fuel; FIFOPort.class);
time);
} } r.addParameter("altitude", altitude);
((Integer)n.getParameter("fuel")).intValue();
r.addParameter("velocity",
} velocity);
//Game constants
time = r.addParameter("fuel",
time + 1; fuel);
if(n.hasParameter("velocity")){
finalaltitude
int r.addParameter("landedSafely",
GRAVITY = 2;
= altitude
this.velocity - =velocity; landedSafely);
send(r);
velocity =((Integer)n.getParameter("velocity")).intValue();
((velocity + GRAVITY) * 10 –
//Internal
} } state
actualBurnRate values for/ computation
* 2) 10;
int altitude
}
fuel = 0;
=if(n.hasParameter("time")){
fuel - actualBurnRate;
int fuel = 0;this.time =
int velocity
protected
//Determine = ((Integer)n.getParameter("time")).intValue();
0;
void
if wehandle(Request
landed (safely)r){
int time = }0;landedSafely
//This
boolean component does not handle requests
= false;
int burnRate
}
if(altitude = 0;<= 0){
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(){

GUI Component
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{
public class GUI String
extendsburnRateString = inputReader.readLine();
ComponentThread{
public GUI(){ burnRate = Integer.parseInt(burnRateString);
super.create("gui", FIFOPort.class);
} Request r = new Request("updateGameState");
r.addParameter("burnRate", burnRate);
send(r);
public void start(){
}
super.start();
Thread t = catch(NumberFormatException
new Thread(){ nfe){
public voidSystem.out.println("Invalid
run(){ burn rate.");
}
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(){

GUI Component
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;
importSystem.out.println("New game state:");
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("
super.create("gui", Fuel: " + n.getParameter("fuel"));
FIFOPort.class);
} }
Request r = new Request("updateGameState");
if(n.hasParameter("velocity")){
r.addParameter("burnRate", burnRate);
System.out.println("
public void start(){ Velocity: " + n.getParameter("velocity"));
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);
}; System.out.println("
inputReader.close();
Burn rate: " + n.getParameter("burnRate"));
}
t.start();
}
} catch(IOException ioe){
ioe.printStackTrace();
}
} 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(){

GUI Component
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
if(altitude game state:");
int burnRate<= = 0){
import java.io.InputStreamReader;
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")){
public GUI(){ System.out.println("You have landed safely.");
burnRate = Integer.parseInt(burnRateString);
System.out.println("
}
super.create("gui", Fuel: " +
FIFOPort.class); n.getParameter("fuel"));
} } else{
Request r = new Request("updateGameState");
if(n.hasParameter("velocity")){
System.out.println("You have crashed.");
r.addParameter("burnRate", burnRate);
System.out.println("
} send(r);
public void start(){ Velocity: " + n.getParameter("velocity"));
} System.exit(0);
super.start();
}
if(n.hasParameter("time")){
}
Thread t = catch(NumberFormatException
new Thread(){ nfe){
System.out.println("
} Time: " +
public voidSystem.out.println("Invalid
run(){ n.getParameter("time"));
burn rate.");
} processInput();
} }
if(n.hasParameter("burnRate")){
}} }while(burnRate >= 0);
}; System.out.println("
inputReader.close();
Burn rate: " + n.getParameter("burnRate"));
}protected void handle(Request r){
t.start();
}
} //This component does
catch(IOException not handle requests
ioe){
} ioe.printStackTrace();
} }
} 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

Вам также может понравиться