Agile Software Entwicklung - ein Freifahrtschein?

photodune.net

Wo alles anfing

Agile Softwareentwicklung ist in aller Munde. Die meisten Teams haben diesen Softwareentwicklungsprozess adaptiert - oder zumindest die angenehmsten “Dinge” davon. Den ersten Kontakt mit agilen Methoden hatte ich bei einem Seminar auf der TU - u.a. mit “User Storys”. Ein guter Einstieg für mich war damals das Buch von Mike Cohn [1]. Ein sehr interessantes Zitat, welches bis heute in meinem Hinterkopf hängen geblieben ist:

Words, especially when written, are a very thin medium through which to express requirements for something as complex as software. With their ability to be misinterpreted we need to replace written words with frequent conversations between developers, customers, and users.

Dem ist nichts anzuhängen und ich stimme der Feststellung zu. Aus der HTL kannte ich noch das Wasserfallmodell mit der Phase der “Anforderungsanalyse”, aus der anschließend die Architektur entworfen wird. Dieser Strategie hielt Cohn entgegen, dass der Kunde nicht alles am Anfang Wissen kann bzw. auch Entscheidungen revidieren kann und will, wenn er erste Lebenszeichen des Produkts sieht. Diese Erfahrung kann ich aus der Praxis nur teilen - egal ob Greenfield oder Reimplementierung vorhandener Software (Brownfield Project). Das ist aber nicht wohl eine Eigenheit der Softwarebranche - “nachgebessert” wird überall - Änderungswünsche sind auch keine Seltenheit. Die 100%ige Vollendung eines Produkts kann man nicht erreichen - umso mehr finanziellen und zeitlichen Aufwand man investiert, umso näher wird man an die 100% kommen (q.e.d. ohne Beweisführung - auch wenn die formalen Jungs anderer Meinung sind - aber irgendwo ist der Fehlerteufel immer präsent).

Zurück zu den User-Stories. User-Stories können als Gedankenstütze gesehen werden, die zum gegeben Zeitpunkt als Diskussionsgrundlage mit dem Kunden dienen. Für viele Projekte ist das wohl möglich, jedoch gibt es auch Projekte, in denen eine Firma Anforderungen vieler Kunden aggregiert (tendenziell Produkt statt Projekt getrieben - wenn auch “Sonderschnitzer” möglich). Puh - hier wird es meiner Meinung nach schon haariger, da sich nicht nur ein Kunde in widersprüchliche Anforderungen verwickelt, sondern eine Menge an Kunden sich in widersprüchliche Anforderungen verwickeln kann (und wird). User Requirements Notation (URN) [2][3] ist mir hier untergekommen, die Anwendung durfte ich allerdings noch nicht “live” erleben. Funktionale Anforderungen und Konflikte finden - a Dream comes true:

UCMs are useful for describing multiple scenarios abstractly in a single, integrated view. This promotes the understanding and reasoning about the system as a whole, as well as the early detection of conflicting or inconsistent scenarios.

Mir scheint so, als wäre URN ein akademisches Extrem - das Ende des Spektrums. Modelle haben den Vorteil analysiert werden zu können - aber der Weg zu den Modellen ist oft auch nicht einfach. Der Einsatz von Modellen ist Facettenreich. Auch Model-Based Testing scheint immer mehr Beliebtheit zu finden. Microsoft Research bietet mit Spec Explorer ein Tool dafür an. Weitere Tools sind:

Wie in dem Video von SpecFlow erwähnt wurde - beim Modellieren der Software wird man u.U. Konflikte finden.

The model is usually manually authored from information specifications or requirements. Creating a formal model from the requirements already results in feedback about the initial specifications, because the process of creation requires modelers to ask themselves questions that lead to detection of missing information or to seeking more clarity.

Quelle: https://msdn.microsoft.com/en-us/library/ee620469.aspx

Spec Explorer is used daily by several Microsoft product teams. For example, in one project that tested an interaction protocol between components of the Windows operating system, Spec Explorer discovered 10 times more errors than traditional manual testing, while the time to develop the Spec# model was about the same as the time taken to develop the manual test cases. The model-based testing also increased the coverage of the implementation code from 60 to 70 percent. Even more significant was that the modeling process exposed twice as many design issues as implementation bugs. Discovering these design errors enabled them to be fixed early and prevented them from going into the code. [8]

