Category

Allgemein

Interview mit Stefan Toth auf der OOP 2020

By | Allgemein, Video | No Comments
Interview mit Stefan Toth – OOP Februar 2020
OOP_Logo_2018
IT-Journalist Christoph Witte im Gespräch mit Stefan Toth
Interviewsprache Englisch, online auf YouTube
veröffentlicht am 11. März 2020,

Mehr zum Thema Architekturbewertung
Architektur-Reviews – warum eigentlich?

Seminare AGILA – Agile Softwareentwicklung, AWERT – Architekturbewertung
iSAQB CPSA-Advanced Seminare

Stefan Toth ist der Experte für agiles Architekturvorgehen im deutschsprachigen Raum und hat viele Unternehmen in entsprechenden Fragestellungen unterstützt. Für den iSAQB hat Stefan Toth den Lehrplan zum Modul „Agile Softwarearchitektur“ (AGILA) verfasst und verantwortet dieses als Kurator. Die Lehrpläne zu Architekturbewertung (AWERT) und „Enterprise Architecture Management (EAM) hat er ebenfalls maßgeblich mitgestaltet, für AWERT hat er ebenfalls die Kurator-Rolle inne. Stefan Toth ist stimmberechtigtes Mitglied im iSAQB und wurde 2019 auch in dessen Strategic Council gewählt.

Der  IT-Journalist Christoph Witte interviewte Stefan Toth im Rahmen der OOP 2020 in München. In dem Interview gibt Stefan Einblicke, wo Architekturbewertungen unterstützen können und welche Schwerpunkte die iSAQB Advanced Module AWERT und AGILA setzen.

 

Vortrag Stefan Toth auf der OOP 2020:
„Warum gute Architektur nichts mit Code-Qualität zu tun hat.“

CONSTRUCT: Aufbauen (5C Design, Teil 6)

By | Allgemein, Inhaltliches | No Comments

Eine Bausteinstruktur kann auf einer Ebene selbst wieder unübersichtlich werden. Baue Systeme höherer Komplexität durch Zusammenfassen von Bausteinen einer Ebene zu einem neuen Baustein einer nächsthöheren Ebene. Dabei sind weiterhin dieselben Handlungsmaximen anzuwenden.

  1. Software-Entwurf: Ein Blick zurück und nach vorn
  2. CUT: Richtig schneiden
  3. CONCEAL: Verbergen
  4. CONTRACT: Schnittstelle festlegen
  5. CONNECT: Verbinden
  6. CONSTRUCT: Aufbauen
  7. Its a Wrap: Zusammenfassung

In den bisherigen Artikeln ging es darum, wie man ein System auf einer Ebene effizient in einzelne Module zerlegt. Bei entsprechend großem Umfang der Lösung kann dabei nach wie vor Folgendes passieren: Die schiere Anzahl der Module wächst Ihnen über den Kopf und das gesamte System ist im Endeffekt wieder unübersichtlich. Was kann man in so einem Fall tun? Eine schlechte Idee wäre, mehr Logik in die einzelnen Module zu geben, sodass die Gesamtzahl an Modulen wieder überschaubar wird. Dadurch würde nur Komplexität in die Module hinein verlagert. Die Alternative ist Strukturen auf der nächst höheren Abstraktionsebene zu bilden. Wir zoomen aus unserer Architektur heraus und bauen dann modulare Strukturen nach denselben Regeln, nach denen wir schon die Module auf der unteren Abstraktionsebene entworfen hatten. Während dies den Vorgang eher bottom-up beschreibt, so ist dasselbe Ergebnis natürlich auch top-down zu erreichen. 

Whole-Part Pattern

Ein fast schon in Vergessenheit geratenes Muster, das dabei hilfreich sein kann, ist das Whole-Part Pattern. Vorgestellt wurde es in einem zeitlosen Klassiker der Software-Architektur namens “Pattern-Oriented Software Architecture” aus dem Jahr 1996. Als Beispiel dient uns der Motor eines Autos. Er besteht aus vielen Einzelteilen, wie dem Kolben, der Kurbelwelle und den Zündkerzen. Der Motor selbst ist aber wiederum nur ein Teil des Autos, das außerdem noch aus Dingen wie dem Lenkrad, der Karosserie, den Rädern und dem Auspuff besteht. Vor dem Fahrer wird diese Komplexität weitestgehend verborgen. Er dreht den Schlüssel um, beschleunigt mit dem Gaspedal und beeinflusst mit dem Lenkrad die Fahrtrichtung. Einmal im Jahr kommt das Auto in die Werkstätte zur Wartung. Dass dort der Filter der Klimaanlage genauso gewechselt wird wie das Motoröl kann dem Fahrer egal sein. Die Abstraktion “Auto” verbirgt all diese Komplexität vor seinem Nutzer so gut es geht.

