Einleitung
Trotz der derzeitigen explosionsartigen Vermehrung von Programmiersprachen ist C++ nach wie vor im Einsatz. Laut dem Tiobe-Index vom Juli 2013 handelt es sich dabei um die am vierthäufigsten verwendete Programmiersprache. (Den aktuellen Index finden Sie auf http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html.) Der ISO-Standard 2011 (ISO/IEC 14822:2011, besser bekannt als C++11) ergänzt C++ um weitere Merkmale, die die Akzeptanz dieser Sprache steigern – oder zumindest die Einwände gegen ihre Verwendung abschwächen.
C++ ist nach wie vor eine der besten Möglichkeiten, um hochleistungsfähige Lösungen zu erstellen. Wenn Sie die Produkte Ihres Unternehmens auf Ihrer eigenen Hardware einsetzen, dann verfügen Sie wahrscheinlich selbst über ein ziemlich großes System, das in C++ geschrieben wurde. Ist Ihr Unternehmen schon seit den 1990er-Jahren oder noch länger im Geschäft, dann haben Sie wahrscheinlich ein langjähriges C++-System, und die Chancen stehen nicht schlecht, dass es Ihnen auch in den nächsten Jahren noch erhalten bleibt.
Vorausgesetzt Sie arbeiten mit C++, kommen Ihnen jetzt vielleicht einige Einwände in den Sinn:
Wir schreiben das Jahr 2014! Warum soll ich mich wieder mit dieser schwierigen (wenn auch unterhaltsamen) Sprache beschäftigen, die ich schon vor Jahren aufgegeben habe? Wie kann ich damit leben, ohne mir dabei selbst zu schaden?
Ich bin ein erfahrener C++-Experte. Ich kenne diese leistungsfähige Sprache in- und auswendig und wende sie schon seit Jahren erfolgreich an. Warum sollte ich meine Arbeitsweise ändern?
Wer bezahlt mich dafür, dass ich mich hiermit beschäftige?
Ich selbst habe Anfang der 1990er-Jahre zum ersten Mal mit C++ gearbeitet, bevor Dinge wie Templates (und Template-Metaprogrammierung!), RTTI (RunTime Type Information), STL (Standard Template Library) und Boost aufkamen. Seitdem musste ich einige wenige Male zu dieser leistungsstarken Sprache zurückkehren, was mich immer ein kleines bisschen erschreckt hat. Wie bei jeder anderen Sprache ist es natürlich auch bei C++ möglich, sich ins eigene Fleisch zu schneiden, aber dabei merken Sie es manchmal gar nicht, bis es zu spät ist. Außerdem wird der Schaden höchstwahrscheinlich größer sein als bei der Verwendung von anderen Sprachen.
Wenn Sie schon seit Jahren mit C++ arbeiten, haben Sie sich wahrscheinlich viele Idiome und Techniken angewöhnt, um für eine hohe Qualität des Codes zu sorgen. Eingefleischte C++-Veteranen gehören zu den sorgfältigsten Entwicklern, da große Vorsicht und Achtsamkeit erforderlich sind, um so lange mit C++ zu überleben.
Angesichts dessen könnte man denken, dass die Qualität des Codes von C++-Systemen sehr hoch sein sollte. Trotzdem weisen viele C++-Systeme dieselben Probleme auf, die wir unabhängig von der Sprache immer wieder vorfinden:
Riesige Quellcodedateien mit Tausenden von Zeilen
Memberfunktionen mit Hunderten oder Tausenden von Zeilen unverständlichen Codes
Datenträger voll totem Quellcode
Build-Zeiten von mehreren Stunden
Hohe Anzahl an Fehlern
Zu verzwickte Logik, um schnelle Korrekturen gefahrlos anzubringen
Redundanter Code in Dateien, Klassen und Modulen
Code durchsetzt mit längst überholten Programmiertechniken
Sind diese Mängel unvermeidlich? Nein! Mit testgetriebener Entwicklung können Sie die Entropie Ihres Systems bekämpfen! Sie können damit vielleicht sogar Ihre Begeisterung für die Entwicklungsarbeit wieder neu anfachen.
Wenn Sie einfach nur an der Bezahlung interessiert sind, dann gibt es für Sie genügend Arbeitgeber, die Sie als C++-Entwickler beschäftigen würden. C++ ist jedoch eine sehr technische und nuancenreiche Sprache. Ihr unachtsamer Gebrauch kann zu Mängeln, sporadischen Ausfällen und mehrtägigen Debugsitzungen führen – lauter Dinge, die Ihr Arbeitsverhältnis und Ihre Bezahlung gefährden. Auch hier kann sich testgetriebene Entwicklung als hilfreich erweisen.
Der Aufwand, der dazu erforderlich ist, den Funktionsumfang eines solchen umfangreichen, langjährigen C++-Systems zu erweitern, ist fast immer deprimierend und schwer einzuschätzen. Um einige wenige Codezeilen zu ändern, benötigen Sie oft Stunden oder gar Tage, um die entsprechende Passage zu verstehen. Die Produktivität wird noch weiter dadurch herabgesetzt, dass die Entwickler stundenlang warten müssen, bis endlich klar ist, ob die Änderungen kompiliert werden können, und es dauert noch länger, um zu sehen, ob sich diese Änderungen mit dem Rest des Systems vertragen.
Das muss aber nicht so sein. Testgetriebene Entwicklung (Test-Driven Development, TDD) ist eine in den späten 1990er-Jahren erfundene Technik für das Softwaredesign, mit der Sie Ihr C++-System niederzwingen und unter Kontrolle halten können, während Sie neue Funktionalität hinzufügen. Die Idee, erst die Tests und dann den Code zu schreiben, besteht schon erheblich länger. Der formale TDD-Zyklus wurde jedoch von Ward Cunningham und Kent Beck erfunden – siehe »Test Driven Development: By Example« [Bec02].
Der Hauptzweck dieses Buches besteht darin, Ihnen eine disziplinierte Vorgehensweise für die Anwendung von TDD beizubringen. Sie werden dabei Folgendes lernen:
Die grundlegenden Mechanismen von TDD
Die möglichen Vorteile von TDD
Designmängel mithilfe von TDD gleich im Ansatz bekämpfen
Probleme und Kosten bei der Verwendung von TDD
Verkürzen oder gar Vermeiden von Debugsitzungen dank TDD
Pflegen von TDD
Eignet sich das auch für mich und mein System?
»Was soll dieser ganze Zirkus um Unit Tests? Das hilft mir doch alles nicht viel weiter!«
Vielleicht haben Sie sich schon einmal an Unit Tests versucht. Vielleicht haben Sie gerade jetzt damit zu kämpfen, Unit Tests für ein Altsystem zu schreiben. Angesichts dieser Erfahrungen mag es für Sie so aussehen, als eigne sich TDD für die seltenen Fälle, in denen jemand das Glück hat, an einem neuen System zu arbeiten. Löst es aber die Probleme, die sich bei Ihrer täglichen Arbeit an einem festgefahrenen, anspruchsvollen C++-System stellen?
TDD ist ein sehr nützliches Werkzeug, aber natürlich kein Allheilmittel für den Umgang mit Altsystemen. Zwar können Sie viele der neuen Features, die Sie dem System hinzufügen, mithilfe von TDD entwickeln, aber Sie müssen auch damit beginnen, den überflüssigen Code zu entfernen, der sich im Laufe der Jahre angesammelt hat. Zusätzliche Strategien und Taktiken für eine fortgesetzte Bereinigung sind erforderlich. Dazu müssen Sie Techniken zum Auflösen von Abhängigkeiten und für die gefahrlose Änderung von Code lernen, die Michael Feathers in seinem unverzichtbaren Buch »Effektives Arbeiten mit Legacy Code« [Fea04] vorstellt. Sie müssen wissen, wie Sie ein groß angelegtes Refactoring angehen, ohne entsprechende Probleme hervorzurufen. Dazu sollten Sie die Mikado-Methode kennenlernen (siehe »Behead Your Legacy Beast: Refactor and Restructure Relentlessly with the Mikado Method« [BE12]). In diesem Buch lernen Sie solche Hilfstechniken und mehr.
Es nützt gewöhnlich nicht viel, einfach Unit Tests für bereits bestehenden Code hinzuzufügen (was ich als TAD für Test-After Development bezeichne), da Sie dabei immer damit zu kämpfen haben, »dass das System so ist, wie es ist«. Sie können Tausende von Mannstunden in das Schreiben von Tests investieren, ohne die Qualität des Systems dadurch messbar zu steigern.
Wenn Sie TDD einsetzen, um Ihr System zu gestalten, dann wird Ihr Design definitionsgemäß testfähig. Sie werden dabei auch andere Designs entwickeln als ohne TDD, und zwar Designs, die in vieler Hinsicht besser sind. Je besser Sie verstehen, was gutes Design bedeutet, umso stärker wird Ihnen TDD dabei helfen, es zu erreichen.
Um Ihnen den Wechsel zu einer neuen Ansicht über Design zu erleichtern, betone ich in diesem Buch die Prinzipien für gutes Codemanagement, z.B. die SOLID-Prinzipien für objektorientiertes Design, die in »Agile Software Development, Principles, Patterns, and Practices« [Mar02] beschrieben werden. Ich zeige Ihnen, wie ein Gefühl für gutes Design die weiter gehende Entwicklung und Produktivität fördert und wie TDD aus Ihnen einen aufmerksamen Entwickler macht, der konsistentere und zuverlässigere Ergebnisse erzielt.
Zielgruppe
Dieses Buch ist für C++-Entwickler unabhängig von ihrem Kenntnisstand gedacht – für Anfänger, die gerade einmal ein grundlegendes Verständnis gewonnen haben, bis hin zu alten Hasen, die auch in die esoterischen Aspekte der Sprache eingeweiht sind. Wenn Sie längere Zeit nicht mehr mit C++ gearbeitet haben, werden Sie feststellen, dass Sie sich durch die schnellen Feedbackzyklen von TDD schnell wieder daran gewöhnen werden.
Der Hauptzweck dieses Buches besteht zwar darin, Ihnen...