Auch interessant ist Architecture Hierarchy [4] - eine Formal-Extremvariante ist Architecture Refinement. Wenn man das Prinzip ganz nüchtern betrachtet und von der Grobsicht in die Feinsicht geht, findet man auch Wiedersprüche bzw. Unschärfen in den Anforderungen. Architektur ist zwar schon sehr spezifisch - aber ich denke noch abstrakt genug. Durch das “Verfeinern” der Problematik ist natürlich “Denkkraft” erforderlich - aber damit sollte man auch schon viel schaffen und den einen oder anderen gröberen Konflikt erkennen. Angemerkt sei noch, dass damit natürlich nicht alle Probleme erschlagen werden - aber ich denke, die am meisten schmerzen. Mehr dazu später (siehe Tests bzw. Modellierung / Simulation).

Und nochmals zurück zu den User-Stories. User-Stories haben die Eigenschaft “testbar” zu sein. Das kann hilfreich sein, um festzustellen, ob ein Kundenwunsch tatsächlich eingehalten wurde. Ohne eine Studie vorlegen zu können behaupte ich, dass das bis vor nicht allzu langer Zeit bei vielen Firmen noch händisch gemacht wurde. Der “Testrunner” war hier tatsächlich eine Person (einer dieser Personen schreibt gerade zu euch). Auch nicht immer schlecht, da Exploratives-Testen (was meist trotz schrittweisen Testvorgaben passiert) durchaus neue Erkenntnisse bringen kann - allerdings reines manuelles testen? Unmöglich! Findet man einen Fehler und bekommt eine neue Version - man müsste wieder das Testbuch von neuem beginnen - ein endloses Spiel. Ergänzend zur obigen Fragestellung sollte festgehalten werden, dass gute Tests durchaus widersprüchliche Anforderungen finden können (wenn auch in einem recht späten Stadium). Aber diese Hürde wurde in der agilen Welt schon von vielen Teams genommen - zumindest in irgendeiner Art und Weise. Testgetriebe Entwicklung macht nicht nur das Leben der Entwickler einfacher, sondern auch jenes der Tester. Unit-Tests, Behavior Driven Development usw. scheinen eine immer größere Beliebtheit bei Entwickler zu haben. Einen flotten Test in der Gherkin-Notation oder einen Unit-Tests - alles kein Kopfschmerz.

Sonnenschein-Tests

Und hier kommen wir zum ersten Phänomen, das ich schon seit einiger Zeit miterleben darf und wo uns die Agilität anscheinend zu agil macht: “Sonnenschein Tests”. Tests über Gut-Fälle zu schreiben macht immer Laune - man muss sich keine Gedanken über “aber was wäre wenn” machen. Es ist sicher nicht schuld der agilen Methodik oder User-Stories - trotzdem verleiten “Akzeptanzkriterien” anscheinend gerne zu vergessen, wann etwas nicht akzeptiert wird. “Akzeptanzkriterien” sind meist im Dunstkreis der businessnahen Codebasis. Extrem wichtig sind “Schlechtwetter-Tests” aber auch im Infrastrukturcode.

photodune.net

Es scheint so, als ob das auch gerne bei Software akzeptiert wird. Bei Finanzsoftware kann man sich sogar darauf berufen, dass Benutzer das womöglich falsche Ergebnis (ausgelöst durch einen Edge-Case) ohnehin selbst kontrollieren müssen. Bei einer Online-Kartenbestellungswebseite - “Internal Server Error” - der Kunde wird es schon nochmal probieren oder sein Ticket auf anderem Wege kaufen. Der finanzielle Schaden oder der Impact auf Menschen ist nicht gegeben. In der Telekommunikationsbranche? Hier wird es schon haariger. Aber das Problem ist durchaus nicht ungelöst. Ein Ausflug in die Embedded-Welt - ein paar Zitate [5]:

Simulation-based fault injection, which assumes that errors or failures occur according to predetermined distribution, is useful for evaluating the effectiveness of fault-tolerant mechanisms and a system’s dependability; it does provide timely feedback to system engineers

To do prototype-based fault injection, faults are injected either at the hardware level (logical or electrical faults) or at the software level (code or data corruption) and the effects are monitored.

Die Ideen lassen sich durchaus adaptieren. Ziel muss es jetzt nicht, einzelne Bits im Arbeitsspeicher zu manipulieren - aber ein korruptes Dateisystem oder eine streikende Datenbank - warum nicht? Ich bin der festen Überzeugung, dass diese Art von Szenarien auch in einem frühen Stadium analysiert und erfasst werden sollten, weil sie durchaus Impact auf das Design der Software haben.

Hilfe, meine Tests erschlagen mich

Hat man sich entschlossen agile zu sein und die Hilfsmittel der Regressionstests anzuwenden, so kann das auch gewaltig in die Hose gehen. Ist das Code-Design zu agile entstanden (Ala Coke Zero - Zero Up-Front Design), so übernimmt der Testcode auch die Struktur des zu testenden Codes. Die Folgen: ein Refactoring tut nicht weh - es schmerzt. Neben den kleinen Änderungen des Produktivcodes kommt noch eine Unmenge an Testcode dazu, der geändert werden muss. Und meist ist Testcodeänderung mit mehr Aufwand verbunden. Das Shotgun Surgery Antipattern schlägt also bei schlechtem Design und zu viel Test-Code sehr hart zu.