Das Beispiel mit dem Auto könnte man sogar noch weiterdenken. Ein Robotertaxi-Service könnte eine weitere Abstraktionsebene darstellen. Eine Serversoftware weiß wo sich die einzelnen selbstfahrenden Taxis gerade befinden. Wenn ein Kunde per App eines der Taxis anfordert wird die Software des nächstbesten Robotertaxis dieses zum Kunden bewegen und ihn in weiterer Folge an sein gewünschtes Ziel bringen. Das Auto, die Software darin, die Software am Server und die App am Handy des Kunden bilden dann in Summe eine weitere Abstraktionsebene, die die Mobilität für den Kunden noch weiter vereinfacht.

In einer komplexen Enterprise Architektur können Sie sich dieses Prinzip wie folgt zu Nutze machen: Die Unternehmensarchitekten legen fest, wie sich die Systemlandschaft in einzelne Subsysteme zerlegt. Sie kümmern sich außerdem um Themen, die über die einzelnen Subsysteme hinaus gehen, wie die Wahl der Technologie zur Integration der einzelnen Systeme. Für die Implementierung der einzelnen Subsysteme selbst wird aber nur der grobe Rahmen definiert. Die Verantwortung für die korrekte Umsetzung wird in den einzelnen Teams belassen. Zu klären, wie sich ein konkretes Subsystem selbst dann weiter in Module zerlegt, ist also wiederum Aufgabe eines der Teams. Die Unternehmensarchitekten kümmern sich in einem solchen Modell um die strategischen Themen und überlassen die Taktik den einzelnen Teams.

Self-Contained Systems

Da die Gedanken bisher eher abstrakt waren, möchte ich noch einen konkreten Architekturstil vorstellen, mit dem man das Prinzip der hierarchischen Zerlegung prima umsetzen kann, nämlich Self-Contained Systems (oder kurz: SCS). Diese setzen explizit auf eine sehr lose Kopplung zwischen den einzelnen Teilsystemen. Bevorzugt wird eine Integration über das User-Interface. Ansonsten ist zeitliche Abhängigkeit zwischen den Systemen durch synchrone Kommunikation (wie über SOAP-RPC) eher verpönt und man sollte stattdessen auf asynchrone Integration (wie über Messaging) und Datenreplikation setzen.

Damit das klappt muss anfangs strategisch festgelegt werden, an welchen Grenzen sich das System gut in solch lose gekoppelte Subsysteme zerlegen lässt. Wenn das allerdings klappt, können die einzelnen Teams relativ isoliert voneinander an ihrem jeweiligen Subsystem arbeiten. Die Art der Umsetzung der einzelnen Teilsysteme kann sich dabei auch stark voneinander unterscheiden. So kann es sich bei einem der Subsysteme um einen Legacy-Deployment-Monolithen handeln, während ein anderes auf einer Microservice-Architektur aufbaut.

Im nächsten und bereits letzten Beitrag dieser Artikelserie fass ich das Thema noch einmal kurz zusammen. Außerdem zeige ich Möglichkeiten, wie man eine Architektur nach 5C umsetzt.

Kim Duggen über Organisationsentwicklung und mehr – im Podcast mit Lena Wittneben

By | Allgemein, Publikationen | No Comments

Kim Duggen über ihre persönliche Sicht auf Organisationsentwicklung im Podcast von und mit Lena Wittneben

Kim Nena Duggen im Gespräch mit Lena „There is a crack in everything – Wünsche, Ziele, Wendepunkte!“
Kim Nena Duggen und Lena Wittneben
Podcast über Organisationsentwicklung, Erfahrungswerte und vieles mehr..
September 2019
lena_wittneben

