Post on 06-Feb-2016
description
Reading C2-style Applications Built in c2.fw
Eric M. Dashofyedashofy@ics.uci.edu
For ICS 52October 20, 2004
Overview Software architectures The C2 architectural style
With live example The Klax application
Software Architecture: Basic Elements
Clock Component
Interfaces
Bus1
Connector
Interfaces
Software Architecture: Basic Elements (cont).
Clock
Bus1
LCDDriver
Links
Configuration
An Architectural Style One definition of an architectural style: An architectural style is a named set of
constraints (e.g., rules) you put on your development Constraints may be topological, behavioral,
communication-oriented, you name it This can complicate development because these
constraints may be inconvenient or unfamiliar BUT architectural styles elicit beneficial system
properties that would be really hard to get otherwise
Examples from building architecture:
1. Name some constraints in each style
2. Name some benefits (-ilities) elicited by each style.
The C2 Architectural Style Topological Constraints
All components, connectors have two interfaces, “top” and “bottom”
Components can be connected to 0-1 connector on each interface
Connectors can be connected to 0+ components or connectors on each interface
The C2 Architectural Style Communication Constraints
Components & connectors communicate using only independent events or messages
• Requests go up (“requests rise”)• Notifications go down• No passing pointers
Components & connectors communicate asynchronously
• Can send/receive events at any time• No blocking!
The C2 Architectural Style Dependency Constraints
Components may make assumptions about services provided above them
• But not who is providing them Components may NOT make assumptions
about services provided below them Concurrency Constraints
Each component & connector assumes it’s running in its own thread of control
Live ExampleDataStore
GUI
GUIInterpreter
Alarm
Live ExampleDataStore
GUI
GUIInterpreter
Alarm
Stores data; emits
notifications whenever data
changes.
Live ExampleDataStore
GUI
GUIInterpreter
Alarm
Interprets basic GUI actions &
translates them into data store
operations
Live ExampleDataStore
GUI
GUIInterpreter
Alarm
Rings a bell whenever value
of X changes
Live ExampleDataStore
GUI
GUIInterpreter
AlarmAccept & process
user actions
Live ExampleDataStore
GUI
GUIInterpreter
AlarmBus connector – routes messages
Live ExampleDataStore
GUI
GUIInterpreter
Alarm
What –ilities does C2 buy us? What do you think?
-ilities bought by C2 Flexibility
Loose coupling lets you swap out components, interpose components
Flexible connectors allow run-time changes Distributability
Since no assumption of shared address space, distributing an app across machines is easy
Visibility Since all messages go through connectors, they are easy
to catch and log Parallelizability
One-thread-per-brick means multiprocessor machines are effectively utilized
Event-based vs. OO Event-based
Communication by events
Mostly asynchronous Requests emitted to
unknown parties Responses and state
changes go to many parties
No shared pointers
Object Oriented Communication by
procedure calls Mostly synchronous Requests emitted to
named party only Responses to caller
only, state changes to many
Lots of shared pointers
Implementing a C2 architecture
C2 architecture
Application (implemented)
Java/JVM
Native OS
Implemented by…
Uses services provided by…
??? How do we bridge this gap?
Event-basedWorld
Object-orientedWorld
Implementing a C2 architecture
C2 architecture
Application (implemented)
Java/JVM
Native OS
Implemented by…
Uses services provided by…
Architecture Framework
Uses services provided by…
Uses services provided by…
Event-basedWorld
Object-orientedWorld
What’s an architecture framework? An architecture framework is
software that helps to bridge the gaps between an architectural style and a particular implementation platform.
Example C2 World
Components Connectors Events Links Many threads Asynchronous
communication
Java World Objects Method calls Parameters References Few threads Synchronous
communication
Enter c2.fw c2.fw is an architecture framework for the
C2 style built in Java, providing: Abstract base classes for components,
connectors Reusable connectors (local & network) (Pluggable) topology management (Pluggable) message queuing policies (Pluggable) threading policies
Essentially, c2.fw does the hard work, components and connectors simply implement behaviors.
What does a message look like? In c2.fw, a message can be any
serializable (e.g. no pointers) object NamedPropertyMessages (or
subclasses) are popular though Have a String name Plus a set of name-value pairs
• e.g. {“description”, “Rectangle 1”}• e.g. {“width”, 123}• e.g. {“color”, java.awt.Color.BLACK}
“Reading” a c2.fw application Basic format Lifecycle methods:
init(), begin(), end(), destroy() start(), stop(), suspend(), resume()
Handling messages void handle(Message m)
Sending messages sendToAll(Message m, Interface i)
Your basic c2.fw component…package edu.uci.ics.mypackage;
import c2.fw.*; //import c2.fw packageimport c2.legacy.*; //import support for 2-interface //C2 components
Your basic c2.fw component…package edu.uci.ics.mypackage;
import c2.fw.*; //import c2.fw packageimport c2.legacy.*; //import support for 2-interface //C2 components
public class MyC2Component extends AbstractC2Brick{
}
Implements lots of boilerplate functionality from the base c2.fw.Brick
interface; declares a top interface topIface and a bottom interface
bottomIface.
A boilerplate c2.fw component…package edu.uci.ics.mypackage;
import c2.fw.*; //import c2.fw packageimport c2.legacy.*; //import support for 2-interface //C2 components
public class MyC2Component extends AbstractC2Brick{
public MyC2Component(Identifier id){ super(id); }
}
Each component or connector has a unique identifier.
A boilerplate c2.fw component…package edu.uci.ics.mypackage;
import c2.fw.*; //import c2.fw packageimport c2.legacy.*; //import support for 2-interface //C2 components
public class MyC2Component extends AbstractC2Brick{
public MyC2Component(Identifier id){ super(id); }
public void begin(){ //called automatically by fw. //send out initial events }}
Lifecycle Methodspublic void init(){ //called when component/connector is created //but component not guaranteed to be hooked up}
public void begin(){ //called when component/connector is hooked up //in the architecture, should send initial messages}
public void end(){ //called when component/connector is about to be //unhooked, should send final messages}
public void destroy(){ //called when component/connector is about to be //destroyed}
A boilerplate c2.fw component…package edu.uci.ics.mypackage;
import c2.fw.*; //import c2.fw packageimport c2.legacy.*; //import support for 2-interface //C2 components
public class MyC2Component extends AbstractC2Brick{
public MyC2Component(Identifier id){ super(id); }
public void begin(){ //called automatically by fw. //send out initial events }
public void handle(Message m){ //handle message }}
Implementing handle() //handle() method for our hypothetical alarm component //Called automatically when component receives a message //Should ring bell whenever value of ‘X’ changes
public void handle(Message m){ //handle message
}
Implementing handle() //handle() method for our hypothetical alarm component
public void handle(Message m){ //handle message
if(m instanceof NamedPropertyMessage){ NamedPropertyMessage npm = (NamedPropertyMessage)m; }
}
Implementing handle() //handle() method for our hypothetical alarm component
public void handle(Message m){ //handle message
if(m instanceof NamedPropertyMessage){ NamedPropertyMessage npm = (NamedPropertyMessage)m; String name = npm.getName(); if((name != null) && (name.equals(“valueChanged”)){
} } }
Implementing handle() //handle() method for our hypothetical alarm component
public void handle(Message m){ //handle message
if(m instanceof NamedPropertyMessage){ NamedPropertyMessage npm = (NamedPropertyMessage)m; String name = npm.getName(); if((name != null) && (name.equals(“valueChanged”)){ String varName = (String)npm.getParameter(“varName”); if((varName != null) && (varName.equals(“x”)){ } } } }
Implementing handle() //handle() method for our hypothetical alarm component
public void handle(Message m){ //handle message
if(m instanceof NamedPropertyMessage){ NamedPropertyMessage npm = (NamedPropertyMessage)m; String name = npm.getName(); if((name != null) && (name.equals(“valueChanged”)){ String varName = (String)npm.getParameter(“varName”); if((varName != null) && (varName.equals(“x”)){ ringBell(); NamedPropertyMessage rnpm = new NamedPropertyMessage(“AlarmFired”); rnpm.addProperty(“time”, System.currentTimeMillis()); sendToAll(rnpm, bottomIface); } } } }
Implementing handle()If we care, we could have checked what interface that message came in on:
if(m.getDestination().getInterfaceIdentifier().equals( AbstractC2Brick.TOP_INTERFACE_ID)){
//it’s a notification
}