Software architecture

7


Additional keywords and phrases: components, information architecture, multimedia information retrieval, feature detection, portability


slide: Software architecture


Elements of architecture

 [Wolf]


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]



slide: Technological infrastucture


Distributed object patterns

 [CorbaPatterns]



slide: Distributed object patterns



slide: The extended ACOI architecture



  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



slide: MIDI features



  
  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]).
  


slide: 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;
  } 
  

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



slide: Keyboard interface



slide: User Query Processing

subsections:


Motivation: e.g the IM&SE Colloquium.

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"); 
    logic.java
    pl.eval("X:assistant(X)"); String res = null; while ( (res = pl.result()) != null ) { System.out.println("
  • " + res); }
  • 
      
    remote.pl
    :- source('www.cs.vu.nl/~eliens/db/se/people.pl'). :- source('www.cs.vu.nl/~eliens/db/se/institute.pl'). :- source('www.cs.vu.nl/~eliens/db/se/property.pl'). :- source('www.cs.vu.nl/~eliens/db/se/query.pl').



    slide: Remarks

    
      interface query { 
    query.idl
    void source(in string file); long eval(in string cmd); string result(in long id); oneway void halt(); };


    slide: Distributed knowledge servers



    Look at the debug information


    slide: Distributed knowledge processing - example



    Look at the debug information


    slide: Distributed knowledge processing - example (2)



    slide: Conclusions



    slide: Objects in Prolog



    slide: Native Objects


    Objects in Prolog


    slide: Objects in Prolog

    requirements


    
      
              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
      


    slide: Native Objects in Prolog



    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;
              }
      

    
      
    in handler.c
    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; };


    slide: Conclusions



    slide: Native Objects in Java

    
      package hush.dv.api;
      
      class obscure { 
    obscure
    public int _self; // peer object pointer ... };

    
      public class handler extends obscure { 
    handler
    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 { 
    kit
    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.c
    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 > { 
    java_vm
    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; };

    subsections:



    slide: Exchanging perspectives


    Rules of thumb -- selecting an architectural style


    slide: Rules of thumb


    Cross-platform development

    Unix vs NT


    Research/GNU

    Commercial


    slide: Cross-platform development


    Elements of architecture

    1



    slide: Section 7.1: Elements of architecture


    Case study -- multimedia feature detection

    2



    slide: Section 7.2: Case study -- multimedia feature detection


    Crossing boundaries

    3



    slide: Section 7.3: Crossing boundaries


    Architectural patterns and styles

    4



    slide: Section 7.4: Architectural patterns and styles


    Cross-platform development

    5



    slide: Section 7.5: Cross-platform development

    1. What are the elements of a software architecture? What role does a software architecture description play 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!

    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 .