„Für mich ist Kim eine absolut positive „Sprechdenkerin“ (ihre Selbstbezeichnung), die mit maximal Herz, Hirn, Humor und Haltung intelligent-inspierende Ideen in die Welt bringt.“ (Zitat Lena Wittneben)

Was bedeutet Selbstorganisation für Kim und welche Erfahrungen hat sie in ihren beruflichen Umfeldern in den letzten Jahren gemacht? Wie haben die skandinavische und die chinesische Kultur sie beeinflusst und welche Rolle spielt ein wichtiger Sparringspartner schon seit Kindertagen in ihrem Leben? – nicht nur wenn es um Organisationsentwicklung geht.

Und wenn Sie auch noch wissen will, warum Kim beim Karaoke immer das gleiche Lied auswählt? Hören Sie selbst..

embarc echo – September 2019

By | Allgemein, echo | No Comments

Impulse aufgreifen – embarc echo

Lassen Sie sich von unseren aktuellen Konferenzbeiträgen und Publikationen im Web & in gebundener Form inspirieren. Wir haben Tipps für Ihren Einstieg in das Thema Machine Learning und Referenzwissen für ein modernes Web-Frontend direkt zum Download. Außerdem stellen wir Ihnen unsere neue Kollegin vor und werfen einen Blick auf künftige Termine & Veranstaltungen. Finden Sie in gewohnt kurzer Form frische Anregungen für Ihre Projekte!

Download embarc echo September 2019 (PDF, 8 Seiten)

follow us on Twitter – @embarced

CONNECT: Verbinden (5C Design, Teil 5)

By | Allgemein, Inhaltliches | No Comments

Durch Verwendung einer Schnittstelle eines anderen Bausteins kommt es immer zu Abhängigkeiten. Plane explizit zwischen welchen Bausteinen es welche Art von Abhängigkeit geben soll.

  1. Software-Entwurf: Ein Blick zurück und nach vorn
  2. CUT: Richtig schneiden
  3. CONCEAL: Verbergen
  4. CONTRACT: Schnittstelle festlegen
  5. CONNECT: Verbinden
  6. CONSTRUCT: Aufbauen
  7. Its a Wrap: Zusammenfassung

Damit ein System, das in seine Einzelteile zerlegt wurde, in Summe das gewünschte große Ganze ergibt, müssen seine Einzelteile miteinander interagieren. Diese Interaktionen erzeugen Verknüpfungen, die wiederum die einzelnen Teile in Abhängigkeiten zueinander bringen. Vereinfacht gesagt sind bei Änderungen, die nach außen wirksam sind, die angebundenen Module immer zu berücksichtigen. Diesen Aspekt gilt es möglichst klein zu halten. Die Abhängigkeiten können unterschiedliche Bereiche betreffen:

  • Daten und Formate: Ein Consumer muss das Format des Providers einer Schnittstelle verstehen. Bei Änderungen daran ist der Consumer ebenfalls betroffen.
  • Zeit: Wenn der Consumer seine Arbeit nur abschließen kann, wenn der Provider im selben Moment auch gerade verfügbar ist, so ist seine Verfügbarkeit auf Zeiten limitiert, in denen der Provider ebenfalls verfügbar ist. In dem Fall kommt es zu einer zeitlichen Abhängigkeit zwischen den Modulen.
  • Technologie: Ist der Consumer in der technologischen Auswahl seiner Implementierung auf irgendeine Weise eingeschränkt? Ein Netzwerkprotokoll wie Java RMI wirkt beispielsweise einschränkender als eine REST-Integration auf Basis des HTTP-Protokolls.
  • Ausführungsort: Ist es zur Interaktion nötig, dass die Module auf derselben (virtuellen) Maschine laufen, so sind sie was den Ausführungsort angeht eingeschränkt. Bei Kommunikation innerhalb der Grenzen des eigenen Prozesses ist dies beispielsweise so.

Diese technischen Abhängigkeiten ziehen in weiterer Folge Abhängigkeiten auf der organisatorischen Ebene nach sich. Ein Unternehmen, das zur Weiterentwicklung seiner Software überdurchschnittlich viele Meetings benötigt wäre ein Beispiel, wo sich diese Auswirkungen zeigen. Das und ein gezwungenermaßen hohes Maß an Bürokratie sind Indizien dafür, dass man die Abhängigkeiten innerhalb der Software nicht mehr im Griff hat.

