Die SOLID Pri­nciples bestehen aus fünf Praktiken und Richt­li­nien für sauberen, wartbaren und flexiblen Code beim ob­jekt­ba­sier­ten Prog­ram­mieren. Die Anwendung und Ein­hal­tung der Pri­nzi­pien er­möglicht ein leicht vers­tänd­lic­hes Software-Design über lange Entwicklung­szeit­räume hinweg. Auf diese Weise lässt sich nicht nur besserer Code schreiben, sondern auch bes­te­hen­der Code besser pflegen.

Was sind die SOLID Pri­nciples?

Am Anfang eines guten Quel­lco­des stehen Regeln, Prog­ram­mier­pa­ra­digmen und ein an­ge­mes­se­ner Prog­ram­mierstil für einen ef­fizien­ten und sauberen Code. Genau dafür sorgen die fünf SOLID Pri­nciples, die von Robert C. Martin, Bertrand Meyer und Barbara Liskov geprägt wurden. Wer bestimmte Pri­nzi­pien in der ob­jek­to­rien­ti­er­ten Prog­ram­mierung (OOP) mit Sprachen wie Python oder Java beachtet, schreibt nicht nur besseren Code, sondern sorgt langf­ris­tig auch für eine ef­fizien­tere Code-Pflege, ein nach­hal­ti­ges und flexibles Software-Design und mehr Sic­her­heit.

Die Bezeich­nung SOLID steht zum einen für die solide Entwicklungsba­sis für alle, die Prog­ram­mieren lernen wollen. Zum anderen setzt sich die Abkürzung aus den jeweils ersten Buchs­ta­ben der fünf Pri­nzi­pien (nach Michael Feathers) zusammen:

  • Single Res­pon­si­bi­lity Principle: Eine Klasse soll nur eine Ve­rantwor­tung (nicht Aufgabe) und nur einen Grund für eine Änderung haben!
  • Open Closed Principle: Klassen sollen für Erwei­te­run­gen offen und für Än­de­run­gen gesch­los­sen sein!
  • Liskov Subs­ti­tu­tion Principle: Subklas­sen sollen alle Methoden und Ei­gensc­haf­ten der Su­perklasse erben und imp­le­men­ti­eren können!
  • Interface Seg­re­ga­tion Principle: Sch­nitts­tel­len sollen nicht mehr Methoden enthalten, als für imp­le­men­ti­erende Klassen er­f­or­der­lich sind!
  • De­pen­dency Inversion Principle: Klassen sollen nicht von anderen Klassen, sondern von Sch­nitts­tel­len oder abst­rak­ten Klassen abhängen!

Welche Vorteile bieten die SOLID Pri­nciples?

Wo keine Regeln gelten, tritt Chaos ein – das wird beim Prog­ram­mieren deutlich. Bereits kleine Fehler, Un­ge­na­uig­kei­ten und Lücken können „unbe­han­delt“ auf längere Sicht einen guten Quellcode völlig unbrauchbar machen. Dafür braucht es nicht viel: Es genügen schon komplexe Klassen, die eine Imp­le­men­ti­erung erschwe­ren, oder Subklas­sen, denen einzelne Ei­gensc­haf­ten ihrer Su­perklas­sen fehlen. Die SOLID Pri­nciples sorgen dafür, dass es möglichst wenig Reparatur von Code durch Re­fac­to­ring braucht.

Die Vorteile einer Anwendung der SOLID Pri­nciples umfassen:

  • Klar, sauber und schön: Software und Codes sind leichter vers­tänd­lich, nachvol­lziehba­rer, effek­ti­ver und einfach schöner.
  • Leicht zu pflegen: Durch die über­sicht­liche, klare Struktur lässt sich sowohl neuer als auch his­to­risch gewach­se­ner Code selbst mit mehreren Be­tei­lig­ten einfacher warten und pflegen.
  • Anpassbar, erwei­ter­bar, wieder­ve­rwend­bar: Durch die bessere Les­bar­keit, geringere Komp­lexi­tä­ten und Ve­rantwor­tun­gen sowie re­duzierte Ab­hän­gig­kei­ten von Klassen lässt sich Code besser be­ar­bei­ten, anpassen, durch Sch­nitts­tel­len erweitern und flexibel wieder­ve­rwen­den.
  • Weniger feh­le­ran­fäl­lig: Durch sauberen Code mit einfacher Struktur wirken sich Än­de­run­gen an einem Teil nicht ungewollt auf andere Bereiche oder Funk­tio­nen aus.
  • Sicherer und zu­ver­läs­si­ger: Durch weniger oder gar keine Schwachs­tel­len, In­kom­pa­ti­bi­li­tä­ten oder Fehler ver­bes­sert sich die Funk­tio­na­li­tät und Zu­ver­läs­sig­keit von Systemen und somit auch die Sic­her­heit.

