Freitag, 19. November 2010

Tag 4: 16:40 - 17:40 : Implementing Emergent Design

Übersetzt man emergent und überträgt dies auf das Thema dieses Vortrages, dann könnte der Votrag auch wie folgt überschrieben sein: "Wie man in der Softwreentwicklung ein Design entstehen und wachsen lässt."

Ein Problem in der Softwareentwicklung - vielleicht sogar das Hauptproblem - liegt darin, dass wir zu Beginn eines Softwareprojektes nahezu nichts über die Anwendungsdomäne wissen und sich das notwendige Wissen erst mit der Zeit entwickelt. Idealerweise warten wir also sehr lange (unendlich lange), bis wir genug für die Umsetzung wissen. Dieses Vorgehen ist leider nur bedingt akzeptabel.

Um dieses Thema greifbarer zu machen, zitiert der Vortragende den ehemaligen Chef-Philosophen der US-Regierung Donald Rumsfeld:

"Es gibt bekanntes Wissen. Das sind Sachen, von denen wir wissen, daß wir sie wissen. Es gibt bekanntes Unwissen. Das bedeutet, es gibt Sachen, von denen wir wissen, daß wir sie nicht wissen. Aber es gibt auch unbekanntes Nichtwissen. Das sind Sachen, von denen wir nicht wissen, daß wir sie nicht wissen."

Diese Unwissenheit macht es in der Softwareentwicklung schwer, ein von Anfang an tragfähiges Design zu entwickeln, geschweige denn ein Design, welches sich leicht an den Wissenszuwachs während der Projektlaufzeit anpassen lässt.

Daher zwei weitere seiner Kernaussagen:
  1. Design ist das Zeug, welches man später nur schwer verändern kann.
  2. Architektur ist, sowenig wie möglich von diesem schwer veränderbaren Zeug zu verwenden.
Das heisst nicht, auf Design zu verzichten. Es heisst lediglich, sein Design auf das aktuelle Wissen um die Anwendungsdomäne zu beschränken und daraus eine Gesamtarchitektur zu entwickeln.

In dem Vortrag wurde zwischen essential complexity (also der Anwendungsdomäne natürlicherweise innewohnenden Komplexität) und accidential complexity (also der durch fehlerhafte Designentscheidungen hinzugefügten Komplexität) unterschieden. Beispiele fur letzteres sind
  • Zuviele Anwendungsschichten
  • Zuviel Delegating oder Proxying
weil man sowas vielleicht später mal brauchen könnte. Genau das ist zu vermeiden aber wie kann man den geschilderten Problemen als begegnen?

Die Vorschläge hierzu sind so brilliant wie einfach:
  1. Test driven design: Hier geht es mehr um das Design als um das Testen. Durch den Aufbau von Unit Tests verschafft man sich erstmal ein besseres Verständnis von dem, was der eigentliche Code leisten soll. Man bricht fast automatisch die Zielklassen in kleinere Einheiten herunter und erreicht dadurch eine bessere Abstraktion. Konsequenz: Weniger accidential complexity. Dieses Vorgehen sollte besonders bei neuem Code angewendet werden.
  2. Refactoring: Es gilt das Prinzip von der collective code ownership, d. h. jeder darf den Code des anderen ändern. Durch Refactoring sollten in bestehendem Code frühzeitig veraltete Abstraktionen und grundsätzlich schlechter Code so schnell wie möglich korrigiert werden (Zitat: "fix broken windows whenever you see them"). Andernfalls dienen solche Codebestandteile früher oder später als vermeidlich brauchbare Vorlage für neuen Code (z. B. in heißen Phasen).
  3. APIs und DSLs: APIs Beschreiben die Schnittstellen zu Teilkomponenten, Alleine sich darüber Gedanken machen zu müssen kann schon dazu führen, dass die Fassade eine Teilkomponente für den Aufrufer leichter und eingängiger bedienbar wird und sich die Komponente nur auf das beschränkt,wofür sie gedacht sein soll. Das Ergebnis kann in eine DSL münden, welche die Verwendung der Komponente ausdrucksstärker und (typ-)sicherer macht. Dies geht einher mit Punkt 1.
 Ein Vortrag, der zum Nachdenken anregt und deren Vorschläge einfach nur noch umgesetzt werden müssen. :-)

Keine Kommentare:

Kommentar veröffentlichen