Zur Vermeidung von Missverständnissen: Wenn Interaktion nötig ist, ist es nicht möglich, Abhängigkeiten völlig zu vermeiden. Und: Interaktion wird nötig sein. Es gilt die negativen Auswirkungen von Abhängigkeiten durch geschickten Architekturentwurf im Zaum zu halten. Ein bekanntes Entwurfsprinzip, dessen Befolgung dabei hilft, ist das Prinzip der azyklischen Abhängigkeiten. In einem Entwurf wo Module zyklisch voneinander abhängig sind, sind diese Module von jedem anderen in diesem Zyklus direkt oder indirekt abhängig. Diese Situation birgt hohe Risiken von unerwünschten Seiteneffekten bei Änderungen. Daher der Grundsatz Strukturzyklen möglichst zu vermeiden.

Kaskadierende Abhängigkeiten

Ebenfalls problematisch sind sogenannte Kaskadierende Abhängigkeiten. Dabei pflanzt sich ein und dieselbe Abhängigkeit, über die jeweiligen Modulgrenzen hinaus über weitere Abhängigkeiten zu weiteren Modulen fort. Mit anderen Worten: Was auch immer diese Abhängigkeit betrifft, sei es ein Datenformat oder eine Technologie, man wird sie nur ändern oder entfernen können indem man Änderungen am gesamten System vornimmt. Die folgende Grafik illustriert das:

Das Schnittstellenformat, das Baustein A anbietet, wird von den Bausteinen B und C selber wiederum intern benützt. Weiters kommen einzelne Aspekte dieser Schnittstelle in den externen Schnittstellen der Bausteine B und C wieder vor, wodurch sie sich auf deren Consumer (in diesem Fall D, E, F und G) ausbreiten. Eine Änderung der Schnittstelle des Bausteins A zieht dann eine Kaskade an Änderungen nach sich, die schließlich das gesamte System betreffen. Um so etwas zu verhindern bietet sich die Anwendung des Integrationgsmusters Anti-Corruption Layer aus dem Domain-Driven-Design an, das in der folgenden Grafik dargestellt ist. Dabei kommuniziert ein Consumer nur über einen solchen Layer mit seinem Provider, der das Modell des Providers in sein eigenes Format konvertiert.

Wenn Sie den Empfehlungen dieser Blog-Serie beim Entwurf Ihres Systems bis hierhin gefolgt sind kann es sein, dass Ihr Entwurf bereits aus einer sehr großen Zahl an Modulen besteht. Eine hohe Anzahl an Modulen kann, auch wenn diese jeweils wunderbar gekapselt sind, wiederum unübersichtlich werden. Sie tun dann gut daran, wiederum dieselben Regeln anzuwenden, allerdings eine Abstraktionsebene höher. Dies bringt uns zum nächsten Beitrag dieser Reihe: „CONSTRUCT: Aufbauen“.

Moin Moin!

By | Allgemein | No Comments

Ich bin als Organisationsentwicklerin im Bereich neue Arbeitswelten, Selbstorganisation und (IT-)Strategie unterwegs. Und seit Mitte August bei embarc mit an Bord! Wenn ich mit Menschen arbeite, die selbst etwas bewegen wollen..

Read More

CONTRACT: Schnittstelle festlegen (5C Design, Teil 4)

By | Allgemein, Inhaltliches | No Comments

Entwerfe Schnittstellen so, dass eine möglichst reibungslose Interaktion zwischen dem Baustein und seinen Consumern möglich ist.

  1. Software-Entwurf: Ein Blick zurück und nach vorn
  2. CUT: Richtig schneiden
  3. CONCEAL: Verbergen
  4. CONTRACT: Schnittstelle festlegen
  5. CONNECT: Verbinden
  6. CONSTRUCT: Aufbauen
  7. Its a Wrap: Zusammenfassung