Die SOLID Pri­nciples im Überblick

Die SOLID Pri­nciples zählen zu den goldenen Regeln für gutes Prog­ram­mieren und sollten daher allen, die sich mit ob­jekt­ba­sier­ter Prog­ram­mierung besc­häf­ti­gen, geläufig sein. Wir stellen die fünf Pri­nzi­pien im Detail vor.

SRP: Single Res­pon­si­bi­lity Principle (Prinzip der ein­deu­ti­gen Ve­rantwort­lich­keit)

Die Original-De­fi­ni­tion gemäß Robert C. Martin in „Agile Software De­ve­lop­ment: Pri­nciples, Patterns and Practices“ besagt:

Quote

„Es sollte nie mehr als einen Grund dafür geben, eine Klasse zu ändern.“

Das SRP besagt, dass für jede Klasse in der OOP nur eine Ve­rantwor­tung gelten soll. Für Än­de­run­gen an der Klasse darf es somit nur einen Grund geben. Entgegen häufigen Miss­vers­tänd­nis­sen bedeutet das nicht, dass eine Klasse oder jedes Modul nur genau eine Aufgabe haben darf. Sie sollte jedoch nur für spezi­fische Aufgaben die Ve­rantwor­tung tragen, die sich möglichst nicht mit anderen Bereichen übersch­nei­den.

Ein Übersch­nei­den von Ve­rantwort­lich­kei­ten, zum Beispiel durch das Be­reits­tel­len von Funk­tio­nen für un­tersc­hied­liche Gesc­häfts­be­reiche, kann im Fall von Än­de­run­gen an einem Bereich, Auswir­kun­gen auf die Funk­tio­na­li­tät der Klasse haben. Durch mehr als eine Ve­rantwor­tung und zu viele Ab­hän­gig­kei­ten kann eine Änderung in einem Bereich mehrere weitere Än­de­run­gen oder Code-Fehler nach sich ziehen.

Das SRP hat somit zum Ziel, kohärente Module zu entwic­keln, die für eine klar vers­tänd­liche Aufgabe oder klar de­fi­nierte Objekte zuständig sind. Durch die klar struk­tu­rierte Form mit re­duzier­ten Ab­hän­gig­kei­ten und ent­kop­pelten Imp­le­men­ti­erun­gen lassen sich spätere Än­de­run­gen und Mo­du­la­tio­nen einfacher, schneller und ohne Komp­li­ka­tio­nen durchfüh­ren.

Note

Klassen, auch als Ob­jekt­ty­pen bekannt, bilden das zentrale Element in der ob­jek­to­rien­ti­er­ten Prog­ram­mierung (OOP). Sie lassen sich als Bauplan mit Att­ri­bu­ten für reale, ähnliche und zu konst­ruierende Objekte in Software-Objekten verstehen. Klassen, auch als Module bekannt, werden daher oft mit Da­teity­pen verg­lic­hen.

OCP: Open Closed Principle (Prinzip der Offen- und Versch­los­sen­heit)

Gemäß Bertrand Meyer und Robert C. Martin in „Object Oriented Software Const­ruc­tion“ besagt das OCP:

Quote

„Software-Entitäten (Klassen, Module, Funk­tio­nen etc.) sollten sowohl offen für Erwei­te­run­gen als auch gesch­los­sen für Mo­di­fi­ka­tio­nen sein.“

Das OCP sorgt dafür, dass Sie eine Software nicht im Kern um­sch­rei­ben müssen, um Än­de­run­gen zu imp­le­men­ti­eren. Sind ti­efg­rei­fende Code-Mo­du­la­tio­nen er­f­or­der­lich, entstehen Risiken für subtile Fehler und Code Smell. Ein gut struk­tu­rier­ter Code sollte sich mit Sch­nitts­tel­len (In­ter­faces) versehen lassen, über die er sich um zu­sätz­liche Funk­tio­nen erweitern lässt. Das Stichwort lautet hier Klassen-Vererbung.

Neue Features und Erwei­te­run­gen mit über­sicht­lic­hen neuen Funk­tio­nen und Methoden, die es zu imp­le­men­ti­eren gilt, lassen sich einfach per Sch­nitts­telle an eine Su­perklasse in Form von Subklas­sen andocken. Auf diese Weise müssen Sie nicht am gesch­riebe­nen, stabilen Code „herump­fusc­hen“. Das er­leich­tert die Wartung und Pflege von Prog­ram­men und gestaltet die Wieder­ve­rwend­bar­keit stabiler Code-Elemente durch Sch­nitts­tel­len deutlich ef­fizien­ter.

LSP: Lis­kov­sc­hes Subs­ti­tu­tions­pri­nzip (Er­se­tzbar­keits­pri­nzip)