Gherkin-Tests erfreuen sich auch immer mehr Beliebtheit. Der Vorteil ist eine Living Documentation die auch von nicht Domain Experten verstanden wird. Eine gute Sache wenn man sie im richten Maß und an der richtigen Stelle einsetzt. Den positiven Effekt sehe ich für Test Ingenieure, die mit Softwareentwicklung nicht viel zu tun haben, und die sich Tests durchaus selbst zusammenstellen können bzw. sich nicht nur anhand kryptischer Testnamen etwas zusammenreimen müssen.

In Frage stelle ich hier, ob es wirklich für die Dokumentation geeignet ist. Dazu gibt es Artikel wie Sand am mehr. Auch wird man in diesem Zusammengang oft auf FitNesse oder JBehave / Specflow stoßen. Bekommt man eine riesige Codebase vorgesetzt und will etwas ändern - man gelangt direkt zu Szenarien und kann die beabsichtigte Verwendung erahnen - praktisch. Ich kann dadurch meine Aufgabe eventuell erledigen - das Verständnis ist allerdings oft sehr lokal - das globale Verständnis fehlt. Da wir ja agil sind, werde ich außer meiner “Living Documentation” nicht viel finden - Diagramme? Nein - die sind ja nicht aktuell und machen nur Zusatzaufwand. Auch hier lohnt sich wieder ein Exkurs in die Embedded-Welt. In der Embedded-Welt wird schon modelgetriebene Dokumentation (eigentlich nur ein Seiteffekt eines Models) betrieben. Auch Reverseengineering aus dem Code zu einem Model ist möglich.

Model Based Testing wurde bereits erwähnt und kann u.U. auch helfen, wenn man eine Vielzahl an Testvariationen händisch schreibt, diese sich aber anders besser beschreiben ließen. MBT werde ich einem gesonderten Artikel genauer analysieren.

Model Based Software Development (MBSD)

Die Architektur einer Software. Ein einleitendes Zitat [7]:

  • Every application has an architecture.
  • Every application has at least one architect.
  • Architecture is not a phase of development.

Referring back to the analogy to buildings […], it is evident that every building has an architecture. That is not to say that every building has an honorable, or elegant, or effective architecture: Sadly, many buildings evince architectures that ill-serve their occupants and shame their designers.

Dieses Phänomen scheint tatsächlich präsenter zu sein als man denkt. Wieviel Upfront-Design ist genug? Brauch ich überhaupt Upfront-Design? Lean Architecture? Ich hab das Buch angefangen zu lesen - dann aber abgebrochen - zu viel um den heißen Brei “herumgeschrieben”. Kurz zusammengefasst:

  • “Lean” means to get rid of waste (like unnecessary documentation), inconsistency (like mismatched interfaces), and irregularity spaced development work in production.
  • In Lean software architecture, we use Domain-Driven Design (DDD) to come up with the system form. The result of this process is the shape of the system.

photodune.net

Auch andere Entwickler zweifeln an ähnlichen Strategien wie Emergent-Architecture. Über Agile Architekturen findet man auch einiges. Im Paper-Dschungel gibt’s auch was [9].

Was hier versucht wird ist mir ein Rätsel. Ich glaube, man kann nicht alle Projekte über einen Kamm scheren. Wie eingangs erwähnt - jede Software hat eine Architektur. Architekturentscheidungen sind essentielle Entscheidungen, welche im Nachhinein Kopfweh und Kosten verursachen, wenn man sie ändern will oder muss. Wenn die Software-Architektur tatsächlich so viel Analogien zur Bauarchitektur aufweist: Ein Architekt im Bauweisen weiß auch wann genug ist. Die Pläne haben dort den Vorteil, dass eine klare Struktur vorgegeben wird, damit bei den Bauarbeiten kein Chaos ausbricht. Und dieses Chaos wird bei einem Softwareprojekt ausbrechen, wenn man Domain-Driven-Design (DDD) nur in den Grundzügen anwendet und den Entwicklern nicht die Schranken weist durch einen Plan.

Infrastrukturcode und Businesscode trennen - man muss alles anscheinend einem Namen geben - gut dann eben DDD. “Dort” nennt man eine Grobseparierung der Domänen “ContextMap”. Wie und wo wird meine “ContextMap” festgehalten? Wie stelle ich fest, ob das was ich mir auf dem Blackboard ausgedacht habe, von Entwickler 2. Generation (welche also nicht von Projektstart an dabei waren) eingehalten wird? Wie erreiche ich eine gute Traceability (siehe Visual Studio Tools wo man e.g. auch Änderungs-Tickets an Modelle heften kann)?

