E-Book, Deutsch, 517 Seiten
Reihe: Rheinwerk Computing
Köhler Softwaredesign und Entwurfsmuster
1. Auflage 2025
ISBN: 978-3-367-10261-7
Verlag: Rheinwerk
Format: EPUB
Kopierschutz: 0 - No protection
Das umfassende Handbuch
E-Book, Deutsch, 517 Seiten
Reihe: Rheinwerk Computing
ISBN: 978-3-367-10261-7
Verlag: Rheinwerk
Format: EPUB
Kopierschutz: 0 - No protection
Ein sauberes, nachhaltiges und erweiterbares Softwaredesign ist die Grundlage professioneller Softwareentwicklung - ob Sie bereits als Softwareentwickler oder -entwicklerin tätig sind, oder sich noch in Ausbildung oder Studium befinden.
In diesem umfassenden Handbuch vermittelt Kristian Köhler praxisnah und modern, wie sich die klassischen Patterns auf der Code-Ebene mit Ansätzen auf Architektur- bzw. Strukturebene verbinden lassen. So erfahren Sie alles über gutes Softwaredesign, wie es in der modernen Softwareentwicklung tatsächlich angewendet wird. Ergänzt wird das Buch durch diverse Code-Beispiele, Best Practices und typische Kontexte, die es als Lehr- und Nachschlagewerk unabdingbar machen.
Aus dem Inhalt:
- Clean Code & Clean Architecture
- Domain Driven Design
- Microservice-Pattern
- Entwurfsmusterbeschreibungen
- Prinzipien für gutes Softwaredesign
- Dokumentation
- Erzeugungs-, Struktur-, Verhaltens-, Architektur- und Datenmuster
- Anwendungsorganisation
- Systemarchitekturmuster
- Cloud-native Patterns
Kristian Köhler ist freiberuflicher Software-Architekt, Berater, Trainer, Entwickler und Consultant. Er berät seine Kunden rund um alle Fragen der Software-Architektur. Seine mehrtätigen Seminare und Praxisworkshops zur Programmiersprache Go sind bei Programmierern heiß begehrt.
Autoren/Hrsg.
Weitere Infos & Material
Materialien zum Buch ... 11 1. Einleitung ... 13 1.1 ... Programmierparadigmen ... 16 1.2 ... Was sind Design-Patterns und wie sind sie entstanden? ... 26 1.3 ... Was sind Softwarearchitektur und Softwaredesign? ... 31 1.4 ... Die Evolution in der Softwareentwicklung und -architektur ... 38 2. Prinzipien für gutes Softwaredesign ... 65 2.1 ... Grundkonzepte der objektorientierten Programmierung ... 66 2.2 ... Clean-Code-Prinzipien ... 78 2.3 ... Die SOLID-Prinzipien ... 114 2.4 ... Information Hiding ... 138 2.5 ... Inversion of Control und Dependency Injection ... 139 2.6 ... Separation of Concerns und Aspektorientierung ... 141 2.7 ... Mit Unit-Tests die Qualität sicherstellen ... 145 3. Sourcecode und Dokumentation der Softwareentwicklung ... 151 3.1 ... Kommentare im Sourcecode ... 152 3.2 ... Dokumentation der Softwarearchitektur ... 166 3.3 ... UML zur Darstellung von Software ... 179 3.4 ... C4 Model zur Darstellung von Softwarearchitektur ... 190 3.5 ... Doc-as-Code ... 199 4. Softwaremuster ... 207 4.1 ... Factory-Method/Fabrikmethode ... 208 4.2 ... Builder/Erbauer ... 217 4.3 ... Strategy/Strategie ... 227 4.4 ... Chain of Responsibility/Zuständigkeitskette ... 235 4.5 ... Command/Kommando ... 244 4.6 ... Observer/Beobachter ... 256 4.7 ... Singleton/Einzelstück ... 266 4.8 ... Adapter/Wrapper ... 274 4.9 ... Iterator ... 284 4.10 ... Composite/Kompositum ... 292 4.11 ... Der Begriff der Anti-Patterns ... 300 5. Softwarearchitektur, -stile und -Patterns ... 307 5.1 ... Die Rolle des Softwarearchitekten ... 308 5.2 ... Softwarearchitekturstile ... 311 5.3 ... Stile zur Anwendungsorganisation und Codestruktur ... 330 5.4 ... Patterns für die Unterstützung der Architekturstile ... 345 6. Kommunikation zwischen Services ... 369 6.1 ... Stile der Anwendungskommunikation ... 371 6.2 ... Resilience Patterns ... 379 6.3 ... Messaging Patterns ... 413 6.4 ... Patterns zur Schnittstellenversionierung ... 438 7. Patterns und Konzepte für verteilte Anwendungen ... 449 7.1 ... Konsistenz ... 450 7.2 ... Das CAP-Theorem ... 451 7.3 ... Das PACELC-Theorem ... 453 7.4 ... Eventual Consistency ... 454 7.5 ... Stateless Architecture Pattern ... 457 7.6 ... Database per Service Pattern ... 463 7.7 ... Optimistic Locking Pattern ... 466 7.8 ... Saga Pattern -- das Verteilte-Transaktionen-Pattern ... 475 7.9 ... Transactional Outbox Pattern ... 480 7.10 ... Event Sourcing Pattern ... 486 7.11 ... Command Query Responsibility Segregation Pattern ... 492 7.12 ... Distributed Tracing Pattern ... 498 Index ... 509
1 Einleitung
Die Softwareentwicklung blickt auf eine lange und bewegte Geschichte zurück, die von diversen Entwicklungen und immer wieder neuen und grundlegenden Ideen und Konzepten geprägt ist. Ziel dieser Entwicklungen war stets die Erstellung besserer Software.
Dieses Kapitel beleuchtet die wichtigsten Programmierparadigmen sowie verschiedene Entwicklungsformen und Einflüsse, die maßgeblich die heutige Softwareentwicklung prägten und wahrscheinlich auch zukünftig prägen werden.
Die Softwareentwicklung hat eine faszinierende Geschichte und Evolution hinter sich. Nachdem Konrad Ernst Otto Zuse im Jahr 1941 den ersten frei programmierbaren funktionsfähigen Computer der Welt vorstellte, wurde immer komplexere Software erstellt.
Zu Beginn wurde Software in Form von maschinenlesbarem Binärcode und als Einheit mit der entsprechenden Hardware entwickelt. Diese Entwicklung in Maschinensprache war zeitaufwendig und – durch die immer größer werdende Komplexität – leider recht fehleranfällig.
Mit der Zeit entstanden höhere Programmiersprachen, mit denen Entwickler und Entwicklerinnen in einer verständlicheren Form Sourcecode erstellen konnten. Bedeutende Meilensteine waren die Erfindung von Fortran (Formula Translation) Mitte der 1950er-Jahren sowie die darauffolgende Veröffentlichung von Cobol (Common Business-Oriented Language) und Lisp (List Processing) im Jahr 1959.
Die damals entstandenen Grundlagen und Konzepte sind heute weiterhin gültig und immer noch im Einsatz – wie z. B. die Backus-Naur-Form (BNR), mit der die Syntax einer Programmiersprache in einer kontextfreien Grammatik dargestellt werden kann.
Backus-Naur-Form und kontextfreie Grammatik
In der Informatik bezeichnet eine kontextfreie Grammatik (CFG) eine spezielle Form einer Grammatik, die zur Beschreibung der Syntax von formalen Sprachen verwendet wird. Die Regeln, die dabei die Struktur der Sprache definieren, hängen nicht vom Kontext ab, in dem sie angewendet werden.
Sie entstand aus der Notwendigkeit, rekursive und hierarchische Strukturen präzise zu beschreiben zu müssen, sowohl in der Linguistik als auch in der Informatik. Noam Chomsky legte in den frühen 1950er-Jahren mit seiner Arbeit den theoretischen Grundstein, und Informatiker wie John Backus und Peter Naur sorgten dafür, dass die sogenannten CFGs ein praktisches Werkzeug für die Spezifikation von Programmiersprachen wurden.
Zu dieser Zeit führte der schnelle Fortschritt der Computer und deren Hardware immer wieder zur Weiterentwicklung bestehender Programmiersprachen oder zur Entstehung neuer, angepasster Sprachen, mit denen bestimmte Probleme effizienter gelöst werden konnten.
Doch auch mit diesen neuen höheren Programmiersprachen konnte in den 1960er-Jahren die erste sogenannte Softwarekrise, nicht verhindert werden: Die Kosten für die Softwareentwicklung überstiegen die Kosten der Hardware. Fehler häuften sich, Termine konnten nicht eingehalten werden und Projekte scheiterten.
Daraufhin entstand in den 1970er-Jahren die Idee des Software-Engineerings, mit dem Ziel, Softwareentwicklung als ingenieurwissenschaftliches Vorgehen zu etablieren, das klaren Methoden, Werkzeugen und Standards folgt. In dieser Zeit entstanden zudem neue Konzepte, beispielsweise das Paradigma der objektorientierten Programmierung oder Vorgehensmodelle wie das Wasserfallmodell.
Diese ganzen Entwicklungen führten zu einer Fülle von Programmiersprachen und Programmierstilen bzw. Programmierparadigmen, die sich in den 1980er-Jahren zusehends konsolidierten und standardisierten.
So entstand z. B. die von Bjarne Stroustrup 1983 vorgestellte Sprache C++, die eine objektorientierte Erweiterung für die 1972 für UNIX entwickelte und verbreitete Sprache C darstellt. Agile Methoden wurden entwickelt, beschrieben und eingesetzt.
Das schnelle Wachstum des Internets in den 1990er-Jahren wurde für die Softwareindustrie zur Herausforderung. Mit ihm entstand eine neue Grundlage für die Entwicklung von Softwaresystemen, und Software wurde oftmals speziell für die Umgebung des Internets entwickelt.
Mit Java stellte Sun Microsystems im Jahr 1995 eine neue, objektorientierte Programmiersprache vor, die sich seitdem einer großen Beliebtheit erfreut und sicher zur Beliebtheit des Programmierparadigmas der objektorientierten Programmierung beigetragen hat.
Neben den vielen neuen Programmiersprachen und Konzepten wurde, wie erwähnt, die Standardisierung und Qualitätssicherung in der Softwareentwicklung immer wichtiger. In den späten 1980er-Jahren entstand aus diesem Grund im Rahmen des Software-Engineerings zusätzlich die Idee, bewährte Lösungen für häufig auftretende Probleme in der Softwareentwicklung mit sogenannten Mustern bzw. Design-Patterns zu standardisieren und somit effiziente und einheitliche Entwicklungsprozesse zu ermöglichen.
In verschiedenen sogenannten Pattern-Katalogen werden seitdem erprobte Lösungen zusammengefasst und beschrieben. Das Buch »Design Patterns: Elements of Reusable Object-Oriented Software« der sogenannten Gang of Four stellt hierbei einen Meilenstein dar und zählt sicher zu einem der bekanntesten und weitverbreitetsten Bücher zum Thema Softwaredesign.
Die Softwareentwicklung hat sich seit ihren Anfängen kontinuierlich verändert und stetig weiterentwickelt. Neue Ansätze, weitere grundlegende Konzepte oder auch zusätzliche Programmiersprachen entstanden, um die unterschiedlichsten Herausforderungen optimaler zu lösen.
Diese Weiterentwicklungen führten nicht nur zu neuen Ansätzen und Methoden in der Softwareentwicklung, sondern auch zur Entstehung innovativer Technologien, die wiederum den Fortschritt der Softwareentwicklung nachhaltig beeinflussten. Ein Beispiel hierfür sind Microservices, ein Programmierstil, der erst durch die Einführung von Container-Technologien, wie z. B. Docker, praktikabel und populär wurde.
In den folgenden Abschnitten werden verschiedene Programmierparadigmen, der Begriff der Design-Patterns sowie wichtige und einflussreiche Entwicklungen bzw. Evolutionen in der Softwareentwicklung ausführlicher beschrieben, da sie meist weiterhin die Basis für aktuelle Produkte, Technologien oder Frameworks darstellen.
Spätestens seit der genannten Softwarekrise ist klar, dass ein Ziel der Softwareentwicklung und des Softwaredesigns immer darin bestehen sollte, gut handhabbaren, wartbaren und wiederverwendbaren Code zu erstellen, der dabei hilft ein Problem zu lösen. Entwickelte Systeme sollen auf lange Sicht zu vertretbaren Kosten wartbar und erweiterbar bleiben.
Wiederkehrende, erkennbare Muster bei der Entwicklung helfen, den Sourcecode entsprechend verständlicher zu machen, sodass die genannten Kriterien besser erfüllt werden können. Sich wiederholende Strukturen und Vorgehen lassen sich nicht nur einfacher erstellen und dokumentieren, sondern können auch von einem Leser leichter erfasst und verstanden werden.
Auf unterschiedlichen Abstraktionsebenen haben sich dementsprechend verschiedene Programmierparadigmen und Lösungsvorschläge bzw. Design-Patterns etabliert, die in diesem Buch in den einzelnen Kapiteln vorgestellt werden. Nur mit dem Wissen über die grundlegenden Konzepte und Vorgehensweisen lassen sich saubere Softwarelösungen erstellen und pflegen.
Softwareentwicklung besteht allerdings nicht nur aus der Erstellung von Sourcecode durch die Entwickler. Die zu erstellenden Lösungen bzw. erstellte Umsetzungen müssen in einer adäquaten Form beschrieben und dokumentiert werden. Nur so kann Software nachhaltig erstellt und später verstanden und gepflegt werden. Auch dieses Thema ist Bestandteil des Buchs und wird in Kapitel 3 betrachtet.
1.1 Programmierparadigmen
Programmierparadigmen sind fundamentale Stile der Programmierung. Sie sind von Programmiersprachen unabhängig und definieren ein grundlegendes Konzept oder eine grundlegende Herangehensweise an die Strukturierung und Organisation von Sourcecode bzw. Software.
Ein Programmierparadigma beeinflusst Entwickler dahingehend, wie sie Probleme angehen, Algorithmen entwerfen oder Code umsetzen. Jedes Paradigma hat seine eigenen Stärken und Schwächen.
In den folgenden Abschnitten werden die bekanntesten und meistverbreiteten Stile vorgestellt.
1.1.1 Strukturierte Programmierung
Die strukturierte Programmierung zählt zum Paradigma der imperativen Programmierung, bei dem eine Abfolge von Anweisungen definiert und ausgeführt wird, um den gewünschten Endzustand zu erreichen.
Als Weiterentwicklung zur grundlegenden imperativen Programmierung zerlegt die strukturierte Programmierung Programme in eine logische, baumartige Struktur und verlangt auf der untersten Code-Ebene eine Beschränkung auf grundlegende Kontrollstrukturen.
Diese Aufgliederung und Strukturierung von Software ermöglicht eine rekursive Dekomposition: Größere zu lösende Probleme werden in höheren bzw. größeren Funktionen zusammengefasst und dann in kleinere, niedere Funktionen untergliedert....