Wie legt man eine Schnittstelle fest, die eine möglichst reibungslose Interaktion ermöglicht? Tatsächlich ist das Thema bereits in den SOLID Prinzipien sehr prominent vertreten. So steht das L darin für das Liskovsche Substitutionsprinzip von Barbara Liskov (nähere Infos hier). Noch interessanter finde ich aber das I aus SOLID, das für das Interface-Segregation Prinzip steht. Dies ist die erste von 3 Techniken für sauberes Schnittstellendesign, die ich ihnen hier vorstelle. Es besagt, dass die Schnittstelle eines Moduls immer nach ihren einzelnen Verantwortlichkeiten aufgeteilt sein sollte. Es darf demnach nicht eine einzige generische Schnittstelle geben, sondern für jeden Anwendungsfall der Benutzung einer Komponente jeweils eine eigene. Ich möchte das anhand eines Beispiels erläutern.

Interface Segregation und REST-APIs

Die Web Service Description Language (oder kurz WSDL) ist eine Beschreibungssprache für Schnittstellen und ein offizieller Standard des W3C Konsortiums. Sie wird meist in Kombination mit dem Simple Object Access Protocol (oder kurz SOAP) verwendet. Bei meinem Grundlagen-Seminaren zum Thema Software-Architektur geht es u.a. immer auch um das Interface-Segregation Prinzip. Ich frage die Teilnehmer dann gerne, ob jemand unter ihnen schon mal eine WSDL-Datei bekommen hat, die mehrere Megabyte groß war, und von der er (oder sie) sich zunächst einmal wie erschlagen fühlte. Eigentlich ist immer jemand dabei, der so eine Situation schon mal erlebt hatte. Solch komplexe Schnittstellen haben 2 potentielle Probleme:

  • Der Einarbeitungsaufwand für den Entwickler, der diese Schnittstelle verwenden möchte, ist ausgesprochen hoch. In der WSDL Spezifikation ist nicht vorgesehen, die Schnittstelle zu strukturieren.
  • Es besteht die Gefahr, dass der Code, der die Schnittstelle konsumiert, Abhängigkeiten zu Teilen der Schnittstelle entwickelt, die von diesem gar nicht benötigt werden. Sobald das Modell zur Schnittstelle vom Client generiert wurde ist es möglich, auch zu nicht relevanten Teilen einer nur teilweise verwendeten Schnittstelle Abhängigkeiten zu entwickeln.

Als Standard für Schnittstellen im Web hat sich inzwischen der Representational State Transfer als Alternative etabliert. Dabei wird eine komplexe Schnittstelle in ihre einzelnen „Subjekte“ bzw. Ressourcen aufgeteilt. Dieser Schritt entspricht einer Umsetzung des Interface-Segregation-Prinzips. REST hat also das I aus SOLID quasi „mit eingebaut“.

Die Kommunikation mit diesen einzelnen Ressourcen erfolgt mit den „Verben“ des HTTP-Protokolls, also beispielsweise mittels GET, PUT, POST und DELETE. Dabei gibt es auch Weiterleitungen von einer Ressource zur nächsten, die damit in Verbindung steht. Diese Weiterleitung (genannt Hypermedia As the Engine of Application State oder kurz: HATEOAS) bietet eine gewisse Flexibilität was die Änderung der einzelnen Endpoints angeht. Außerdem ist sie noch eine Form der Selbstdokumentation für Nutzer der Schnittstelle. Das Gefühl der Frustration, weil man so etwas wie eine monströse WSDL erhalten hat, sollte es bei REST-APIs also gar nicht erst geben.

Das Schnittstellen-Problem des Mars-Climate Orbiter

Neben der Schnittstellentrennung gibt es weitere Techniken für eine reibungslose Interaktion. Im konkreten Beispiel hätte ihre Anwendung einen Millionenschaden vermieden. Vielleicht hatten Sie es 1999 in den Nachrichten mitbekommen: Die NASA Sonde Mars-Climate Orbiter war abgestürzt. Sie hätte in einen Orbit um den Planeten Mars eintreten sollen, ist aber stattdessen auf dessen Oberfläche zerschellt (für nähere Infos dazu klicken Sie bitte hier). Passiert war Folgendes: Die Software wurde in Teilen von der NASA und teilweise von Lockheed-Martin entwickelt. An einer Stelle gab es eine Schnittstelle zur Weitergabe des gemessenen Impulses an die Steuerungseinheit. Während das eine Team davon ausging, dass dieser auf dem metrischen System basiert ging das andere Team von einer Abbildung basierend auf dem imperialen System aus. Das Ergebnis war der oben erwähnte Verlust der Raumsonde und ein entsprechender Millionenschaden. Ich könnte mir vorstellen, dass diese Schnittstelle nicht viel spezifischer definiert war als in folgendem Listing:


