Mittwoch, März 28, 2007

Was ist Software-Architektur?



Was ist Software-Architektur? Wenn Sie nach einer Definition im Internet recherchieren, werden Sie auf eine Unmenge von Vorschlägen stoßen. Wenngleich kein vollkommener Konsens besteht, so findet die Definition von Bass et al. (Software Architecture in Practice, 2nd Ed., Addison-Wesley, 2003) offenbar den meisten Anklag. In der deutschsprachigen Literatur zum Thema wird sie auch gerne herangezogen.

The software architecture of a program or computing system is the structure or structures of the system, which comprises software elements, the externally visible properties of those elements, and the relationships among them.

Ich halte diese Definition für zu kurz gegriffen -- Sie stimmt nicht mit meinen Erfahrungen aus der Praxis überein. Architektur hat nach meinem Verständnis sehr viel mit Ökonomie zu tun.

Die Architektur ist die ökonomischste Form der Beschreibung "innerer" Anforderungen, die nicht mit der Implementierung des Systems identisch ist.

Unter den "inneren" Anforderungen verstehe ich alle Maßgaben an eine Implementierung, der sich eine Organisation unterwirft (siehe auch das Bild). Das beschränkt sich nicht einzig auf Blaupausen zur Software-Organisation und arbeitsteiligen Entwicklung (dem Design), sondern bezieht auch Qualitätsmerkmale mit ein. Ob ein Softwaresystem fehlertolerant, wartbar etc. sein soll, interessiert den Kunden herzlich wenig. In der Realität ist diese Sicht etwas zu schwarz/weiß, aber sie soll klar machen, dass es Gesichtspunkte bei der Architektur gibt, die sich eine Organisation auferlegt, z.B. um ihr Software-Produkt am Markt für ein, zwei Jahrzehnte(!) am Markt positionieren und halten zu können. Es gibt Dinge, die müssen weit über den Horizont eines Kunden entschieden und bei der Software-Entwicklung durchgesetzt werden.

Am Dienstag, 27. März 2007, habe ich meine Sicht der Dinge zusammen mit weiteren Ausführungen im Workshop "Software-Architektur und Migration" im Rahmen der Konferenz "Software Engineering 2007" zur Diskussion gestellt. Ich schloss meinen Vortrag (Titel: "Was ist Software-Architektur? Ein Abgleich mit der Praxis") mit folgendem Fazit:

  • Architektur ist Ausdruck der "internen" Anforderungen

  • Architektur unterliegt ökonomischen Antriebskräften

  • Komponenten-Orientierung und Sichtkonzepte greifen als Modellierungsparadigmen für Architekturen zu kurz

  • Modellierungsansätze müssen Domänen-Modelle integrieren

  • Es fehlt eine Methodik zur Architekturmodellierung


Zu meiner eigenen Überraschung erhielt ich in vielen Punkten Zustimmung; es entstand eine lebhafte Diskussion. Möglicherweise (die Diskussionen dazu waren zu kurz) habe ich den Nerv eines Problems getroffen. Auf alle Fälle gibt es zum Thema "Software-Architektur" noch einiges zu forschen und zu bewältigen. Wir sind noch lange nicht am Ende eines umfassenden Verständnisses von Software-Architektur angekommen.

Montag, März 26, 2007

"Open, reusable object models" in Python

It's roughly three or four weeks ago that I read an interview with Alan Kay ("Alan Kay: The PC Must Be Revamped—Now", CIO Insight, Feb 14, 2007). I found it quite inspiring, began surfing the Internet for more material and finally stumbled across Ian Piumarta's paper "Open, reusable object models" (2007/2/7) (see here also). I was fascinated by all the claims stated in the paper and started to have a closer look. Finally, in order to really understand what he did, I started coding his concept world in Python (my favourite programming language). The code is shown below. It's very close to the pseudo code used in the paper on page 5.

Before you have a look at the Python code, some remarks.

After the third rework of my code, I started renaming concepts. For my taste, e.g. "vtable" is not so intuitive. You will see that I introduce a "Object" class, a "ObjectBehavior" class and a "BehaviorBehavior" class in the code. Furthermore, I changed the names for the methods. They are now called "addClosure", "lookupClosure", "createObject", and "createBehavior". I think, the intentions of the object model get much clearer with the names changed.

