Auszug aus dem Buch

9 783864 902857
Gary McLean Hall
Gary MacLean Hall
Zentrales Thema dieses Buchs ist die Entwicklung von anpassungsfähigem C#-Code,
der agilen Teams die Arbeit erleichtert und
bewährte Prinzipien der objektorientierten
Programmierung (insbesondere SOLID) berücksichtigt. Das Ergebnis ist ein praxisorientiertes
Werk, das Ihnen anhand vieler Code-Beispiele
verdeutlicht, wie Sie in einem agilen Umfeld
Code schreiben können, der flexibel und adaptiv ist. Lernen Sie, wie Sie Unit Tests richtig
einsetzen, welche Methoden der Refaktorierung
effektiv sind, wie Sie wichtige Patterns verwenden und gefährliche Anti-Patterns vermeiden.
Dieses Buch macht Ihren Code agil!
• Die Scrum-Grundlagen: Artefakte, Rollen,
Kennzahlen und Phasen
• Organisation und Management von
­Abhängigkeiten
• Best Practices für Patterns und Anti-Patterns
• Beherrschung der SOLID-Prinzipien:
Single-Responsibility, Open/Closed,
­Liskovsche Substitution
• Schnittstellen richtig managen, um anpassungsfähigen Code zu erhalten
• Unit Tests und Refaktorierung im
­Zusammenspiel
• Einfluss von Delegation und Abstraktion auf
die Anpassungsfähigkeit von Code
• Implementierung von Dependency Injection
• Die praktische Anwendung dieser Prinzipien
im Rahmen eines agilen Projekts
Unter »Microsoft Press« erscheinen
exklusiv im dpunkt.verlag Übersetzungen der besten Microsoft PressTitel.
Thema
• Softwareentwicklung
• C#
Leser
• fortgeschrittene
Programmierer
Website
• http://github.com/
garymclean/
AdaptiveCode
€ 39,90(D)
€ 41,10 (A)
ISBN 978-3-86490-285-7
www.dpunkt.de
Interesse am E-Book?
www.dpunkt.de/plus
McLean Hall
Wie geht man am besten mit wechselnden
Anforderungen im Laufe eines Software­
projektes um? Wie kann man Änderungen im
Code einfach, zeitsparend und ohne Fehler
umsetzen? Agile Methoden und Prozesse wie
Scrum helfen, aber auch der Code selbst muss
adaptiv und agil sein.
Agile Softwareentwicklung mit C#
Agile Softwareentwicklung mit C#
Agile
Softwareentwicklung
mit C#
Best Practices und Patterns
für flexiblen und adaptiven C#-Code
Gary McLean Hall lebt mit seiner Frau, seiner Tochter und
ihrem Hund in Manchester, England. Er ist ein erfahrener Microsoft .NET Framework-Entwickler, der sich auf Patterns und Best
Practices spezialisiert hat. In vielen Jahren als Softwareentwickler hat er in zahlreichen agilen Teams gearbeitet, die sich stark
auf das Ziel konzentriert haben, Code zu erstellen, der äußerst
anpassungsfähig ist. Er hat für Unternehmen wie Eidos, Xerox,
Nephila Capital Ltd. und The LateRooms Group gearbeitet.
Außerdem hat er mehrere Jahre lang ein Softwareconsultingunternehmen geleitet und drei Jahre lang auf Bermuda gelebt und gearbeitet. In allen
Rollen hat er es immer geschafft, eine beeindruckende Balance zwischen pünktlicher Auslieferung eines Softwareprodukts und der Qualität seines Quellcodes zu
finden.
Zu diesem Buch – sowie zu vielen weiteren dpunkt.büchern –
können Sie auch das entsprechende E-Book im PDF-Format
herunterladen. Werden Sie dazu einfach Mitglied bei dpunkt.plus+:
www.dpunkt.de/plus
Gary McLean Hall
Agile Softwareentwicklung mit C#
Best Practices und Patterns für flexiblen
und adaptiven C#-Code
Gary McLean Hall
Übersetzung: Detlef Johannis, Kempten
Lektorat: Thomas Braun-Wiesholler, München
Copy-Editing: Dorothee Klein, Siegen
Herstellung: Frank Heidt
Satz: Gerhard Alfes, mediaService, Siegen, www.mediaservice.tv
Umschlaggestaltung: Helmut Kraus, www.exclam.de
Druck und Bindung: M.P. Mediaprint Informationsdienste, Paderborn
Bibliografische Information der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie;
detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.
ISBN:
Buch
PDF
ePub
978-3-86490-285-7
978-3-86491-690-8
978-3-86491-691-5
Translation Copyright für die deutschsprachige Ausgabe © 2015 dpunkt.verlag GmbH
Wieblinger Weg 17
69123 Heidelberg
Copyright der amerikanischen Originalausgabe © Gary McLean Hall, 2014
Title of American original: Adaptive Code via C#
Published by Microsoft Press
ISBN: 978-0-321-94854-0
Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung
der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags
urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung
oder die Verwendung in elektronischen Systemen.
Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie
Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-,
marken- oder patentrechtlichem Schutz unterliegen.
Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor
noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der
Verwendung dieses Buches stehen.
543210
Für Amelia Rose
– Gary McLean Hall
Inhaltsübersicht
Einführung
1
TEIL I
Eine agile Grundlage
Kapitel 1
Einführung in Scrum
13
Kapitel 2
Abhängigkeiten und Schichten
57
Kapitel 3
Schnittstellen und Entwurfs-Patterns
111
Kapitel 4
Unit-Tests und Refaktorierung
147
TEIL II
Schreiben von SOLID-Code
Kapitel 5
Das Single-Responsibility-Prinzip
Kapitel 6
Das Open/Closed-Prinzip
237
Kapitel 7
Das Liskovsche Substitutionsprinzip
247
Kapitel 8
Interface-Segregation
283
Kapitel 9
Dependency-Injection
317
TEIL III
Entwickeln von adaptivem Code in der Praxis
Kapitel 10
Beispiel für die Entwicklung von adaptivem Code: Einführung
365
Kapitel 11
Beispiel für die Entwicklung von adaptivem Code: Sprint 1
379
Kapitel 12
Beispiel für die Entwicklung von adaptivem Code: Sprint 2
409
TEIL IV
Anhang
Anhang A
Adaptive Tools
Anhang B
GitHub-Codebeispiele
Stichwortverzeichnis
195
427
online
435
vii
Inhaltsverzeichnis
Einführung
1
Wer sollte dieses Buch lesen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
Aufbau dieses Buchs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
Konventionen in diesem Buch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
Systemvoraussetzungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
Downloads: Codebeispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
Danksagungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
Errata und Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
Kostenlose E-Books von Microsoft Press . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
TEIL I
Eine agile Grundlage
Kapitel 1
Einführung in Scrum
13
Scrum und Wasserfall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
Rollen und Verantwortungsbereiche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
Product Owner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Scrum Master . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Entwicklungsteam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Schweine und Hühner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
19
19
20
Artefakte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
Das Scrum-Board . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Diagramme und Kennzahlen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Backlogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
35
40
Der Sprint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
Releaseplanung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sprintplanung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Daily Scrum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sprintvorführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sprint-Retrospektive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Scrum-Kalender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
43
43
45
47
48
50
Probleme beim Einsatz von Scrum und Agile . . . . . . . . . . . . . . . . . . . . . . . . . . .
51
Nicht adaptiver Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
ix
Kapitel 2
Kapitel 3
Kapitel 4
x
Abhängigkeiten und Schichten
57
Die Definition von Abhängigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
Ein simples Beispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Modellieren von Abhängigkeiten in einem gerichteten Graphen . . . . . . .
59
66
Verwalten von Abhängigkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
Implementierungen und Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der verdächtige Geruch von new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Alternativen zur Objekterstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das Anti-Pattern Entourage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das Stairway-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Auflösen von Abhängigkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Abhängigkeitsverwaltung mit NuGet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
71
75
78
80
82
93
Schichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
98
Wichtige Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Grenzüberschreitende Angelegenheiten . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Asymmetrische Schichteinteilung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
99
106
107
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
110
Schnittstellen und Entwurfs-Patterns
111
Was ist eine Schnittstelle? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
112
Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Explizite Implementierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Polymorphie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
112
115
120
Adaptive Entwurfs-Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
121
Das Null-Object-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das Adapter-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das Strategy-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
122
128
131
Mehr Vielseitigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
132
Duck-Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Mixins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Flüssige Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
133
137
143
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
144
Unit-Tests und Refaktorierung
147
Unit-Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
148
Arrange, Act, Assert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Testorientierte Entwicklung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Komplexere Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
148
153
158
Inhaltsverzeichnis
Refaktorieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Vorhandenen Code ändern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
Ein neuer Kontotyp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
TEIL II
Schreiben von SOLID-Code
Kapitel 5
Das Single-Responsibility-Prinzip
195
Das Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
Refaktorieren, um die Übersichtlichkeit zu verbessern . . . . . . . . . . . . . . . . . 199
Refaktorieren, um Abstraktion zu erreichen . . . . . . . . . . . . . . . . . . . . . . . . . . 204
SRP und das Decorator-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Das Composite-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Predicate-Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Branching-Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Lazy-Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Logging-Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Profiling-Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Asynchronous-Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Decorator für Eigenschaften und Ereignisse . . . . . . . . . . . . . . . . . . . . . . . . .
213
218
221
222
223
225
229
231
Verwenden des Strategy-Patterns statt switch . . . . . . . . . . . . . . . . . . . . . . . . . . 233
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
Kapitel 6
Das Open/Closed-Prinzip
237
Einführung in das Open/Closed-Prinzip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
Die Meyer-Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Martin-Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fehlerkorrekturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Lose Kopplung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
237
238
238
239
Erweiterungspunkte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
Code ohne Erweiterungspunkte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Virtuelle Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Abstrakte Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Schnittstellenvererbung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Vererbung in den Entwurf einarbeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
240
240
241
242
243
Geschützte Variation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Prognostizierte Variation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
Eine stabile Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
Gerade genug Anpassungsfähigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
Inhaltsverzeichnis
xi
Kapitel 7
Kapitel 8
Kapitel 9
xii
Das Liskovsche Substitutionsprinzip
247
Einführung in das Liskovsche Substitutionsprinzip . . . . . . . . . . . . . . . . . . . . . .
247
Formale Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
LSP-Regeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
248
248
Verträge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
249
Vorbedingungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nachbedingungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Dateninvarianten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Liskovsche Vertragsregeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Codeverträge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
251
252
253
255
263
Kovarianz und Kontravarianz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
271
Definitionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Liskovsche Typsystemregeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
271
278
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
281
Interface-Segregation
283
Ein Beispiel für Interface-Segregation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
284
Eine einfache CRUD-Schnittstelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Dekorieren mehrerer Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
284
290
294
Verwenden von Schnittstellen in Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
297
Mehrere Implementierungen, mehrere Instanzen . . . . . . . . . . . . . . . . . . . .
Einzelne Implementierung, einzelne Instanz . . . . . . . . . . . . . . . . . . . . . . . . .
Das Interface-Soup-Anti-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
297
300
301
Zerlegen von Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
302
Anforderungen des Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Anforderungen der Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Schnittstellen mit einer einzigen Methode . . . . . . . . . . . . . . . . . . . . . . . . . .
302
309
313
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
315
Dependency-Injection
317
Bescheidene Anfänge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
318
Die Aufgabenlistenanwendung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Erstellen des Objektgraphen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Inversion of Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
321
324
328
Inhaltsverzeichnis
Jenseits der simplen Injection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
Das Service-Locator-Anti-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das Illegitimate-Injection-Anti-Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Composition-Root . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Konvention vor Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
344
348
350
356
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
TEIL III
Entwickeln von adaptivem Code in der Praxis
Kapitel 10
Beispiel für die Entwicklung von adaptivem Code:
Einführung
365
Trey Research . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
Das Team . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Das Produkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
Anfängliches Backlog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
User Stories in Prosabeschreibungen finden . . . . . . . . . . . . . . . . . . . . . . . . . 370
Abschätzen der Story-Punkte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Kapitel 11
Beispiel für die Entwicklung von adaptivem Code:
Sprint 1
379
Planung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
»Ich will Räume anlegen, um Unterhaltungen thematisch einzugrenzen.« . . 382
Der Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
Das Raum-Repository . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
»Ich will eine Liste der Räume ansehen, die Unterhaltungen repräsentieren.« 392
»Ich will die Nachrichten ansehen, die an einen Raum geschickt wurden.« . 397
»Ich will reine Textnachrichten an andere Raummitglieder schicken.« . . . . . . 400
Sprintvorführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
Erste Vorführung von Proseware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402
Sprint-Retrospektive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
Was lief gut? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Was lief schlecht? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Was sollte sich ändern? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Was sollte beibehalten werden? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Überraschungen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
403
404
405
406
407
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
Inhaltsverzeichnis
xiii
Kapitel 12
Beispiel für die Entwicklung von adaptivem Code:
Sprint 2
409
Planung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
409
»Ich will Markdown senden, der richtig formatiert ist.« . . . . . . . . . . . . . . . . . .
411
»Ich will Nachrichteninhalte so filtern, dass sie nicht anstößig sind.« . . . . . .
415
»Ich will Hunderte von Benutzern gleichzeitig bedienen.« . . . . . . . . . . . . . . .
419
Sprintvorführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
421
Sprint-Retrospektive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
422
Was lief gut? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Was lief schlecht? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Was sollte sich ändern? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Was sollte beibehalten werden? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Überraschungen? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
422
423
423
424
424
Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
424
TEIL IV
Anhang
Anhang A
Adaptive Tools
427
Quellcodeverwaltung mit Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
427
Kontinuierliche Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
432
Anhang B
GitHub-Codebeispiele
Stichwortverzeichnis
xiv
Inhaltsverzeichnis
online
435
Einführung
Der Begriff adaptiver Code aus dem Untertitel dieses Buchs liefert eine gute Beschreibung
für das Ergebnis, das Sie erhalten, wenn Sie die Prinzipien des Buchs anwenden: die Fähigkeit von Code, sich an alle neuen Anforderungen oder unvorhergesehenen Szenarien
anpassen zu lassen, ohne dass er dafür in weiten Teilen umgearbeitet werden muss. Dieses
Buch hat das Ziel, viele der aktuellen Best Practices aus dem Bereich der C#-Programmierung mit dem Microsoft .NET Framework in einem Band zusammenzufassen. Ein Teil des
Inhalts wird zwar auch in anderen Büchern behandelt, aber diese Bücher konzentrieren sich
entweder stark auf die Theorie oder sind nicht spezifisch auf die .NET-Entwicklung zugeschnitten.
Programmierung kann ein langsamer Prozess sein. Wenn Ihr Code adaptiv ist, sind Sie
in der Lage, Änderungen schneller, einfacher und mit weniger Fehlern vorzunehmen, als
wenn Sie mit einer Codebasis arbeiten, die Änderungen behindert. Wie jeder Entwickler
weiß, ändern sich Anforderungen. Auf welche Weise mit diesen Änderungen umgegangen
wird, macht den Unterschied zwischen erfolgreichen Softwareprojekten und denen aus, die
aufgrund eines völlig außer Kontrolle geratenen Umfangs steckenbleiben. Entwickler können auf unterschiedliche Arten auf Änderungen der Anforderungen reagieren, wobei zwei
gegensätzliche Standpunkte die Extreme des Spektrums bilden.
Erstens können Entwickler einen inflexiblen Standpunkt einnehmen. Bei diesem Ansatz
ist das Projekt angefangen beim Entwicklungsprozess bis hinunter zum Klassenentwurf so
inflexibel, als wäre es vor 50 Jahren mithilfe von Lochkarten implementiert worden. Wasserfall-Methodologien sind bekannte Vertreter dieser Zunft, der es darum geht sicherzustellen, dass sich Software nicht nach Belieben verändern darf. Ihr Beharren darauf, dass die
Phasen von Analyse, Entwurf, Implementierung und Testen voneinander isoliert bleiben
und nur in einer Richtung nacheinander abgearbeitet werden, macht es schwierig oder
zumindest teuer für den Kunden, irgendwelche Anforderungen zu verändern, nachdem die
Implementierung erst einmal begonnen hat. Der Code braucht daher gar nicht so beschaffen zu sein, dass er leicht zu ändern ist: Der Prozess verbietet praktisch Änderungen.
Der zweite Ansatz, agile Methodologie, besteht nicht etwa darin, lediglich eine Alternative zu solch inflexiblen Methodologien zu finden. Er will eine Reaktion auf sie sein. Agile
1