Software architecture
7
- architecture -- components and boundaries
- case study -- a framework for multimedia feature detection
- native objects -- the language boundary
- embedded logic -- the paradigm boundary
- architectural styles -- distributed object technology
- cross-platform development -- Unix versus Windows
Additional keywords and phrases:
components,
information architecture,
multimedia information retrieval,
feature detection,
portability
slide: Software architecture
Elements of architecture
[Wolf]
- processing elements -- transformation on data
- data elements -- contain information
- connections -- glue that holds elements together
Models and views
[Kruchten95]
- logical -- functional requirements
- process -- performance, availability, distribution
- physical -- scalability, configuration
- development -- organization of software modules
- scenarios -- instances of use cases
Definitions
slide: Elements of architecture -- models and views
The software architecture of a program or computing system
is the structure of the system, which comprises
software components, the externally visible properties
of those components, and their interrelationships.
Technological infrastructure
[CS2001]
- client-platform -- hardware, OS
- presentation services -- windows, multimedia
- application software -- code, business logic
- network -- communication support
- middleware -- distribution, (object) brokers
- server platform -- hardware, OS
- database -- data management system
slide: Technological infrastucture
detector world; // finds the name of the world
detector people; // checks name, eliminates institutes
detector company; // looks if there are at least two persons
atom str name;
community: world people company;
world: name;
people: person*;
person: name;
slide: A sample grammar
int personDetector(tree *pt, list *tks ){
...
q = query_query("kit=pl src=check.pl");
while (t = next_token(tks)) {
sprintf(buf,"person(\%s)",t);
query_eval(q,buf);
if (query_result(q,0)) put name(person) on tokenstream
putAtom(tks,"name",t);
}
...
}
slide: A person detector
V0 := newoid();
V1 := newoid();
community_world.insert(oid(V0),oid(V1));
world_name.insert(oid(V1),"casa");
community_people.insert(oid(V0),oid(V1));
V2 := newoid();
people_person.insert(oid(V1),oid(V2));
person_name.insert(oid(V2),"alice");
people_person.insert(oid(V1),oid(V2));
person_name.insert(oid(V2),"sebastiaan");
...
slide: Database updates
detector song; ## to get the filename
detector lyrics; ## extracts lyrics
detector melody; ## extracts melody
atom str name;
atom str text;
atom str note;
song: file lyrics melody;
file: name;
lyrics: text*;
melody: note*;
slide: A simple feature grammar for MIDI files
event('kortjakje',2,time=384, note_on:[chan=2,pitch=72,vol=111]).
event('kortjakje',2,time=768, note_off:[chan=2,pitch=72,vol=100]).
int melodyDetector(tree *pt, list *tks ){
char buf[1024]; char* _result;
void* q = _query;
int idq = 0;
idq = query_eval(q,"X:melody(X)");
while ((_result = query_result(q,idq)) ) {
printf("note: \%s",_result);
putAtom(tks,"note",_result);
}
return SUCCESS;
}
slide: The melody detector
given type AtomName, AtomValue;
interface tokenstream {
void putAtom(in AtomName, in AtomValue);
};
V1 := newoid();
midi_song.insert(oid(V0),oid(V1));
V2 := newoid();
song_file.insert(oid(V1),oid(V2));
file_name.insert(oid(V2),"kortjakje");
song_lyrics.insert(oid(V1),oid(V2));
lyrics_text.insert(oid(V2),"e");
lyrics_text.insert(oid(V2),"per-");
lyrics_text.insert(oid(V2),"sonne");
lyrics_text.insert(oid(V2),"Moi");
lyrics_text.insert(oid(V2),"je");
lyrics_text.insert(oid(V2),"dis");
lyrics_text.insert(oid(V2),"que");
lyrics_text.insert(oid(V2),"les");
lyrics_text.insert(oid(V2),"bon-");
lyrics_text.insert(oid(V2),"bons");
lyrics_text.insert(oid(V2),"Val-");
lyrics_text.insert(oid(V2),"ent");
song_melody.insert(oid(V1),oid(V2));
melody_note.insert(oid(V2),"a-2");
melody_note.insert(oid(V2),"a-2");
melody_note.insert(oid(V2),"g-2");
melody_note.insert(oid(V2),"g-2");
melody_note.insert(oid(V2),"f-2");
melody_note.insert(oid(V2),"f-2");
melody_note.insert(oid(V2),"e-2");
melody_note.insert(oid(V2),"e-2");
melody_note.insert(oid(V2),"d-2");
melody_note.insert(oid(V2),"d-2");
melody_note.insert(oid(V2),"e-2");
melody_note.insert(oid(V2),"c-2");
slide: Update of Monet database
- (SG/X)ML-like syntax for queries
- logic engine in filter
- Note: this is an offline approach
- Rationale: only knowledge maintenance
embedded logic
<query kit=pl src=local.pl cmd=X:email_address(X)>
<param format=" \%s">
<param result="">
<param display="<h4>The query</h4>">
<param header="<h4>The adresses</h4> <ul>">
<param footer="</ul>">
email_address(E) :-
person(X),
property(X,name:N),
property(X,familyname:F),
email(X,E),
cout(['', N,' ',F,' has email adress ']),
cout([ '<a href=mailto:', E, '>', E, '</a>',nl]).
</query>
query pl = new query("kit=pl src=remote.pl");
pl.eval("X:assistant(X)");
String res = null;
while ( (res = pl.result()) != null ) {
System.out.println(" " + res);
}
- maintaining knowledge is difficult
- don't replicate, otherwise ...
- so we need to access knowledge from remote sources
- and possibly mix remote and local knowledge
- Solution: url-enabled consults
- Problem: availability of the (VU) server
- queries may clash, we need seperate 'engines'
- this is static, the next step is dynamic: signed applets
- this is research code, not production code
slide: Remarks
interface query {
void source(in string file);
long eval(in string cmd);
string result(in long id);
oneway void halt();
};
- knowledge management with logic is feasible
- has applications in document engineering and ...
- embedding is relatively efficient
- can be done in multiple ways
- corba enabled logic services are possible
- true logic is hard to debug
slide: Conclusions
- Many flavors: Sicstus, ...
- Modules do not suffice - ...
- Requirements: low overhead, natural syntax
- Additional requirements:
binding with native objects
slide: Objects in Prolog
- native bindings are mostly for functions only
- Java, however, provides an example
- Let's first look at objects in Prolog,
and then their possibly native realization
slide: Native Objects
- representation -- object(Handler,Class,ID,REF,Ancestors)
- object definition -- class_method(This,...)
- object invocation -- self(This):method(...)
- state variables representation -- value(ID,Key,Value)
- state variable access -- var(Key) = Value, Var = value(key)
- native binding - native(Handler,Method,Result)
slide: Objects in Prolog
requirements
- low overhead, especially when not needed
- natural syntax for object clause definitions
- support for native objects
midi(This):midi, // create midi object
Self = self(This),
Self:open('a.mid'),
Self:header(0,1,480),
Self:track(start),
Self:melody([48,50,51,53,55]), // c d es f g, minor indeed
Self:track(end), // end track
midi
:- use(library(midi:[midi,lily,music,process])).
:- declare(midi:object,class(midi),[handler]).
midi_midi(This) :- // constructor
midi(This):handler(H), // gets Handler from class
declare(H,new(midi(This)),[],[],_).
native methods
midi_read(This,F) :- native(_,This,read(F),_).
midi_analyse(This,I,O) :- native(_,This,analyse(I,O),_).
midi_open(This,F) :- native(_,This,open(F),_).
midi_header(This,M) :- native(_,This,header(M,0,480),_).
midi_track(This,X) :- native(_,This,track(X),_).
midi_tempo(This,X) :- native(_,This,tempo(X),_).
midi_event(This,D,C,M,T,V) :-
native(_,This,event(D,C,M,T,V),_).
midi_note(This,D,C,T,V) :-
Self = midi(This), // cast to midi
Self:event(D,C,note_on,T,V),
Self:event(D,C,note_off,T,V).
midi_melody(This,L) :- self(This):melody(480,1,L,64).
midi_melody(_This,_,_,[],_).
midi_melody(This,D,C,[X|R],V) :-
Self = self(This),
Self:note(D,C,X,V),
midi_melody(This,D,C,R,V). // direct invocation
- method call - check ID is a REF
- declaration - call (native) constructor
- mapping creation and method calls -- through native support
- native support -- binding: object_handler and query_event
- native support -- classes: the usual (hush) hierarchy
e.g. obscure
and kit
slide: Native Objects in Prolog
- generic binding for (pl) kit - with secondary handler dictionary
- handler hierarchy -- obscure, handler, event, kit, query
- downcall - via smart pointer vm
- upcall - via embedded vm in handler
slide: C++ bindings
class query_object : public kit_object { kit_object
public:
query_object(kit* q, char* n = "query:object") : kit_object(q,n) { }
object_handler* _create(query* q, char* n = "query:object") {
return new query_object(q,n);
}
int operator()();
};
int kit_object::operator()() {
event* e = _event;
vm<kit> self(e); // smart pointer
string method = e->_method();
if (method == "kit") { // constructor
kit* q = new kit(e->arg(1));
_register(q);
result( reference((void*)q) );
} else if (method == "eval") {
long res = self->eval(e->arg(1));
result( itoa(res) );
} else if (method == "result") {
char* res = self->result( atoi(e->arg(1)) );
result(res);
} else { // dispatch up in the hierarchy
return handler_object::operator()();
}
return 0;
}
event* handler::dispatch(event* e) {
_event = e;
if (_vmp) {
return ((vm*)_vmp)->dispatch(e);
} else {
if (e->thekit()) tk = e->thekit(); // AE
int result = this->operator()();
if (result != OK) return 0; // jrvosse
else return _event;
}
}
template <class T>
class vm { smart pointer class
public:
vm(event* e) {
int p = 0;
char* id = e->option("ref");
if (id) {
p = atoi(id);
}
_self = (T*) p;
}
virtual inline T* operator->() { return _self; }
private:
T* _self;
};
- See some more examples
pointer.c
and pointer.pl.
- Objects - in a mix of styles
- With native support - similar to hush-java support
- key-value transfer of native calls
- virtuality, operator overloading, nested calls, native support
- now we need concurrency ...
- remember query: we do have distribution already
slide: Conclusions
- representation if C++ peer: self pointer
- object/method function call: native functions
- cast self pointer to object: smart vm
slide: Native Objects in Java
package hush.dv.api;
class obscure {
public int _self; // peer object pointer
...
};
public class handler extends obscure {
public static kit tk;
protected Event _event;
public Event dispatch(event ev) {
_event = (Event) ev;
operator();
return _event;
}
public int operator() {
...
return OK;
}
};
package hush.dv.api;
public class kit extends handler {
public kit() { _self = init(); }
protected kit(int x) { }
private native int init();
public native void source(String cmd);
public native void eval(String cmd);
public String result() {
String _result = getresult();
if (_result.equals("-")) return null;
else return _result;
}
private native String getresult();
public native void bind(String cmd, handler h);
...
};
include @lt;hush/hush.h>
include @lt;hush/java.h>
include @lt;native/hush_dv_api_kit.h>
#define method(X) Java_hush_dv_api_kit_##X
JNIEXPORT jint JNICALL method(init)(JNIEnv *env, jobject obj)
{
jint result = (jint) kit::_default; // (jint) new kit();
if (!result) {
kit* x = new kit("tk");
session::_default->_register(x);
result = (jint) x;
}
return result;
}
JNIEXPORT jstring JNICALL method(getresult)(JNIEnv *env, jobject obj)
{
java_vm vm(env,obj);
char *s = vm->result();
if (s) return vm.string(s);
else return vm.string("-");
}
JNIEXPORT void JNICALL method(bind)(JNIEnv *env, jobject obj,
jstring s, jobject o)
{
java_vm vm(env,obj);
java_vm* vmp = new java_vm(env,o,"Handler");
const char *str = vm.get(s);
handler* h = new handler();
session::_default->_register(h);
h->_vmp = vmp;
h->_register(vmp);
vm->bind(str,h);
vm.release(s, str);
}
handler::dispatch
event* handler::dispatch(event* e) {
_event = e;
if (_vmp) {
return ((vm*)_vmp)->dispatch(e);
} else {
int result = this->operator()();
if (result != OK) return 0;
else return _event;
}
}
#include <hush/vm.h>
#include <jni.h>
template< class T >
class java_vm : public vm< T > {
public:
java_vm(JNIEnv* env_, jobject obj_) {
_env = env_;
_obj = obj_;
_self = self();
}
...
event* dispatch(event* e) { java dispatch
call("dispatch",(int)e);
return e;
}
T* operator->() { return _self; }
T* self() {
jfieldID fid = fieldID("_self","I");
return (T*) _env->GetIntField( _obj, fid);
}
void call(const char* md, int i) { // void (*)(int)
jmethodID mid = methodID(md,"(I)V");
_env->CallVoidMethod(_obj, mid, i);
}
private:
JNIEnv* _env;
jobject _obj;
T* _self;
};
- the distributed objects style
- the (dynamically) downloadable code style
- the mobile objects style
Rules of thumb -- selecting an architectural style
- Dedicated hardware or legacy code
distributed objects
- Strategic or secret code
distributed objects
- Many users
downloadable code
- Periodic updates
downloadable code
- Communication and negotiation
mobile objects
slide: Rules of thumb
Cross-platform development
Unix vs NT
- open toolkits and standards -- OMG CORBA
Research/GNU
- AT&T U/WIN -- Posix for 95/NT
- Cygnus -- GNU-win32
Commercial
- NuTCracker/MKS -- porting Unix applications to Windows
- Wind/U, Mainwin -- porting Windows applications to Unix
- Tributary -- developing Unix applications from Windows IDE
slide: Cross-platform development
- deploying platform-independent toolkits
- porting applications from Unix to Windows
- porting applications from Windows to Unix
- What are the elements of a software architecture?
What role does a software architecture description play in development?
- Give a definition of software architecture.
Can you think of alternative definitions?
- What kind of patterns can you think of for distributed object architectures?
- Give an example of a complex software architecture.
Can you relate the description of the architecture to
the definition given earlier?
- Discuss the possible motivations for deploying
embedded logic.
- How would you extend a given imperative or
declarative language with objects?
- Discuss the Java Native Interface.
Does it provide a solution for the problem
posed in the previous question? Explain.
- What determines the choice for an architectural style?
Give an example!
An excellent book on software architectures is [Practice].
You may also want to visit the SEI architecture site at
www.sei.cmu.edu/architecture, which
provides definitions, and a wealth of other
information.
As a discussion of the software engineering implications
of CORBA, you may want to read [CorbaPatterns].
If you are interested in multimedia information systems,
read [MM]. For more information on ACOI,
visit the ACOI website on www.cwi.nl/~acoi .