public double getSpeed ();

Eine solche Definition lässt einfach zu vieles offen. Um welche Einheit handelt es sich bei der Geschwindigkeit? Außerdem ist nicht klar ob auch negative Werte möglich sind, oder nur positive Werte als Rückgabewerte in Frage kommen. Diese Art von Problem kann durch eine spezifischere Definition des Schnittstellenkontraktes behoben werden. Viel besser ist die folgende Definition, wo wir uns des JSR305 bedienen und mit der entsprechenden Annotation beschreiben, dass diese Methode keine negativen Werte zurückliefert. Außerdem wird durch die Methodensignatur klar, dass es sich um die SI Einheit für Geschwindigkeit handelt:


public @Nonnegative double getSpeedInMetersPerSecond();

Achtung, Gefahr!

Besonders problematisch sind Schnittstellen, die einem jeden Consumer die Möglichkeit bieten, den Provider selbst in Probleme zu bringen. Dies zu vermeiden wäre mein 3. Tipp zum Thema. Wo man dies häufig antrifft ist, wenn sich mehrere Services oder Subsysteme den Zugriff auf ein und dieselbe Datenbank mit demselben Datenmodell teilen. So wie dies in der folgenden Grafik dargestellt ist:

Die Schnittstelle, die eine solche geteilte Datenbank ihren Consumern bereitstellt ist nämlich das Datenmodell selbst, und im Falle einer relationalen Datenbank die Abfragesprache SQL. Das beinhaltet die Möglichkeit einzelne Tabelleneinträge zu sperren, oder auch die Datenbank mit umfangreichen Query-Abfragen inkl. Joins über viele Tabellen zu lähmen. Eine dermaßen missbräuchliche Verwendung wird die anderen Consumer der Datenbank ebenfalls in Probleme bringen. Genau das sollte aber über eine Schnittstelle gar nicht erst möglich sein. Ich rede dabei wohlgemerkt nicht von Denial-of-Service Attacken, sondern von Dingen, welche früher oder später im Zuge der üblichen Wartungstätigkeit passieren.

Wird eine Schnittstelle zwar angeboten, aber von niemandem benutzt, ist natürlich noch keine Interaktion passiert. Im nächsten Beitrag (“CONNECT: Verbinden”) betrachten wir die Folgen, welche es zwangsläufig haben wird, wenn Bausteine über Schnittstellen miteinander interagieren.

DevOpsDays London 2019: DevOps and Legacy Code

By | Allgemein, Publikationen | No Comments

DevOps and Legacy Code

Unfortunately we can’t all work in startup companies. Some of use have to deal with legacy code bases. These are often structured as a monolith and tightly coupled. They typically are hard to build and deploy. You might think all the new DevOps practices and toys are not suitable for your context. You are wrong!

We will discuss strategies to work with legacy code and still use DevOps practices and tools. These include breaking up of monolithic structures, migrating data and monitoring systems that aren’t built to be monitored. We will show real-world examples of successful applications of these strategies.

While dealing with legacy code will still be painful, you will have some applicable ideas to relieve your pain.

Devopsdays London 2019

follow us on Twitter – @embarced

CONCEAL: Verbergen (5C Design, Teil 3)

By | Allgemein, Inhaltliches | No Comments

Verbirg so viel der internen Struktur eines Bausteins und der Art der Umsetzung vor der Außenwelt wie möglich.

  1. Software-Entwurf: Ein Blick zurück und nach vorn
  2. CUT: Richtig schneiden
  3. CONCEAL: Verbergen
  4. CONTRACT: Schnittstelle festlegen
  5. CONNECT: Verbinden
  6. CONSTRUCT: Aufbauen
  7. Its a Wrap: Zusammenfassung

