"use strict";(self.webpackChunkgatsby_starter_default=self.webpackChunkgatsby_starter_default||[]).push([[554],{2632:function(e,n,t){t.d(n,{Z:function(){return l}});var r=t(7294),i=t(5444),a=t(7450);function l(e){var n=e.pages;return r.createElement("nav",{className:"bg-diit border-b border-gray-200 flex","aria-label":"Breadcrumb"},r.createElement("ol",{role:"list",className:"max-w-screen-xl w-full mx-auto px-4 flex space-x-4 sm:px-6 lg:px-8"},r.createElement("li",{className:"flex"},r.createElement("div",{className:"flex items-center"},r.createElement(i.Link,{to:"/",className:"text-white hover:text-blue-300"},r.createElement(a.tvw,{className:"flex-shrink-0 h-5 w-5","aria-hidden":"true"}),r.createElement("span",{className:"sr-only"},"Home")))),n.map((function(e){return r.createElement("li",{key:e.name,className:"flex"},r.createElement("div",{className:"flex items-center"},r.createElement("svg",{className:"flex-shrink-0 w-6 h-full text-white",viewBox:"0 0 24 44",preserveAspectRatio:"none",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true"},r.createElement("path",{d:"M.293 0l22 22-22 22h1.414l22-22-22-22H.293z"})),r.createElement(i.Link,{to:e.href,className:"ml-4 text-sm font-medium text-white hover:text-blue-300","aria-current":e.current?"page":void 0},e.name)))}))))}},7198:function(e,n,t){var r=t(7294),i=t(5444),a=t(1615),l=t(3375),s=t(5186);n.Z=function(e){var n=e.children;(0,i.useStaticQuery)("3649515864");return r.createElement(r.Fragment,null,r.createElement(s.q,{htmlAttributes:{lang:"de-DE"}}),r.createElement("div",{className:"relative h-full bg-gray-100 font-sans"},r.createElement(a.Z,null),r.createElement("main",null,n)),r.createElement(l.Z,null))}},4100:function(e,n,t){t.r(n),t.d(n,{default:function(){return s}});var r=t(7294),i=t(7198),a=t(6179),l=t(2632);function s(){return r.createElement(r.Fragment,null,r.createElement(i.Z,null,r.createElement(a.Z,{title:"Artikel: Die SOLID Prinzipien der OOP"}),r.createElement(l.Z,{pages:[{name:"Artikel",href:"/Artikel",current:!1},{name:"Die SOLID Prinzipien der OOP",href:"/Artikel/SolidPrinziples",current:!0}]}),r.createElement("div",{className:"relative py-16 bg-white overflow-hidden max-w-3xl mx-auto mt-10 sm:rounded-lg"},r.createElement("div",{className:"hidden lg:block lg:absolute lg:inset-y-0 lg:h-full lg:w-full"},r.createElement("div",{className:"relative h-full text-lg max-w-prose mx-auto","aria-hidden":"true"},r.createElement("svg",{className:"absolute top-12 left-full transform translate-x-32",width:404,height:384,fill:"none",viewBox:"0 0 404 384"},r.createElement("defs",null,r.createElement("pattern",{id:"74b3fd99-0a6f-4271-bef2-e80eeafdf357",x:0,y:0,width:20,height:20,patternUnits:"userSpaceOnUse"},r.createElement("rect",{x:0,y:0,width:4,height:4,className:"text-gray-200",fill:"currentColor"}))),r.createElement("rect",{width:404,height:384,fill:"url(#74b3fd99-0a6f-4271-bef2-e80eeafdf357)"})),r.createElement("svg",{className:"absolute top-1/2 right-full transform -translate-y-1/2 -translate-x-32",width:404,height:384,fill:"none",viewBox:"0 0 404 384"},r.createElement("defs",null,r.createElement("pattern",{id:"f210dbf6-a58d-4871-961e-36d5016a0f49",x:0,y:0,width:20,height:20,patternUnits:"userSpaceOnUse"},r.createElement("rect",{x:0,y:0,width:4,height:4,className:"text-gray-200",fill:"currentColor"}))),r.createElement("rect",{width:404,height:384,fill:"url(#f210dbf6-a58d-4871-961e-36d5016a0f49)"})),r.createElement("svg",{className:"absolute bottom-12 left-full transform translate-x-32",width:404,height:384,fill:"none",viewBox:"0 0 404 384"},r.createElement("defs",null,r.createElement("pattern",{id:"d3eb07ae-5182-43e6-857d-35c643af9034",x:0,y:0,width:20,height:20,patternUnits:"userSpaceOnUse"},r.createElement("rect",{x:0,y:0,width:4,height:4,className:"text-gray-200",fill:"currentColor"}))),r.createElement("rect",{width:404,height:384,fill:"url(#d3eb07ae-5182-43e6-857d-35c643af9034)"})))),r.createElement("div",{className:"relative px-4 sm:px-6 lg:px-8"},r.createElement("div",{className:"text-lg max-w-prose mx-auto"},r.createElement("h1",null,r.createElement("span",{className:"block text-base text-center text-blue-500 font-semibold tracking-wide uppercase"},"Meine ganz persönliche Sicht"),r.createElement("span",{className:"mt-2 block text-3xl text-center leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl"},"Die SOLID Prinzipien der OOP")),r.createElement("p",{className:"mt-8 text-xl text-gray-500 leading-8"},"Als Programmierer von objekt-orientierten Programmen sollte man unbedingt die",r.createElement("a",{href:"https://expleoacademy.com/dach/service/glossar/erklaerung/s-o-l-i-d-principles"}," SOLID Prinzipien")," kennen. Diese sind schon häufig ausführlich beschrieben worden. In diesem Artikel beschreibe ich meine ganz persönliche Sicht darauf und welche Erfahrungen ich damit gemacht habe.")),r.createElement("div",{className:"mt-6 prose prose-blue prose-lg text-gray-500 mx-auto"},r.createElement("h2",null,"Solide im wahrsten Sinne"),r.createElement("p",null,"Soweit es mir bekannt ist, wurden die SOLID Prinzipien Anfang 2000 zusammengestellt aus verschiedenen Veröffentlichungen von Robert C. Martin. Sie waren eine Sammlung von Best Practices für die Entwicklung von objekt-orientierten Programmen."),r.createElement("p",null,"Seitdem hat sich viel getan in der Software-Entwicklung. Neue und schnellere Hardware wurde erfunden, neue Programmiersprachen erschaffen und immer mehr Menschen entwickeln Software. Aber was ist geblieben?"),r.createElement("ul",null,r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Auf Version 1 folgt Version 2.")," Sobald ein Programm fertig entwickelt ist, kommt schon die nächste Anforderung, die umgesetzt werden muss. Hoffentlich passt das alles gut zusammen."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Es muss schnell gehen.")," Auftraggeber sind immer noch ungeduldig und neue Funktionen verkaufen sich nun mal am Besten. Für Refactoring ist selten Verstädndnis im Management."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Software wird häufiger gelesen als geschrieben.")," Wird eine Software in einem Unternehmen entwickelt, verdingen sich über die Jahre eine ganze Reihe von verschiedenen Programmierern daran. Nicht selten sind die ursprünglichen Entwickler nach einiger Zeit nicht mehr im Unternehmen und neue Leute müssen den Code von anderen verstehen, übernehmen und erweitern."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Code steht nicht in einer einzigen Datei.")," Der Umfang von Software kann ganz schnell beträchtlich werden und früher wie heute wird der Code auf viele Dateien und Module verteilt. Durch unachtsam gewählte Abhängigkeiten kann ein Software-Projekt ganz leicht unwartbar werden."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Die SOLID Prinzipien sind immer noch aktuell.")," Das ist das Erstaunliche! Obwohl sich so viel in der OO-Welt getan hat; die SOLID Prinzipien sind wirklich grundsolide und erweisen sich so nützlich und sinnvoll wie eh und je.")),r.createElement("h2",null,"Meine Sicht auf die SOLID Prinzipien"),r.createElement("p",null,"Im Folgenden werde ich auf die einzelnen Prinzipien eingehen, aber sie nicht erklären, sondern meine ganz persönliche Sicht und Erfahrungen mit ihnen darlegen. Es würde mich freuen, von anderen Entwicklern zu hören, ob sie meine Sicht teilen und ähnliche Erfahrungen gemacht haben oder ob sie es gänzlich anders sehen."),r.createElement("blockquote",null,r.createElement("p",null,"Vielleicht werde ich Programmierer. Geistige Arbeit ist nicht so anstrengend.")),r.createElement("h2",null,"Single Responsibility Principle"),r.createElement("blockquote",null,r.createElement("p",null,"Es sollte nie mehr als einen Grund dafür geben, eine Klasse zu ändern.")),r.createElement("p",{className:"font-normal text-sm"},"– Robert C. Martin: Agile Software Development: Principles, Patterns, and Practices"),r.createElement("p",null,"Wer noch unerfahren in der OOP ist, wird mit diesem Prinzip nichts anfangen können. Ich wage zu behaupten, dass so ziemlich jeder am Anfang seiner Programmierer-Karriere nur ein Ziel hatte: Das Programm muss funktionieren! Alles andere ist sekundär."),r.createElement("p",null,'Mit jedem Software-Projekt wächst die Erfahrung, vor allem wenn gestandene Entwickler mit von der Partie sind, von denen man lernen kann und das auch möchte. Man trifft dann unweigerlich auf große Klassen, deren Code umfangreich und oftmals nur schwer verständlich ist. Die normale Reaktion: "Wer schreibt denn so einen Haufen Sch...?"'),r.createElement("p",null,"Die paradoxe Erfahrung, die ich mit dem Single Responsibility Prinzip gemacht habe:"),r.createElement("blockquote",null,r.createElement("p",null,"Wenn andere große Klassen schreiben, regt man sich darüber auf. Wenn es die eigenen Klassen sind, ist das ok.")),r.createElement("p",null,"Aber ganz im Ernst: in praktisch jedem Projekt, in dem ich bislang gearbeitet habe, wird früher oder später dieses Prinzip verletzt. Es entstehen sogenannte Gott-Klassen, die nicht nur eine Aufgabe haben, sondern viele grundlegend verschiedene Sachen erledigen. Und damit haben sie mehr als einen Grund, sich zu ändern."),r.createElement("h3",null,"Zusammenfassung"),r.createElement("ul",null,r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Unerfahrenen Programmierern")," ist dieses Prinzip egal — Hauptsache dat Ding läuft."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Erfahrenere Programmierer")," kennen das Prinzip, wenden es auch gelegentlich an eigenem Code an, ignorieren es geflissentlich (wenn's mal schnell gehen muss) und monieren es gerne bei anderer Leute Code. So einen richtigen Schmerz spüren sie aber noch nicht dabei."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Richtig erfahrene Programmierer")," erkennen Gott-Klassen als ernsthaftes Problem, das Bauchschmerzen verursacht. Sie produzieren zwar manchmal vorübergehend Klassen, die mehr als einen Grund zur Änderung haben, aber sie drängen darauf, dies beim nächsten Refactoring aufzulösen.")),r.createElement("h2",null,"Open-Closed Prinzip"),r.createElement("blockquote",null,r.createElement("p",null,"Module sollten sowohl offen (für Erweiterungen), als auch geschlossen (für Modifikationen) sein.")),r.createElement("p",{className:"font-normal text-sm"},"– Bertrand Meyer: Object Oriented Software Construction"),r.createElement("p",null,"Meine Erfahrung mit diesem Prinzip in der Praxis ist, dass es fast nie angewendet wird. Man findet fast immer die Situation vor, dass bei Erweiterungen nicht etwa nur neue Klassen implementiert werden, sondern vor allem Änderungen an bestehenden Klassen."),r.createElement("h3",null,"Warum ist das ein Problem?"),r.createElement("p",null,"Ich halte das aus mehreren Gründen für problematisch:"),r.createElement("ul",null,r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Erhöhte Kosten, weil getesteter Code verändert wird.")," Nehmen wir an, wir haben eine Version 1.0 einer Software in Produktion, in der alles getestet ist. Werden jetzt für Version 2.0 neue Funktionen implementiert, kommt logischerweise neuer Code hinzu, der getestet werden muss. Wenn dieser neue Code in vorhandene Klassen kommt, riskiert man damit, funktionierenden Code kaputt zu machen. Auch vorhandene Tests für diesen Code können dabei anzupassen sein."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Schwerer zu verstehen.")," Source Code, der das Open-Close Prinzip umsetzt, ist in der Regel auch sehr gut zu verstehen, da die Rollen und Aufgaben klar auf einzelne Klassen verteilt sind. Wenn ich z.B. schon eine ",r.createElement("span",{className:"italic font-semibold"},"TextProcessor")," Klasse und eine ",r.createElement("span",{className:"italic font-semibold"},"JpgProcessor")," Klasse habe, ist es einfach eine ",r.createElement("span",{className:"italic font-semibold"},"PngProcessor")," Klasse hinzuzufügen. Wenn alle diese Prozessoren in einer Klasse wären, wäre die Sache viel unübersichtlicher."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Einfacher zu testen.")," In Tests benötigt man häufig Mocks, um seine Tests einfach zu erstellen. Für Source Code, der das Open-Close Prinzip beherzigt, ist es meisten sehr einfach Mocks zu erstellen.")),r.createElement("h3",null,"Zusammenfassung"),r.createElement("ul",null,r.createElement("li",null,"Das Open-Close Prinzip ist ein seltener Gast in Software-Projekten. Dies ist meine persönliche Bilanz; ich würde mich freuen, wenn mich meine persönliche Erfahrung täuschen würde."),r.createElement("li",null,"Das Open-Close Prinzip sollte von viel mehr Programmierern verstanden und beherzigt werden. Daher sollten erfahrenere Programmierer in Code Reviews mehr auf dieses Prinzip achten."),r.createElement("li",null,r.createElement("span",{className:"font-semibold"},"Meine Empfehlung: Frühe Design-Reviews.")," In Projekten gibt man Programmierern gerne eine AUfgabe und wenn sie fertig sind, gibt es ein Code Review. Wenn dort das verletzte Open-Close Prinzip moniert wird, ist die Standardantwort, dass das zwar eine gute Idee wäre, aber jetzt ist es ja schon fertig programmiert und für ein Refactoring ist keine Zeit mehr. Daher empfehle ich, dass der Programmierer sich ein Design zur Umsetzung überlegen soll und ",r.createElement("span",{className:"italic"},"bevor")," er etwas umsetzt, diskutiert man das im Kollegenkreis. Ich habe es noch nie erlebt, dass man in einer solchen Diskussion mit einer schlechteren Lösung herausgegangen ist. Dies sorgt auch bei allen für eine bessere Stimmung und mehr Motivation.")),r.createElement("h2",null,"Liskov Substitution Prinzip"),r.createElement("blockquote",null,r.createElement("p",null,"Wenn S ein Subtyp von T ist, dann können Objekte des Typs T durch Objekte des Typs S ersetzt werden, ohne dass sich die gewünschten Eigenschaften des Programms ändern.")),r.createElement("p",{className:"font-normal text-sm"},"– Barbara H. Liskov, Jeannette M. Wing: Behavioral Subtyping Using Invariants and Constraints Construction"),r.createElement("p",null,"Wenn man Programmierer fragt, ob sie das Liskov Substitution Prinzip beherzigen, bekommt man meistens große Augen zu sehen. Das liegt wohl daran, dass dieses Prinzip sehr mathematisch formuliert ist und viele die Definition nicht wirklich verstehen. Dabei drückt das Prinzip doch nur eine grundlegende Eigenschaft von OOP aus. Das bedeutet, dass man jede Unterklasse anstelle ihrer Elternklasse verwenden kann ohne das Verhalten des Programms zu verändern."),r.createElement("p",null,"Ich habe festgestellt, dass die meisten Programmierer das intuitiv richtig machen. Es passiert relativ selten, dass man auf eine Subklasse trifft, die ein gänzlich anderes Verhalten als das per Contract vereinbarte an den Tag legt. Wenn das passiert, ist die Überraschung auf Seiten des Aufrufers groß."),r.createElement("p",null,"Vielleicht kann man das Liskov Substitution Prinzip flapsig so formulieren: "),r.createElement("blockquote",null,r.createElement("p",null,"Sorge dafür, dass abgeleitete Klassen Verträge / Promises einhalten, um den Aufrufer nicht zu überraschen.")),r.createElement("h2",null,"Interface Segregation Prinzip"),r.createElement("blockquote",null,r.createElement("p",null,"Clients sollten nicht dazu gezwungen werden, von Interfaces abzuhängen, die sie nicht verwenden.")),r.createElement("p",{className:"font-normal text-sm"},"– Robert C. Martin: The Interface Segregation Principle"),r.createElement("p",null,"Die Verletzung dieses Prinzips findet man sehr häufig in der freien Wildbahn. Statt einem Client nur das zu überreichen, was er tatsächlich benötigt, wird ganz häufig die gesamte Klasse direkt übergeben."),r.createElement("p",null,"Das ist in etwa so, wie wenn man im Supermarkt an der Kasse €13,95 bezahlen soll und statt dem Mitarbeitenden an der Kasse einen passenden Geldschein zu überreichen, gibt man seine Aktentasche mit Portemonnaie und Geschäftsunterlagen weiter in der Hoffnung, dass schon das richtige herausgenommen wird. Was im realen Leben nicht passiert, wird im übertragenen Sinn beim Programmieren sehr häufig praktiziert."),r.createElement("h3",null,"Warum ist das ein Problem?"),r.createElement("p",null,"Man könnte ja argumentieren, dass das unproblematisch sei, weil Hauptsache es ist genügend Information da. Etwas mehr Information kann ja nicht schaden. Was in der Realität früher oder später passiert, ist, dass dieses Mehr an Möglichkeiten auch genutzt wird (ist ja so praktisch) und dadurch entstehen zusätzliche Abhängigkeiten, die fortwährend unterstützt werden müssen. Nur in den seltensten Fällen ist diese Abhängigkeit auch so gewollt. Und wie wir alle schon schmerzhaft erfahren haben: Abhängigkeiten können Software-Projekt zum Erliegen bringen!"),r.createElement("h2",null,"Dependency Inversion Prinzip"),r.createElement("blockquote",null,r.createElement("p",null,"Abstraktionen sollten nicht von Details abhängen. Details sollten von Abstraktionen abhängen.")),r.createElement("p",{className:"font-normal text-sm"},"– Robert C. Martin: The Dependency Inversion Principle"),r.createElement("p",null,"Mit der guten Unterstützung von DI-Containern in .NET findet man das Dependency Inversion Prinzip häufig im Einsatz. In der Praxis habe ich es erlebt, dass Container nur dann verwendet werden, wenn der Constructor eines Objekts nur von anderen ebenfalls im Container befindlichen Objekten abhängt. Sobald Parameter dazu kommen, die erst zur Laufzeit bekannt sind, wird gerne mal auf Container verzichtet, statt mit entsprechenden Factories zu arbeiten."),r.createElement("p",null,"Das arbeiten mit DI-Containern vereinfacht das Entwickeln so ungemein, dass man darauf auch nicht verzichten möchte. Aufwändige Objektgraphen können viel leichter erzeugt werden und auch das Testen wird massiv vereinfacht, weil man sich gemockte Objekte in den Container legen kann."))))))}}}]); //# sourceMappingURL=component---src-pages-artikel-solid-principles-js-f02e11631f2983353461.js.map