When it comes to bootstrapping, I think that the code in Fig. 15 does not precisely re-construct the object model as shown in Fig. 5. When you look at the Python code, you'll see that the hard coded approximation and the bootstrapped model match quite nicely. This was also a main motivation to change names, as mentioned above. I have the feeling that it's now somewhat easier to see what is done in the paper and how the object model is "born".


lookupClosure = "lookupClosure"
addClosure = "addClosure"
createObject = "createObject"
createBehavior = "createBehavior"

class Closure(object):
def __init__(self,method,data=None):
assert callable(method)
self.method = method
self.data = data

def eval(self,obj,*args,**kwds):
assert isinstance(obj,Object)
return self.method(self,obj,*args,**kwds)

class Object(object):
def __init__(self,behavior,data=None):
assert isinstance(behavior,ObjectBehavior)
self.behavior = behavior
self.data = data

class ObjectBehavior(Object): # formerly 'VTable'
def __init__(self,behavior,delegate=None):
assert isinstance(behavior,BehaviorBehavior)
assert delegate == None or isinstance(delegate,ObjectBehavior)
Object.__init__(self,behavior,{})
self.delegate = delegate

class BehaviorBehavior(ObjectBehavior): # formerly 'VTableVTable'
def __init__(self):
ObjectBehavior.__init__(self,self)

def _addClosure(context,obj,key,closure): # see 'addMethod' (Fig. 10)
obj.data[key] = closure

def _lookupClosure(context,obj,key): # see 'lookup' (Fig. 11)
if key in obj.data:
return obj.data[key]
if obj.delegate != None:
return send(obj.delegate,lookupClosure,key)
return None

def _createObject(context,obj,data=None): # see 'allocate' (Fig. 12)
return Object(obj,data)

def _createBehavior(context,obj,delegate=None): # see 'delegated' (Fig. 13)
return ObjectBehavior(obj,delegate)

addClosureClosure = Closure(_addClosure)
lookupClosureClosure = Closure(_lookupClosure)
createObjectClosure = Closure(_createObject)
createBehaviorClosure = Closure(_createBehavior)

def send(obj,messageName,*args,**kwds): # see 'function send()' p.5
assert isinstance(obj,Object)
closure = bind(obj,messageName)
return closure.eval(obj,*args,**kwds)

def bind(obj,messageName): # see 'function bind()' p.5
assert isinstance(obj,Object)
if obj.behavior == obj:
closure = lookupClosureClosure.eval(obj,messageName)
else:
closure = send(obj.behavior,lookupClosure,messageName)
return closure

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Bootstrap the object universe (Fig. 15)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

_bb_ = BehaviorBehavior()
addClosureClosure.eval(_bb_,addClosure,addClosureClosure)
send(_bb_,addClosure,lookupClosure,lookupClosureClosure)
send(_bb_,addClosure,createObject,createObjectClosure)
send(_bb_,addClosure,createBehavior,createBehaviorClosure)

_b_ = send(_bb_,createBehavior,delegate=_bb_) # just an example
_o_ = send(_b_,createObject) # just an example


Any comments are welcome.

Mittwoch, März 21, 2007

Factor: In der Kürze liegt die Würze

Es gibt eine Sprache, die mich immer wieder und zunehmend irritiert: Factor von Slava Pestov. Factor steht in der Tradition von Forth und ist eine rein stack-basierte Sprache. Die angepriesenen Features auf der Factor-Webseite klingen erstaunlich genug, um einen genaueren Blick auf die Sprache zu werfen:

Factor is a general purpose, dynamically typed, stack-based programming language.

Factor has an optimizing native compiler, automatic memory management with a generational garbage collector, a powerful collections library, and various advanced language features such as higher-order programming, continuations, and extensible syntax.

Factor development is done in an interactive environment with a graphical user interface. There is a single-stepping debugger which can travel backwards in time, and extensive documentation. An easy to use C library interface allows one to call C libraries without writing any glue code in C. Bindings for OpenGL, FreeType, X11, Cocoa, and Windows APIs are provided.

Ein faszinierendes Spektrum an Eigenschaften, nicht wahr?