Es war 1972 als David Parnas sein visionäres Papier mit dem Titel “On the Criteria To Be Used in Decomposing Systems into Modules” veröffentlichte. Während Parnas hier viele Aspekte der Modularisierung angesprochen hat, ist es inzwischen hauptsächlich noch für eines bekannt, und zwar für die Formulierung des Information-Hiding Prinzips. Alles, von dem man annahm, dass es sich später ändern könnte, sei vor der Außenwelt zu verbergen. So hat man die Garantie, dass es von außerhalb eines Bausteins niemals Abhängigkeiten dazu geben wird. Dadurch kann dies später jederzeit isoliert geändert werden. Ich unterstreiche das und gehe sogar noch weiter: Verbergen Sie am besten einfach alles, was sich verbergen lässt. Standardmäßig sollte einmal alles zunächst einmal verborgen sein. Nur wenn es außerhalb wirklich benötigt wird, sollte es auch veröffentlicht werden. Schließlich ist es schwierig vorherzusehen, was tatsächlich später einmal geändert werden muß.

Einer der Vorzüge der aktuell so beliebten Microservices ist, dass dabei Interna der einzelnen Module (dort eben Microservices genannt) automatisch hinter einer Remote-Schnittstelle (hier oft REST) verborgen werden. Durch den Verteilungsaspekt eines Service sind das nicht nur die konkreten Komponenten, sondern auch deren Laufzeitumgebung und die jeweils eingesetzte Technologie zur Implementierung.

Die verschiedenen Technologien bringen allerdings selbst bereits Dinge mit, um Subbausteine zu verbergen. In Java ist dies wie folgt möglich, wobei wir auf der niedrigen Abstraktionsebene beginnen und danach “nach außen zoomen”:

  • Innerhalb einer Klasse lassen sich einzelne Member (wie Methoden und Variable) verbergen, beispielsweise mit dem private-Keyword. In Java hat sich eingebürgert Instanzvariable einer Klasse prinzipiell zu verbergen, und wenn, dann nur über sogenannte getter und setter zu veröffentlichen.
  • Klassen lassen sich innerhalb eines Java-Packages verbergen, indem man diese als package-protected definiert. Die Angabe erfolgt dann ohne visibility Modifier in der Klassen-Deklaration.
  • Ab Java 9 können Packages mittels JigSaw (nähere Infos dazu hier) zu Modulen zusammengefasst werden. Dabei kann man gezielt Packages exportieren oder vor der Außenwelt verbergen.

Facade Pattern

Eine Möglichkeit um das Information-Hiding Prinzip umzusetzen stellt das Facade Pattern dar (nähere Infos dazu hier). Bei einer Fassade handelt es sich um einen dezidierten Einstiegspunkt in ein Modul oder Subsystem. Die einzelnen Bestandteile werden gezielt verborgen und jede Interaktion mit ihnen von außen erfolgt über die Fassade. Bei einer REST-API eines (Micro-)Service beispielsweise handelt es sich im Grunde ebenfalls auch immer um eine Fassade.

Law-of-Demeter / Principle of least Knowledge

Beim Law-of-Demeter (zum Ursprung und Namen des Prinzips siehe hier) handelt es sich um einen Spezialfall des Information-Hiding Prinzips. Für den Consumer einer Schnittstelle soll das Zusammenspiel des Providers mit anderen Komponenten möglichst verborgen sein. Der Consumer vemeidet dadurch Abhängigkeiten zu den vom Provider verwendeten weiteren Komponenten. Im folgenden Listing muss der Fahrer wissen, aus welchen einzelnen Bauteilen das Auto besteht, um es zu verwenden. Für die Hersteller des Autos hat dieses Design den Nachteil, bei Änderungen die Fahrer informieren zu müssen, damit diese sich darauf einstellen können.


Car wartburg = new Car();
wartburg.getSeatbelt().fasten();
wartburg.getEngine().start();

Im folgenden Listing sind diese Probleme behoben. Nun kann ich den Verbrennungsmotor durch Elektromotoren auswechseln, die an den Radnaben montiert sind, und außerdem den Start des Autos verweigern, sollte sich der Fahrer nicht angeschnallt haben. Den Fahrer muss ich über diese Änderungen gar nicht informieren.


Car tesla = new Car();
tesla.secureDriver();
tesla.activate();

Wenn Sie konsequent Dinge verbergen stellt sich die Frage, wie den möglichen Consumern der Zugang zur Funktionalität des eigenen Bausteins gewährt werden soll. Hier kommen dann Schnittstellen ins Spiel, was uns auch zu unserem nächsten Beitrag dieser Serie bringt, nämlich: “CONTRACT: Schnittstelle festlegen“. (Coming soon, stay tuned…)