Gemäß Barbara H. Liskov und Jeannette M. Wing in „Be­ha­vio­ral Subtyping Using In­va­riants and Const­raints“ besagt das LSP:

Quote

„Sei q (x) eine Ei­gensc­haft des Objekts x vom Typ T, dann sollte q (y) für alle Objekte des Typs S gelten, wobei S ein Subtyp von T ist.“

Was auf den ersten Blick kryptisch klingt, lässt sich leicht verstehen: Verk­nüpfte oder erwei­terte Subklas­sen müssen wie ihre Su­perklas­sen oder Ba­sis­klas­sen funk­tio­nieren. Das bedeutet, dass jede Subklasse mittels Vererbung die Ei­gensc­haf­ten ihrer jewei­li­gen Su­perklasse erhalten muss und diese Ei­gensc­haf­ten in der Subklasse keine Än­de­run­gen erfahren dürfen. Sie müssen vom Prinzip her ersetzbar sein – daher Er­se­tzbar­keits­pri­nzip. Su­perklas­sen hingegen dürfen sich durch Än­de­run­gen mo­di­fizieren lassen.

Zur Ve­ransc­hau­lic­hung dient das klas­sische Beispiel von Robert C. Martin vom Rechteck und Quadrat. Im Geo­met­rie­un­ter­richt gilt die Er­kennt­nis: Jedes Quadrat ist ein Rechteck, aber nicht jedes Rechteck ist ein Quadrat. Ein Quadrat teilt sich vielmehr die Ei­gensc­haft „Rechtwink­lige Seiten“ mit der Oberklasse der Rechtecke, weist jedoch die zu­sätz­liche Ei­gensc­haft „Gleich lange Seiten“ auf.

Anders beim Prog­ram­mieren: Hier führt die Annahme, dass ähnliche oder scheinbar iden­tische Klassen sich au­fei­nan­der beziehen oder vo­nei­nan­der abhängig sind, zu Fehlern, Miss­vers­tänd­nis­sen und unklarem Code. Aus diesem Grund ist beim Prog­ram­mieren die Klasse „Rechteck“ kein Quadrat und die Klasse „Quadrat“ kein Rechteck. Beide werden „ent­kop­pelt“ und getrennt imp­le­men­ti­ert. Ohne in­teg­rierte Ver­bin­dung zwischen den Klassen kann ein Miss­vers­tänd­nis nicht zu klas­se­nü­berg­rei­fen­den Fehlern führen. Das erhöht die Sic­her­heit und Sta­bi­li­tät beim Austausch von Imp­le­men­ti­erun­gen in Subklas­sen oder Su­perklas­sen ohne Auswir­kun­gen.

ISP: Interface Seg­re­ga­tion Principle (Sch­nitts­tel­le­nauf­tei­lungspri­nzip)

Das ISP definiert sich nach Robert C. Martin in „The Interface Seg­re­ga­tion Principle“:

Quote

„Clients sollten nicht dazu gezwungen werden, von In­ter­faces abzu­hän­gen, die sie nicht verwenden.“

Das ISP besagt, dass Anwen­de­rin­nen und Anwender nicht gezwungen sein sollen, Sch­nitts­tel­len (In­ter­faces) zu verwenden, die sie nicht brauchen. In anderen Worten: Um Clients die Funk­tio­nen von bes­timm­ten Klassen zur Verfügung zu stellen, werden neue, kleinere Sch­nitts­tel­len auf konkrete An­f­or­de­run­gen zu­gesch­nit­ten. So lässt sich ver­hin­dern, dass In­ter­faces zu groß werden und starke Ab­hän­gig­kei­ten zwischen Klassen entstehen. Der Vorteil: Software mit ent­kop­pelten Klassen und mehreren kleinen, auf konkrete For­de­run­gen zu­gesch­nit­te­nen In­ter­faces lässt sich leichter pflegen.

DIP: De­pen­dency Inversion Principle (Ab­hän­gig­keits-Umkehr-Prinzip)

Das fünfte und letzte der SOLID-Pri­nciples lautet nach Robert C. Martin in „The De­pen­dency Inversion Principle“ wie folgt:

Quote

„A. Module hoher Ebenen sollten nicht von Modulen niedriger Ebenen abhängen. Beide sollten von Abst­rak­tio­nen abhängen. B. Abst­rak­tio­nen sollten nicht von Details abhängen. Details sollten von Abst­rak­tio­nen abhängen.“

Das DIP sorgt dafür, dass konkrete Funk­tio­nen und Ab­hän­gig­kei­ten in Quellcode-Ebenen auf abst­rak­ten Sch­nitts­tel­len und nicht au­fei­nan­der aufbauen. Zur Erklärung: Software-Arc­hi­tek­tu­ren lassen sich grob in höhere Be­nu­tze­re­be­nen und nied­ri­gere oder tiefere abstrakte Ebenen un­tersc­hei­den. Rein logisch lässt sich annehmen, dass die abstrakte Basis das Verhalten der höheren Ebenen bestimmt. Das DIP sieht hierin jedoch eine Feh­le­ran­fäl­lig­keit, da es zu Ab­hän­gig­kei­ten der höheren Ebenen von tieferen Ebenen kommt.