Ich verfolge seit einiger Zeit den Blog von Pestov zu Factor. Was mich erstaunt, ist die Kürze der Programme. Ein paar Beispiele: Das Framework zum Unit-Testing ist kaum eine DIN A4-Seite lang. Pretty Printing sieht von der Codemenge her ebenfalls kurz aus. So manch ein Programm, hier Topological Sort oder ein Sudoko-Solver, präsentiert sich in aufreizender Kürze.

Zum ersten Mal wurde ich auf die Kompaktheit von Factor-Programmen aufmerksam durch doctest, ein Modul, das es auch für Python gibt und dessen Code ich mir irgendwann einmal angeschaut habe. Es sieht nicht so aus, dass das doctest-Modul für Factor mit der selben Power daher kommt. Aber selbst wenn es sich bei Factor nur um eine Realisierung eines Proof-of-Concepts hielte, es schlägt an Kürze alles, was ich von Python oder einer anderen Sprache her kenne. Das hat natürlich unter anderem mit der syntaktischen Einfachheit von Factor zu tun.

Was ist der Grund, dass Factor es erlaubt, so kurze, knackige Programme zu schreiben? Ich habe mich noch nicht ausreichend mit der Sprache beschäftigt, als dass ich wirklich verstanden hätte, mit welchen "Gewürzen" Factor diese Kürze erreicht.

Donnerstag, März 15, 2007

Rechnen mit Quanten, Quanten rechnen

Interessieren Sie sich für Quantenmechanik? Vielleicht wird es einmal Computer geben, die mit so genannten Qubits (Quantenbits) arbeiten. Ganz absurd ist der Gedanke heute nicht mehr, aber die Realisierung solcher Maschinen erweist sich bislang als gar nicht so einfach. Die Technologie dazu steckt in den Kinderschuhen, man ist weit entfernt von einem PC-Ersatz. Doch wer weiß, in 20 Jahren gehören Qubits womöglich zu den "Grundlagen der Informatik". Ich würde mich darüber freuen, weil das völlig interessantes Zeugs ist.

Wenn Sie zu dem Thema "Quantenrechner" herumsurfen, werden Sie interessantes Material finden. Hin und wieder geistern ja auch Meldungen dazu über die Nachrichtenticker. Worüber ich die Tage stolperte, war der Blog-Eintrag "Independence, entanglement and decoherence with the quantum monad". Hier geht es weniger um Quantenrechner als um das Rechnen mit Quanten, was im wesentlichen Wahrscheinlichkeitsrechnung ist. Das Faszinierende daran ist für mich, wie man sich Quantenmechanik programmierbar machen kann. Der Autor verwendet dazu Haskell und ein besonderes Konstrukt, die Monade. Haskell ist eine rein funktionale Programmiersprache; funktionale Sprachen sind vollkommen zustandsfrei. Monaden sind gewissermaßen ein Kunstgriff, Zustände durch die Funktionen zu pipen, ohne dabei das funktionale Paradigma zu verletzen.

Was mich aber endgültig an dem Blog-Eintrag in den Bann zog, war Folgendes: Der Autor betrachtet ein System, das sich zusammensetzt aus Umgebung (environment) und Subsystem. So lange beide unabhängig sind, sind beide isoliert voneinander studierbar. Er sagt, dass wir mit der Vorstellung vertraut sind, dass der Zufluss von etwas in das System, das Ganze (die isolierte Betrachtung) über den Haufen werfen kann. Er zeigt aber auch, dass der Abfluss von etwas aus dem System es ebenfalls "vermasseln" kann -- und das entspricht nicht mehr unbedingt unserer Intuition.

Ich finde diese Gedanken sehr interessant, auch wenn ich die Quantenrechnerei dahinter nicht wirklich verstehe. Können wir das übertragen auf den Umgang mit komplexen Softwaresystemen? Gibt es da Analogien? Vielleicht weiß ich das in 20 Jahren ;-)

Wie auch immer. Wen das Rechnen mit Quantenphänomenen weniger interessiert und wer loslegen möchte, ein Quanten-Linux zu programmieren, nur zu: hier eine Simulation ("A lambda calculus for quantum computation") von André van Tonder dazu.