Principles of Object-Oriented Software Development Software Architecture Software Architecture Introduction Elements of architecture Case study -- multimedia feature detection Crossing boundaries Architectural patterns and styles Cross-platform development Summary Q/A Literature Software architecture • 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 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 http://www.sei.cmu.edu/architecture/definitions.html 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. Bass et al. 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 Distributed Object Patterns [CorbaPatterns] Framework (class hierarchies) Applications (wrappers) System Enterprise Intra/Internet (horizontal, vertical, metadata) (reference models, infrastructure, policies) (standards) Case study multimedia feature detection The extended ACOI architecture The ACOI framework detector world; detector people; detector company; finds the name of the world checks name, eliminates institutes looks if there are at least two persons atom str name; community: world people company; world: name; people: person*; person: name; 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); } ... } 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"); ... Database updates The anatomy of a MIDI feature detector MIDI features detector song; detector lyrics; detector melody; to get the filename extracts lyrics extracts melody atom str name; atom str text; atom str note; song: file lyrics melody; file: name; lyrics: text*; melody: note*; 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]). Prolog representation Processing MIDI file 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; } The melody detector Queries -- the user interface Keyboard interface User Query Processing Crossing boundaries Subsections: Embedded logic -- crossing the paradigm boundary Native objects -- crossing the language boundary Combining Java and C++ Embedded Logic -- crossing the paradigm boundary <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(['<li>', 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("<li> " + res); } logic.java Distributed knowledge servers remote.pl :- source('http://www.cs.vu.nl/~eliens/db/se/people.pl'). :- source('http://www.cs.vu.nl/~eliens/db/se/institute.pl'). :- source('http://www.cs.vu.nl/~eliens/db/se/property.pl'). :- source('http://www.cs.vu.nl/~eliens/db/se/query.pl'). interface query { void source(in string file); long eval(in string cmd); string result(in long id); oneway void halt(); }; query.idl Native objects crossing the language boundary Objects in Prolog • 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) • low overhead, especially when not needed • natural syntax for object clause definitions • support for native objects midi(This):midi, Self = self(This), Self:open('a.mid'), Self:header(0,1,480), Self:track(start), Self:melody([48,50,51,53,55]), Self:track(end), create midi object // c d es f g, minor indeed end track midi :- use(library(midi:[midi,lily,music,process])). :- declare(midi:object,class(midi),[handler]). midi_midi(This) :midi(This):handler(H), declare(H,new(midi(This)),[],[],_). constructor // gets Handler from class 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 C++ bindings int kit_object::operator()() { kit_object 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; } template <class T> class vm { 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; }; smart pointer class Combining Java and C++ package hush.dv.api; class obscure { obscure public int _self; peer object pointer ... }; 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); ... }; kit kit.c #include <hush/hush.h> #include <hush/java.h> #include <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 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) { call("dispatch",(int)e); return e; } java_vm java dispatch 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; }; Architectural patterns and styles Subsections: From technology to style Case study -- perspectives in visualization From technology to style • the distributed objects style • the (dynamically) downloadable code style • the mobile objects style distributed objects Component Connector Creation Location Client Server object ORB server server fixed extensible downloadable code mobile objects object/class various client client extensible fixed agent methods any any extensible extensible Feature classification Case study -- perspectives in visualization Exchanging perspectives Guidelines for selecting a 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 Cross-platform development 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 • deploying platform independent toolkits • porting applications from Unix to Windows • porting applications from Windows to Unix Summary 1 Elements of architecture • processing elements -- transformation on data • data elements -- contain information • connections -- glue that holds elements together 2 Case study -- multimedia feature detection • feature grammar -- structure • embedded logic -- rules for recognition • architecture -- multimedia information system 3 Crossing boundaries • embedded logic -- crossing the paradigm boundary • native objects -- crossing the language boundary • combining Java and C++ 4 Architectural patterns and styles • technology matrix -- from technology to style • case study -- visualization perspectives 5 Cross-platform development • from Unix to Windows -- AT&T U/Win, Cygnus GNU-win32 • from Windows to Unix -- Wind/U, Mainwin Questions 1. What are the elements of a software architecture? What role plays a software architecture description in development? 2. Give a definition of software architecture? Can you think of alternative definitions? 3. What kind of patterns can you think of for distributed object architectures? 4. Give an example of a complex software architecture. Can you relate the description of the architecture to the definition given earlier? 5. Discuss the possible motivations for deploying embedded logic. 6. How would you extend a given imperative or declarative language with objects? 7. Discuss the Java Native Interface. Does it provide a solution for the problem posed in the previous question? Explain. 8. What determines the choice for an architectural style? Give an example! Further reading An excellent book on software architectures is [Practice]. You may also want to visit the SEI architecture site at http://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 http://www.cwi.nl/~acoi .