Statt höhere Ebenen an nied­ri­gere Ebenen zu koppeln, sollten Klassen in hohen und niedrigen Ebenen von abst­rak­ten, zwisc­hen­gesc­hal­teten Sch­nitts­tel­len abhängen. Die Sch­nitts­tel­len rufen Funk­tio­na­li­tä­ten, die in höheren Ebenen benötigt werden, von unteren Ebenen ab und stellen sie bereit. Auf diese Weise lässt sich eine „Bottom-to-Top-Hie­rarc­hie“ aus Ab­hän­gig­kei­ten vermeiden, die mit der Zeit zu Fehlern im Code führen kann. Das er­leich­tert die Wieder­ve­rwend­bar­keit von Modulen und er­möglicht Än­de­run­gen an unteren Klassen ohne Auswir­kun­gen auf höhere Ebenen.

Was passiert bei Nich­tein­hal­tung der SOLID Pri­nciples?

Ein schöner, leicht lesbarer Code, der Pflege so leicht wie möglich macht, sollte das Ziel jeder Software-Entwicklung sein. Geraten Richt­li­nien wie die SOLID Pri­nciples jedoch in Ver­ges­sen­heit, altert Code durch Schwachs­tel­len, Re­dundanzen, an­ge­häufte Fehler und zu viele Ab­hän­gig­kei­ten sehr schlecht. Im sch­limms­ten Fall wird der Code mit zu­neh­men­der Zeit unbrauchbar. Das stellt vor allem in der agilen Software-Entwicklung ein großes Problem dar, denn hier arbeiten meist viele Be­tei­ligte an einem komplexen Code.

Zu den Folgen, die un­sau­be­rer Code oder schlechte Co­depflege mit sich bringen, zählen:

  • Code Smell: His­to­risch gewach­sene Schwachs­tel­len aus un­sau­be­rem Code, bekannt als Code Smell oder „müffeln­der Code“, führen zu Funk­tions­feh­lern und in­kom­pa­tib­len Prog­ram­men.
  • Code Rot: Kommt es nicht zur Wartung oder Reparatur durch Re­fac­to­ring oder ein kosts­pie­li­ges Code Review, kann Code im übertra­ge­nen Sinne „verfaulen“ und seine Funk­tio­na­li­tät vollstän­dig einbüßen. Eine andere Bezeich­nung für un­les­ba­ren, ve­rwor­re­nen Code ist Spaghetti-Code.
  • Sic­her­heits­lücken: Nicht nur Ausfälle, komp­lizierte Pflege oder In­kom­pa­ti­bi­li­tä­ten sind eine Folge, sondern auch Sic­her­heits­lücken, die Sc­had­sof­tware die Chance auf Exploits sowie Zero-Day-Exploits eröffnen.

Wer hat die SOLID Pri­nciples entwic­kelt?

Der Ursprung der SOLID Pri­nciples liegt in mehreren Pri­nzi­pien, die erstmals von Robert C. Martin („Uncle Bob“), einem der Ini­tia­to­ren der agilen Prog­ram­mierung, in seinem Essay „Design Pri­nciples and Design Patterns“ im Jahr 2000 ein­ge­führt wurden. Die Gruppe der fünf SOLID Pri­nciples wurde von Robert C. Martin, Bertrand Meyer und Barbara Liskov mit­ge­prägt. Das eingän­gige Akronym bestehend aus den fünf An­fangsbuchs­ta­ben der Pri­nzi­pien wiederum wurde von Michael Feathers pro­pa­giert, indem er fünf der we­sent­lic­hen Pri­nzi­pien neu ar­ran­gierte.

Welche ähnlichen Prog­ram­mierpri­nzi­pien gibt es?

In der Sof­twa­reentwicklung stehen Pri­nzi­pien für al­l­ge­m­eine oder sehr konkrete Leit­li­nien und Handlung­sempfehlun­gen ähnlich wie die SOLID Pri­nciples, die ein Set aus Pri­nzi­pien für das Paradigma der ob­jek­to­rien­ti­er­ten Prog­ram­mierung bieten. Weitere Prog­ram­mierpri­nzi­pien für Clean Code sind etwa:

  • DRY-Prinzip (Don’t repeat yourself) für Funk­tio­nen mit einer einzigen, ein­deu­ti­gen Dars­tel­lung
  • KISS-Prinzip (Keep it simple, stupid) für einen möglichst einfach konst­ruier­ten Code
Go to Main Menu