Angriff von der theoretischen Seite: Einen interessanten Ansatz liefert Taylor [7]. Die Architektur als Components, Connectors und Modelling Configuration (Beschreibung der architekturellen Struktur - festlegen der Topologie) zu beschreiben. Was hat es mit Modellen auf sich?

Model-based engineering is the creation and analysis of models of your system such that you can predict and understand its capabilities and operational quality attributes (e.g., its performance, reliability, or security). … Analyzable models provide a foundation for prediction and design assurance by enabling meaningful assessment and reasoning about their properties and the properties of the systems they represent. Model properties are addressed in the development process and focus on quality attributes such as modifiability and maintainability, while system properties address operational quality attributes such as performance, safety, and reliability. [6]

Man baut ein Modell, synthetisiert Code und kann auch noch auf dem Modell e.g. Simulation und Analysen durchführen. Bei der Diplomarbeit bin ich auf ArchStudio gestoßen - werde darüber noch berichten. Auch Visual Paradigm macht einen guten Eindruck. Ich bin sehr positiv gestimmt auf diese Disziplin und werde sicher noch mehr davon berichten. Visual Studio bietet übrigens auch einiges - wobei hier Modellierung nicht das Hauptaugenmerk zu sein scheint.

Ein weiterer interessanter Ansatz ist jener von George Fairbanks. Dieser definiert die Menge des Up-Front Designs anhand des Risikos - einer sehr interessanter Ansatz, den ich noch in einem gesonderten Artikel beschreiben werde, da er mir extrem gut gefällt.

Standup-Meeting & Common Codebase

Zwei lustige Dinge der agilen Welt - ich finde beide toll. Allerdings gibt es auch sehr fragwürdige Ausprägungen. Ersteres ist wohl einer jener Empfehlungen, die am liebsten umgesetzt wird. Man stellt sich an einen runden Tisch und erzählt, was man gerade so macht. Prinzipiell eine gute Idee, wenn man eine gemeinsame Codebase hätte. Das ist jedoch selten der Fall (zumindest bewege ich mich anscheinend in Kreisen, wo das nicht der Fall ist). Kommt man dann mit Fremd-Code in Berührung - der Tag ist gelaufen. Warum ist das so? Ich persönlich vermisse hier ein wenig “Traceability” (wie ist es zu den Entscheidungen gekommen) und “Refinement” (der Blick vom Großen aufs Kleine). Legt man einem frischen Beamten den ganzen Stadtplan hin und gibt ihm eine Aufgabe - er wird verzweifeln. Erst Gruppierungen (Bezirke - in Software Komponenten) und die Anordnung (e.g. Parzellensystem in Amerika - in Software diverse Designdisziplinen) helfen uns vom Großen ins Kleine zu denken.

Verweise

[1] Cohn, Mike. User stories applied: For agile software development. Addison-Wesley Professional, 2004.
[2] Amyot, Daniel. “Introduction to the user requirements notation: learning by example.” Computer Networks 42.3 (2003): 285-301.
[3] Amyot, Daniel, and Gunter Mussbacher. “User requirements notation: the first ten years, the next ten years.” Journal of software 6.5 (2011): 747-768.
[4] Donohoe, Patrick, ed. Software Architecture. Vol. 12. Springer Science & Business Media, 1999.
[5] Hsueh, Mei-Chen, Timothy K. Tsai, and Ravishankar K. Iyer. “Fault injection techniques and tools.” Computer 30.4 (1997): 75-82.
[6] Feiler, Peter H., and David P. Gluch. Model-Based Engineering with AADL: An Introduction to the SAE Architecture Analysis & Design Language. Addison-Wesley, 2012.
[7] Taylor, Richard N., Nenad Medvidovic, and Eric M. Dashofy. Software architecture: foundations, theory, and practice. Wiley Publishing, 2009.
[8] Utting, Mark, and Bruno Legeard. Practical model-based testing: a tools approach. Morgan Kaufmann, 2010.
[9] Hayata, Tomohiro, Jianchao Han, and Mohsen Beheshti. “Facilitating Agile Software Development with Lean Architecture in the DCI Paradigm.“Information Technology: New Generations (ITNG), 2012 Ninth International Conference on. IEEE, 20

Weitere Themen

Soweit mal die ersten Brocken. Folgende Themen werde ich in einem Folgeartikel noch behandeln:

  • Vom Sonnenschein zum Schlechtwetter - Fault Tolerance
  • Coding Dojo
  • Code Reviews & Pair Programming
  • Polyglot Programming
  • Software Security