All Posts By

Herbert Dowalil

CUT: Richtig schneiden (5C-Design, Teil 2 von 7)

By | Allgemein, Inhaltliches | No Comments

Je unabhängiger ein Baustein ist, desto einfacher wird er zu handhaben sein. Schneide Bausteine so, dass sie sich möglichst gut voneinander abgrenzen.

  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. It´s a Wrap: Zusammenfassung

Um Komplexität dauerhaft beherrschbar zu machen, gibt es kaum eine Alternative dazu, diese in einzelne kleinere Teile zu zerlegen. Dafür muss man sich zunächst einmal die Frage stellen, an welchen Grenzen diese Abgrenzung denn am besten funktioniert. Wie findet man diese? Im Endeffekt wird der Programmcode der Lösung ein Abbild der fachlichen Anforderungen sein. Die möglichen Grenzen müssten demnach bereits in den Anforderungen auffindbar sein. Warum eine solche “fachliche Grenzziehung” (auch Vertikalität genannt) zu mehr Eigenständigkeit der Bausteine führt möchte ich anhand eines Beispiels verdeutlichen.

Schichten vs. Vertikale Architektur

Abbildung 1 zeigt ein nach klassischer Manier in technische Strukturen zerlegtes System. Daraus ergeben sich die dort abgebildeten Schichten, manchmal auch Layer genannt. Damit werden vorrangig die technischen Aspekte der Lösung betont. Dies hat den Vorteil, dass Entwickler passend zu ihren Stärken Strukturen im Code wiederfinden. Es werden außerdem querschnittliche Themen wie Persistenz gleichartig behandelt, was meist auch gewünscht ist. Auch das User-Interface wird für den Benutzer hier wohl ein durchgängig flüssiges Erlebnis darstellen. Aber: Sobald der Wunsch auftaucht, in irgendeinem der bestehenden Features ein weiteres Eingabe-Feld hinzuzufügen, zieht dies eine Kaskade an Änderungen in allen Layern nach sich. Man beginnt in der DB, zieht dies dann im DB-Access-Layer nach, danach in der Service-Schicht und zum Schluss im UI. Auch wird ein Ausfall einer niedrigeren Schicht sich immer auch auf alle Schichten darüber auswirken. Solch technische Strukturen sind demnach nicht wirklich eigenständig.

Abb. 1: Schichtenarchitektur

Die Alternative zu technischen Strukturen sind fachliche bzw. vertikale Strukturen (siehe Abb. 2). Hier wird besonders die Fachlichkeit betont. Das heißt übrigens nicht, dass man bei näherem Blick in eine dieser fachlichen Strukturen nicht wieder so etwas wie Layer finden wird. Trotzdem: Der Aspekt, der der obersten Abstraktionsebene Form gibt, wird immer etwas stärker betont werden als der sekundäre Aspekt innerhalb dieser primären Struktur.

Abb. 2: Vertikale / Fachliche Architektur

Die Grenzen der fachlichen Zerlegung

Tatsache ist allerdings, dass vertikale Abtrennung in manchen Fällen etwas besser funktionieren wird, und in anderen Fällen wiederum nicht so gut. Die Anforderungen eignen sich nämlich nicht immer in gleichem Maß für eine solche Aufteilung. Manchmal sind bereits die Business-Regeln, die der Fachexperte formuliert, so dermaßen miteinander vernetzt, dass eine effiziente Zerlegung schwierig wird. Werfen Sie dazu bitte einen Blick auf die Architektur, die in Abb. 3 dargestellt ist. Es handelt sich dabei um einen Web-Shop, welcher nach allen aktuellen Regeln der Kunst in fachliche Microservices zerlegt wurde, während die User-Interfaces nach wie vor als monolithische Layer implementiert sind.

Zunächst ist bemerkenswert, dass man ein solch monolithische Design des UI in Microservice-Architekturen häufig antrifft. Hier möchte ich kurz innehalten und die Frage stellen, warum dem eigentlich so ist. Warum klappt hier die fachliche Zerlegung oft nicht so gut wie im Backend? Die Ursache ist bei einer nicht-funktionalen (oder qualitativen) Anforderung zu finden. Wenn ich dem User ein durchgängiges Erleben des UIs ermöglichen möchte, so ist ein vertikaler Architekturstil an dieser Stelle nicht besonders gut geeignet. Daran sieht man, dass qualitative Anforderungen ebenfalls Einfluss auf die optimal mögliche Zerlegung eines Systems haben können.

Im Backend wiederum scheint die vertikale Modularisierung prima geklappt zu haben. Im Service “Kundenkonto” werden die Daten gespeichert, die ich vom Kunden benötige um ihn in der Plattform zu registrieren. Dabei wird die Validität seiner Angaben entweder über eine EMail oder eine SMS geprüft. Aus diesem Grund haben wir das Thema “Kommunikation” hier mit rein gepackt. Weiters gibt es Services für die “Bestellung”, das “Lager”, die “Bezahlung” und die “Lieferung”. Querschnittliche fachliche Themen wie die Daten des Kunden (Zahlungsweise, Lieferadresse, Rechnungsadresse etc.) haben wir ebenfalls auf diese Services aufgeteilt wie das Produkt an sich (Preis, Lagerstand, Beschreibung etc.).

Das Ziel war Logik und Daten jeweils nahe beieinander zu haben um eine Architektur mit hoher Kohäsion und niedriger Kopplung zu erreichen. Dies ist hier auch ganz gut gelungen, wie ich finde. Würde mir das jemand als Architektur zum Review vorlegen mit der Fragestellubg, ob dies gängigen Best-Practices folgt, hätte ich zumindest auf den ersten Blick nichts zu beanstanden.

Abb. 3: Die einwandfreie Microservice-Architektur unseres Web-Shops

Eine neue Anforderung

Ab sofort soll es in gewissen Fällen möglich sein, frische Schnittblumen bei jeder Bestellung mit auszuliefern. Dies kann entweder über Bezahlung möglich sein, oder ab jeweils einem Umsatz von 1000 Euro einmalig als Gratis-Angebot. Dies ist allerdings nur möglich bei Lieferdiensten, die dabei auch mitmachen. Diese müssen nämlich die Blumen immer frisch bei örtlichen Blumenhändlern abholen. Außerdem ist dies nur möglich, wenn es in der jeweiligen Gegend auch einen Blumenhändler gibt, der mit uns kooperiert. Angeboten wird dies außerdem nur weiblichen Kunden. Für männliche Kunden wird überlegt evtl. später ein After-Shave als Bonus den Paketen beizulegen. Allerdings nur solange auch welche auf Lager sind. In welchem der Bausteine würden Sie diese Änderung verorten? Es gäbe dafür diverse Strategien:

  • Man schreibt einen neuen Service “Geschenke”, der genau dieses Feature abbildet.
  • Man gibt das neue Feature irgendwo dazu, z.B. bei Payment, Bestellung oder Lieferung.
  • Man extrahiert aus den bestehenden Services einen neuen namens “Produkt”, der Daten und Logik der Produkte beinhaltet und dabei die Geschenke als Sonderfall behandelt.

Jede dieser Lösungen führt dazu, dass sich die Kopplung zwischen den Services im Vergleich zur Situation davor vergrößert. Dies allerdings nicht, weil keine gute Arbeit geleistet wurde, sondern weil dies die Anforderungen selbst nötig machten.

Fazit

Es gibt nicht nur qualitative Anforderungen, die eigentlich immer querschnittlicher Natur sind. Es gibt ebenfalls funktionale Anforderungen, welche auf gewisse Weise übergreifend sind. Sie vernetzen bestehende Anforderungen und sind nicht so gut als Modul isolierbar. Sie führen dazu, dass sich die Software in Summe nicht so gut modularisieren lässt. Die Aufgabe ist, eine Struktur zu finden, welche möglichst gut zu den fachlichen Anforderungen passt. Außerdem haben Sie idealerweise noch die Möglichkeit, auf Änderungen der Fachlichkeit zu reagieren, indem Sie im Zuge eines Refactorings eine Restrukturierung vornehmen. Abhängig von der Komplexität der Anforderungen selbst wird Ihnen das manchmal besser gelingen, und manchmal sind dem gewisse Grenzen gesetzt. Wenn Ihnen das gelungen ist, geht es weiter mit dem nächsten der 5 C´s, nämlich: “CONCEAL: Verbergen” (Coming soon, stay tuned…).

Software-Entwurf: Ein Blick zurück und nach vorn (5C-Design, Teil 1 von 7)

By | Allgemein, Inhaltliches | No Comments

Als in den 80ern und 90ern des vorigen Jahrhunderts die Objektorientierte Programmierung angetreten ist alle Probleme der Entwicklung komplexer Software zu lösen, fasste Robert C. Martin einige Prinzipien des Software-Entwurfs unter dem Kürzel (und Schlagwort) SOLID zusammen. Diese Sammlung an Prinzipien ist auch heute noch populär, obwohl sich seither einiges getan hat. Anfangs der 2000er wurde dann die “SOA-Sau” durchs Dorf getrieben, und heute muss man sich fast schon schämen, wenn man keine “Microservices” macht. Und das, obwohl der Terminus “Microservices” alles andere als exakt definiert ist und eigentlich einige unterschiedliche Architekturstile umfasst. Die SOLID Prinzipien gab es als eine weithin anerkannte Grundlage des Software-Entwurfs dabei die ganze Zeit. Leider waren diese aber keineswegs hilfreich dabei die SOA zu widerlegen, noch kann man sie als Grundlage für gute Microservice Architekturen zu Rate ziehen.

  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. It´s a Wrap: Zusammenfassung

Über SOLID

Es war 1999 als Robert C. Martin auf der Basis seiner eigenen Arbeit, und der Arbeit einiger anderer wie Bertrand Meyer und Barbara Liskov, seine Top 5 Prinzipien des objektorientierten Entwurfs festgelegt hat. Später erst fiel es einem gewissen Michael Feathers auf, dass man diese prima unter dem Akronym SOLID zusammenfassen kann. Dass diese Abkürzung der Popularität geholfen hat merkt man alleine schon daran, dass die anderen Prinzipien, die er gleichzeitig für Kohäsion und die Kopplung von Packages festgelegt hat, heute kaum noch jemand kennt. Bei SOLID handelt es sich im Detail um die folgenden 5 Prinzipien:

  • Single-Responsibility Principle: Eine Klasse sollte einen, und nur (!) einen Änderungsgrund haben
  • Open-Closed Principle: Sie sollten in der Lage sein, das Verhalten einer Klasse zu erweitern, ohne diese im Zuge dessen ändern zu müssen
  • Liskov´s-Substitutionsprinzip: Abgeleitete Klassen müssen durch ihre Basisklassen ersetzbar sein
  • Interface-Segregation Principle: Entwerfe kleine Schnittstellen, jeweils passend für einen Anwendungsfall der Benützung der Klasse
  • Dependency-Inversion Principle: Sei immer von Abstraktionen abhängig, und niemals von konkreten Implementierungen

Wie man sieht ging man damals davon aus, dass Software-Entwurf dem Entwurf von Klassen entspricht. Darauf lag auch der Fokus von SOLID. Objektorientierung war damals das, was heute Microservices sind. Sie galten als Patentrezept zur Lösung so ziemlich aller Probleme der Software-Architektur. Unnötig zu erwähnen, dass man das heute anders sieht. Die OOP gilt als überschätzt, und auch wenn man ab und zu auf Vererbung setzt, so gilt doch der Grundsatz: Composition-over-Inheritance.

Dependency Inversion

Wenn auch tatsächlich keiner der 5 Punkte in SOLID falsch ist, so möchte ich doch zumindest die damals gültige Interpretation des Dependency-Inversion Prinzips hinterfragen. Robert C. Martin war der Meinung, dass eine Klasse A, welche die Schnittstelle einer anderen Klasse B benützt nicht direkt von Klasse B abhängig sein sollte. Niemals. Stattdessen sollte A eine Abstraktion der benötigten Schnittstelle festlegen. B implementiert dann diese Schnittstelle. Damit wäre die Abhängigkeit umgekehrt (siehe u.a. Abbildung), wenn man die neu hinzugefügte Schnittstelle als Teil von A sieht. Das hätte den positiven Effekt, dass später die Implementierung der Schnittstelle ausgewechselt werden kann. B kann also durch eine andere Klasse C ersetzt werden, wenn diese dieselbe Schnittstelle implementiert. Heute sieht man es keineswegs so, dass dies immer zu geschehen habe, sondern eher, dass dies in Ausnahmefällen Sinn macht. Eine abstrakte Schnittstellendefinition sollte man nur festlegen, wenn:

  • … es mehr als eine Implementierung davon gibt.
  • … es absehbar ist, dass es in naher Zukunft mehr als eine Implementierung davon geben wird.
  • … die Schnittstelle als möglicher Erweiterungspunkt dienen soll. Dies ist oft bei der Entwicklung von Frameworks der Fall.
Abhängigkeitsumkehr, dem D in SOLID entsprechend

Das genügt hoffentlich als Beleg dafür, dass SOLID keinesfalls als allumfassende Grundlage für zeitgemäßen Software-Entwurf gesehen werden kann. Wenn wir Software in ihre Einzelteile zerlegen, und uns dabei an Best-Practices orientieren möchten, dann benötigen wir etwas anderes, moderneres. Bevor wir so etwas entwickeln, schärfen wir aber noch die Zielsetzung. Schließlich gibt es ja moderne Prinzipien-Sammlungen, wie die der 12-Factor-App. Diese hat als konkrete Zielsetzung, dass sich die damit entwickelten Applikationen zum “Deployment auf modernen Cloud-Plattformen eignen, die Notwendigkeit von Servern und Serveradministration vermeiden”. Ein adäquater Ersatz für Robert C. Martins Prinzipiensammlung sollte sich aber eher um Wartbarkeit von Code drehen.

Die IT in der Legacy Krise

Dass Wartbarkeit ein großes Thema ist merkt man alleine schon an der Zahl der komplexen Softwaresysteme, die inzwischen als “Legacy” bezeichnet werden. Meist meint man damit einen gewissen Kontrollverlust, der sich in Instabilität und steigenden Kosten bei den laufenden Updates (der Wartung) am System zeigt. Um hier für Abhilfe zu sorgen werden wir zunächst eine Blick auf mögliche Ursachen werfen. Sobald das Team die Software nicht mehr versteht besteht die Gefahr des Kontrollverlustes. Das Verhalten bei Änderungen an der Software wird dadurch in hohem Ausmaß nicht-deterministisch und es kommt zu unerwünschten Seiteneffekten. Dies kann ganz banale Ursachen haben, wie das Fehlen einer Dokumentation. Oder es wurde den Entwicklern, denen das System zur Wartung übergeben wurde, schlichtweg nicht die Möglichkeit gegeben sich in den Code einzuarbeiten. Meist ist es aber so, dass das System zu komplex geworden ist.

Über Komplexität

Aber was heißt eigentlich Komplexität? Eine mögliche Definition ist, dass es dabei um die Knoten eines Graphen geht, und die Kanten mit denen diese miteinander verbunden sind. Je mehr Knoten in Summe, und je mehr Kanten in Relation zu diesen Knoten ein Graph hat, desto komplexer ist er. Ein Beispiel für eine sehr hohe Komplexität ist im folgenden Bild dargestellt. Es handelt sich bei den außen dargestellten Knoten um die Klassen eines der Module der OpenJPA , und bei den Kanten dazwischen um die Abhängigkeiten dieser zueinander. Man kann sich leicht vorstellen, dass die Wartung dieses Codes zumindest eine Herausforderung darstellt. Wenn die Entwickler der OpenJPA das Ding auch offensichtlich unter Kontrolle haben, so können wir uns hoffentlich darauf einigen, dass diese Situation keinesfalls als erstrebenswert bezeichnet werden kann. Ich habe jedenfalls noch nie erlebt, dass etwas vergleichbares vorab als Zielbild entworfen wurde. Demnach ist davon auszugehen, dass dies irgendwie “passiert” ist und niemals so geplant war.

Ein Teil (!) der Komplexität der OpenJPA Codebasis im Tool Sonargraph

So geht es weiter…

Nachdem wir nun ein gemeinsames Verständnis der Problematik haben, gehen wir einen Schritt weiter und beginnen mit der Lösungssuche. Wir brauchen ein Modell, welches den Entwicklern der Software hilft, dauerhaft die Kontrolle darüber zu behalten. Dazu ist es nötig die Komplexität, die bei der Entwicklung von Software automatisch entsteht, in geordnete Bahnen zu lenken. Dafür gibt es keinen besseren Weg als die Gesamtkomplexität in ihre einzelnen, danach im Kleinen einfacher beherrschbaren, Teile zu zerlegen. Ziel ist, dass diese einzelnen Teile danach:

  • … möglichst ohne Seiteneffekte und Abstimmungsarbeit weiterentwickelt werden können.
  • … unabhängig vom Rest zu dokumentieren und zu verstehen sind.
  • … an ihren ein- und ausgehenden Schnittstellen isoliert getestet werden können.
  • … unabhängig voneinander ausgetauscht werden können.

Im nächsten Teil dieser Artikelserie beginnen wir gleich mit dem ersten logischen Schritt, nämlich der möglichst effizienten Zerlegung eines großen Ganzen in seine Einzelteile und nennen dies: „CUT: Richtig schneiden“! Dabei handelt es sich um das erste von 5 C´s, welche dann in Summe die moderne Sammlung von Prinzipien zum Software-Entwurf darstellen werden.

ModulithFirst_HDowalil_InformatikAktuell

Modulith First! – Artikel von Herbert Dowalil auf Informatik Aktuell

By | Artikel, Publikationen | No Comments

Modulith First! Der angemessene Weg zu Microservices

Logo_Informatik_Aktuell

Modulith First! Der angemessene Weg zu Microservices
Autor: Herbert Dowalil
Artikel auf Informatik Aktuell
online erschienen am 05. März 2019

Hinter dem Microservice-Architekturstil steckt u. a. die Idee, mittels forcierter technischer Abgrenzung durch das Netzwerk die Motivation zur strukturellen und fachlichen Abgrenzung der einzelnen Module (dann Services genannt) zu erhöhen. Dies klappt beileibe nicht immer. Zudem bleibt die Frage, wo genau die Abgrenzung zwischen den einzelnen Services am besten funktioniert? Fachliche, vertikale Strukturen und Domain-Driven-Design sind in aller Munde, stellen aber ebenfalls kein einfach anzuwendendes Patentrezept für eine effiziente Abtrennung von Modulen und Services dar. In diesem Artikel werfen wir einen Blick auf vergleichsweise objektive Ansätze.

Artikel Online Lesen

follow us on Twitter – @embarced

architektur-spicker08

Architektur-Spicker Nr. 8: Nachhaltiges Software-Design

By | Publikationen, Spicker | No Comments
Architektur-Spicker Nr. 8: Nachhaltiges Sofware-Design

Architektur-Spicker


Architektur-Spicker Nr. 8: Nachhaltiges Software-Design
Autor: Herbert Dowalil
Referenzkarte bei architekturSPICKER PDF, 4 Seiten
Erschienen 25. Februar 2019

Download auf architektur-spicker.de

Die aktuelle Ausgabe unseres Architektur-Spickers unterstützt Sie und Ihr Team bei der Auswahl und Umsetzung zeitgemäßer Design-Prinzipien und dem Entwurf einer nachhaltigen Software-Architektur. Vermeiden Sie steigende Aufwände in der Wartungstätigkeit durch fortschreitende Erosion der Codestrukturen.


In dem vierseitigen PDF gehen wir unter anderem auf die folgenden Fragen ein:
  • Wie bleibt die Wartung Ihrer Software langfristig effizient?
  • Welche Prinzipien sind noch zeitgemäß im Sinne der neuen Schule der Softwarearchitektur?
  • Welche Muster und Praktiken setzen diese um?

Architektur-Spicker 1-8


Architektur-Spicker Nr. 8: Nachhaltiges Software-Design

follow us on Twitter – @embarced

Softwarearchitektur Meetup_Wien

Meetup Wien: Mentos Effekt – Ursachen und Lösungsansätze fragiler Wartung von Legacy Systemen

By | Publikationen, Vorträge | No Comments
„Mentos Effekt – Ursachen und Lösungsansätze fragiler Wartung von Legacy Systemen“

 

 

 

 

Die Durchführung von Wartungstätigkeiten an so mancher in die Jahre gekommener Software (a.k.a Legacy System) ist nicht selten von einer ausgesprochen Fragilität. Die Auswirkungen auch von kleinen Änderungen sind im Vorhinein kaum abschätzbar und nicht selten zeigen sich unerwünschte Seiteneffekte an Teilen, die im Zuge des Updates eigentlich gar nicht geändert wurden. Diese potentielle Gefahr führt meist dazu, dass erst recht von notwendigen Refactorings Abstand genommen wird, und es damit zu einer noch schnelleren Erosion der bestehenden Architektur kommt. In diesem Talk gehen wir auf die Ursachen dieser typischen Problematik ein, eruieren wie man diese von Anfang an verhindern kann und zeigen auch Mittel und Wege auf, diesem Teufelskreis wieder zu entkommen.

follow us on Twitter – @embarced

JS_pest-control_Artikel

Artikel JavaSpektrum: Pest Control – Immerwährende Immunität für Java-Code

By | Artikel, Publikationen | No Comments
Immerwährende Immunität für Java-Code

JavaSPEKTRUM Logo




„Pest Control – Immerwährende Immunität für Java-Code“

Autor: Herbert Dowalil

Artikel im JavaSPEKTRUM 06/2018
erschienen am 30. November 2018

Wie schön wäre doch das Leben eines Softwareentwicklers, wenn da nicht die lästigen Wanzen, genannt Bugs, wären, die sich immer wieder ungefragt in unserem Code breitmachen. Warum sind einige Systeme wesentlich weniger anfällig für Bugs als andere? Tatsächlich ist es möglich, durch Anwendung mancher Designprinzipien, Software schon im Zuge der Erstellung gezielt robust zu gestalten.

Eine Garantie, dass keine Fehler mehr gemacht werden, kann und wird es natürlich nie geben. Tatsache ist aber auch, dass man durch manch einfache Maßnahme die Robustheit von Software spürbar verbessern kann. Darüber hinaus können die in diesem Artikel angeführten Maßnahmen auch einen ersten Schritt zu einer langlebigen Softwarearchitektur bedeuten. Mich hat die Erfahrung gelehrt, dass sich eine solche am besten bottom-up im Laufe der Evolution der Software entwickelt. Dies funktioniert dann auch klar besser als ein Big Up Front Design eines zentralen Architekturteams.

Digitale Ausgabe JavaSPEKTRUM

 
follow us on Twitter – @embarced

Architektur Meetup Wien

Softwarearchitektur Meetup Wien: Evolutionäre-Architektur & Digitalisierung

By | Allgemein, Publikationen, Vorträge | No Comments

Meetup

 Evolutionäre-Architektur & Softwarearchitektur/Digitalisierung
Impuls und Moderation: Stefan Toth & Herbert Dowalil
Veranstaltung beim Softwarearchitektur Meetup Wien
05. November 2018, 18:00 Uhr
weXelerate, Praterstrasse 1 in Wien

Foliendownload (PDF)

Evolutionäre Architekturansätze können helfen, sich kleinteiliger und stetiger um Innovation zu kümmern und auch mit größeren Systemen über längere Zeit hohe Qualität auszustrahlen. Sie werden mehr und mehr der neue Standard – das neue Normal.

Beim neuen Softwarearchitektur Meetup gestern Abend in Wien gab Stefan Toth einen Überblick, welche Faktoren Softwarearchitektur heutzutage erfolgreich machen, um in einem dynamischen Umfeld zu bestehen. Er stellte den Zyklus evolutionärer Architekturentwicklung vor – von Lernfenstern mit Experimenten und erlaubten Abweichungen vom „Standard“, über weich definierte Regeln und geförderte Innovation bis hin zur eingeschränkten Anwendbarkeit von überholten Konzepten. Dabei spielen aktuelle Konzepte wie Anti-Zähigkeit und Fitness-Functions eine zentrale Rolle. Praxisbeispiele aus realen Entwicklungsvorhaben verdeutlichen die Ansätze. Fast 60 Teilnehmer waren beim Kickoff des Wiener Meetups in den Räumen von weXelerate dabei und es gab einen regen Austausch zwischen Speakern, Besuchern und Organisatoren!

Stefan Toth - Softwarearchitektur Meetup Wien: Evolutionäre-Architektur


Unser nächstes Meetup ist für den 12. Dezember 2018 geplant – wir freuen uns auf den Austausch in Vorträgen, Diskussionen und interaktiven Formaten!

Fotos vom Softwarearchitektur Meetup am 05. November 2018:


















Bullshit_Bingo_Artikel JAXenter

Artikel auf JAXenter – Hohle Phrasen in der IT erkennen und vermeiden

By | Artikel, Inhaltliches, Publikationen | No Comments
Bullshit Bingo: Wie man hohle Phrasen in der IT erkennt und vermeidet

JAXenter Logo


Bullshit Bingo: Wie man hohle Phrasen in der IT erkennt und vermeidet
Autor: Herbert Dowalil
Online-Beitrag bei JAXenter, erschienen am 19. Oktober 2018

Online lesen auf JAXenter


Jeder kennt ihn, jeder belächelt ihn und jeder benutzt ihn hin und wieder mal als Werkzeug, um unverdient zu Glänzen: Den Bullshit. Er ist in unserer Branche so omnipräsent, dass er eigentlich kaum noch wegzudenken ist. Es muss die Frage erlaubt sein, worum es sich dabei eigentlich handelt und warum gerade wir in der IT so massiv darunter zu leiden haben.

Online lesen

 
follow us on Twitter – @embarced

HD_DZone_Visibility Metrics

DZone Article – Visibility Metrics and the Importance of Hiding Things

By | Artikel, Publikationen | No Comments
Visibility Metrics and the Importance of Hiding Things

DZone


Why is it important to hide the things a module contains from its consumers in microservice architecture? Hiding things is important when designing a sustainable architecture. There are a couple of ways to hide internal structures and design decisions from the outside world and from the consumers of a modules API. These days, microservices are very popular. The microservice community argues, that distribution over the network is the one and only way to actually hide the internals of modules (here services). We just need to take a quick look at good old Java, where we already have plenty of options for hiding, even without using tools or proprietary libraries.

Controlling this by using metrics and maybe even tool support can be crucial for success. Just recently I was wondering, how to measure how well a piece of software is in hiding things. Surprisingly there was no software metric and no tool so far that offered a possibility to measure this. The Visibility Metrics described in the article helped me to solve the problem..

..read more

 
follow us on Twitter – @embarced

Software vermessen_Blog Dowalil

Über die Vermessung von Software

By | Inhaltliches | No Comments


“If you can´t measure it, you can´t manage it”

Das wusste schon Peter Drucker! Wenn sich die Qualität von Software als Zahl wiedergeben lässt, so wird es wesentlich einfacher gute Entscheidungen zu treffen. Aber auch wenn Sie so eine Bürde nicht zu tragen haben, möchten Sie vielleicht wissen, wie weit Sie im Zuge von Verbesserungsmaßnahmen eines Produktes bereits gekommen sind. Es ist also kein Wunder, dass es den Wunsch nach der Objektivierung durch Kennzahlen in der Welt der IT ebenfalls gibt. Zunächst klingt es verlockend, denn so scheint es doch, als würden sich die Bits und Bytes von Software besonders für die Abbildung durch Metriken eignen. Tatsächlich habe ich in meiner Karriere aber sehr oft erleben müssen, dass durch die Anwendung einer Kennzahl mehr Schaden angerichtet wurde, als Nutzen generiert. In diesem Artikel möchte ich Ihnen einerseits Möglichkeiten aufzeigen, Software in Zahlen zu Vermessen, als auch andererseits vor typischen Fallstricken warnen, die es im Zuge dessen zu vermeiden gilt.

Kategorien von Software Metriken
Zyklomatische Komplexität nach McCabe als Beispiel
Mögliche Fallstricke beim Einsatz von Metriken
Mögliche Lösungsansätze beim Umgang mit Metriken

Eingehen möchte ich auf Kennzahlen zur Messung von Komplexität und struktureller Qualität von Software. Tatsächlich gibt es noch weitere Kategorien von Metriken im Umfeld von Software. Bei der folgenden Auflistung beziehe ich mich dabei ausschließlich auf Kennzahlen, welche sich auf das fertige Software-Produkt beziehen, und nicht auf solche, die im Umfeld davon existieren. Es gibt Kennzahlen, welche versuchen die Produktivität bei Entwicklung der Software zu vermessen, oder die Effizienz im Zuge der Benutzung. Dies ist aber nicht Fokus dieses Artikels und ich verweise dafür auf das Buch Software in Zahlen von Harry M. Sneed, Richard Seidl und Manfred Baumgartner.

Kategorien von Software Metriken

Quantität

Dabei wird die schiere Menge an Software gemessen, welche vorhanden ist. Es kann sich um die Anzahl an Codezeilen handeln, die Anzahl an Klassen, Codedateien oder auch Bildschirmmasken, welche vorhanden ist. Der Vorteil dieser Art von Kennzahl ist die Transparenz, da man sich darunter relativ einfach etwas vorstellen kann. Der Nachteil ist, dass es relativ wenig über die Software aussagt. Beim Hauptschirm einer Applikation wie Microsofts Word ist mit Sicherheit das x-fache an Komplexität enthalten, als in einer durchschnittlichen Bildschirmmaske.

Komplexität

Wie schwierig ein Stück Software zu verstehen oder zu entwickeln ist wird wesentlich besser von den Kennzahlen aus dem Gebiet der Komplexität wiedergegeben. Wenn Sie die Wartungs- oder Entwicklungstätigkeiten in Relation setzen möchten, so verwenden Sie bitte besser eine dieser Kennzahlen.

Struktur

Diese Art von Metriken misst die Kapselung des Codes in Bausteine, und auch, wie diese dabei zueinander in Relation stehen. Beispiele dafür wären die Software-Package-Metrics von Robert C. Martin oder auch die Metriken von John Lakos. Ich ziehe dabei diejenigen von John Lakos vor, da diese Abhängigkeiten transitiv betrachten. Eine Abhängigkeit, wo Baustein B den Baustein A benötigt wirkt sich dort nämlich auch auf einen potentiellen Baustein C aus, wenn dieser den Baustein B benützt. Dies entspricht viel mehr der tatsächlichen Natur der Abhängigkeiten im Code.

Testautomatisierung

Die bekannteste Kennzahl aus dem Bereich der automatisierten Tests ist mit Sicherheit die der durch Unit-Tests abgedeckten Code-Zeilen. Testabdeckung wird dabei aber auch durch System- und Integrationstests erzeugt, welche zwar ebenfalls Code automatisch testen, dabei aber nicht die Kennzahl der Abdeckung durch Unit-Tests beeinflussen. Das kann ein guter oder schlechter Aspekt dieser Kennzahl sein. Tatsächlich ist meine Erfahrung, dass eine sehr niedrige Abdeckung durch Unit-Tests ein Indiz für das Fehlen von Strukturen in der Codebasis darstellt. Unit-Tests testen nämlich per definitionem gezielt die einzelnen kleinsten Bausteine des Codes. Wenn dies nicht passiert, so ist es nicht selten so, dass es diese Zerlegung in Bausteine nicht gibt und das Unit-Testen dadurch gar nicht erst möglich ist.

Qualität

Die Erfüllung gewisser Qualitätsmerkmale der laufenden Software kann ebenfalls recht gut auf objektive Art und Weise gemessen werden. Ein Beispiel dafür ist die Zuverlässigkeitsmessung nach Tom Gilb, welche schlichtweg wie folgt errechnet wird:

(Anzahl richtiger Ergebnisse) / (Anzahl aller Ergebnisse)

Andere Beispiele wären die durchschnittliche Zeit bis zum Zusammenbruch des Systems (Mean-Time-to-Failure) und die durchschnittliche Zeit bis sich dieses wieder von seinem Problem erholt (Mean-Time-to-Recover). Eine Messung der durchschnittlichen Response Time würde wiederum die Erfüllung von Performance Anforderungen prüfen.

Zyklomatische Komplexität nach McCabe als Beispiel

Verdeutlichen möchte ich die Thematik noch anhand eines konkreten Beispiels, nämlich der Zyklomatischen Komplexität nach McCabe, da es sich dabei um die populärste der Komplexitätsmetriken handelt. Als Beispiel soll uns das folgende Code-Snippet dienen:


while (x < 100) {                  // 1

   if (values(x) % 2 == 0) {       // 2 
      parity = 0;                  // 3 
   } else {
      parity = 1;                  // 4 
   }                               // 5 

   switch (parity) {               // 6 
   case 0: 
      System.out.pritln("Even");   // 7 
      break; 
   case 1: 
      System.out.println("Odd");   // 8 
      break; 
   default: 
      System.out.println("Weird"); // 9 
      break; 
   } 

   x++;                            // 10 
}
result = true;                     // 11


Diese Abbildung illustriert die möglichen Wege durch dieses relativ kurze Stück Code. Hier sehen wir 11 verschiedene Knoten (welche auch im Code durch Kommentare am Zeilenende markiert sind) sowie 14 Pfeile, welche die möglichen Pfade zwischen dieses Knoten illustrieren. Die Formel lautet nun:

(Anzahl Pfeile) – (Anzahl Knoten) + 2

Was im konkreten Fall eine zyklomatische Komplexität nach McCabe von 5 ergibt.

Bleibt noch die Frage zu beantworten, was man denn nun konkret mit einer solchen Kennzahl wie McCabe anfangen kann?! Eine mögliche Anwendung ist die Beantwortung der Frage, ab wann man einen Baustein (wie eine Klasse) auf Grund seiner Komplexität weiter aufteilen sollte. Ein hohes Maß an Komplexität könnte bedeuten, dass diese eine Klasse mehr als nur eine Verantwortung hat, was aber im Sinne des Single-Responsibility-Prinzips nicht sein sollte. Außerdem ist eine derart komplexe Klasse auch für den Entwickler schwieriger zu verstehen, und sollte daher eher auf weitere Einzelteile aufgebrochen werden. Es ist demnach durchaus sinnvoll, eine Obergrenze für Komplexität für Klassen oder Methoden festzulegen.

Mögliche Probleme beim Einsatz von Software Metriken

Leider gibt es jede Menge Fallstricke, welche es auf dem Weg zum erfolgreichen Einsatz von Metriken im Unternehmen zu vermeiden gilt. Die am häufigsten anzutreffenden sind:

Einschränkende Sicht auf die Gesamtproblematik

Eine Kennzahl ist eine numerische Abstraktion eines Aspektes einer Software. Die Gefahr beim Messen einer solchen ist, dass daraufhin dieser Aspekt maximiert wird, und dadurch nicht erfasste Aspekte vernachlässigt werden. Ein Beispiel dafür: Ein Unternehmen war ausgesprochen unglücklich über die hohen Kosten, welche vom Rechenzentrum für CPU Zeiten berechnet wurden, welche am Großrechner anfielen. Ergo gab man das Ziel aus, die CPU Nutzung am Großrechner messbar zu reduzieren. Als möglicher Verursacher wurde die Kompilierung von Cobol Sourcen ausgemacht. Auf die Aufforderung, die Sourcen in Zukunft auf alternativer Hardware zu übersetzen und erst danach auf den Großrechner zu übertragen, konnte das Development Team aufzeigen, dass die Kosten für die Mehraufwände die möglichen Ersparnisse durch die Reduktion der CPU-Zeiten überstiegen hätten.

Auf Umwegen zum Ziel

Viele Wege führen nach Rom. Ähnliches gilt für die Erfüllung von Kennzahlen. Meist möchte man, dass mit der gewünschten Veränderung einer Kennzahl auch eine gewünschte Veränderung im Unternehmen stattfindet. Allerdings wird dieses eigentliche Ziel dabei oft nicht erreicht, einfach weil übersehen wird, dass ein für die Mitarbeiter angenehmerer Weg ebenfalls zum gewünschten Ziel führt. Im schlimmsten Fall kann genau das sogar zu einer Verschlechterung der Situation führen. Das klassische Beispiel um dies darzustellen ist die folgende Geschichte, die sich so angeblich in Indien zugetragen hat, als es noch von den Briten besetzt war: Ein Gouverneur wollte die Anzahl der Kobras in seinem Herrschaftsgebiet reduzieren, indem er ein Kopfgeld für jede tote Kobra ausbezahlte. Das Ergebnis war aber, dass sich die bestehende Kobra-Plage in der Gegend sogar noch verschlimmerte. Durch das Kopfgeld erhielten tote Kobras plötzlich einen Wert. Was dazu führte, dass die Einwohner begannen, Kobras zu züchten und später zu töten, um diese Prämie zu kassieren. Manche dieser Tiere entkamen und verschlimmerten dadurch sogar die Problematik.

Ein Beispiel aus der IT Praxis ist die folgende Anekdote: Ein Konzern wollte von einem der großen Consultingunternehmen ob der Produktivität seiner Programmierer bescheid wissen. Das Unternehmen untersuchte die beiden Teams, von denen eines für die Erstellung und Wartung von Cobol Sourcen verantwortlich war, und das andere entsprechend für den Java Code. Das Ergebnis dieser Untersuchung war: Man sollte auf Cobol Entwicklung umsteigen, weil dieses Team angeblich wesentlich produktiver wäre. Was war hier geschehen? Gemessen wurde die Anzahl an Codezeilen in Relation zu den Stunden, welche die Mitarbeiter zur Programmierung dessen brauchten. Da derselbe Sachverhalt in Java allerdings in wesentlich weniger Codezeilen ausgedrückt werden kann, war man danach irrtümlich der Meinung, dass Cobol Entwicklung produktiver wäre.

Falsche Anreize

Verschärft wird jede Art von Problemen mit Kennzahlen immer, wenn an der Erfüllung eines gewissen Grenzwertes der Erfolg von Mitarbeitern gemessen wird. Ganz besonders dann, wenn damit ein monetärer Anreiz verbunden ist. Überlegen Sie sich also gut, ob sie eine finanzielle Belohnung im Umgang mit Metriken einsetzen möchten.

Mögliche Lösungsansätze

Ich hoffe ich konnte Sie überzeugen, dass beim Einsatz von Metriken zur Vermessung von Software auf jeden Fall Vorsicht geboten ist. Nachdem Sie nun aber genug über Probleme gelesen haben, möchte ich nun zu möglichen Lösungsstrategien zur Thematik kommen. Was empfiehlt sich, um mit Metriken auch tatsächlich erfolgreich zu sein?

Wenig reduzierend

Den Terminus “gesamtheitlich” vermeidend möchte ich empfehlen, Kennzahlen zu wählen, welche bei der Auswahl der Aspekte des Erfolges möglichst wenig einschränkend sind. Also so breit wie möglich die Güte der Arbeit der Mitarbeiter wiedergeben. Dadurch wird vermieden, dass nur ein Aspekt besonders betont wird und somit falsche Prioritäten gesetzt werden. Dies hat wiederum den Nachteil, dass es somit u.U. schwierig wird, die Performance einzelner Teams einzuschätzen. Entschärfen können Sie diese Problematik wiederum durch eine Organisation um die fachlichen Teilbereiche der Problemdomäne herum. Ein Team ist dann genau der Behandlung einer Subdomäne (oder Business Capability) zugeordnet und dafür verantwortlich. Anhand dessen kann der Erfolg prinzipiell recht umfangreich, aber eben nur für einen solchen Teilbereich, gemessen werden. Wesentlich schwieriger is so etwas, wenn Ihre Organisation anhand der Aufgaben bei der Entwicklung von Software strukturiert ist, wie Analyse, Architektur, Entwicklung und Test. In so einem Fall könnten isolierte Kennzahlen sogar die Zusammenarbeit zwischen den Teams behindern. Wenn jedes Team an der Erfüllung der eigenen Kennzahl gemessen wird, dann wird es auch alles danach ausrichten, diese zu optimieren, und zur Not die Schuld, wenn es nicht klappen sollte, bei anderen suchen.

Zusammenfassen

Um nicht reduzierend zu wirken kann man Kennzahlen auch kombinieren. Dafür müssen sie natürlich zuerst in ein einheitliches Format gebracht werden. Für Software bietet es sich an, Verfehlungen bei Metriken in Aufwänden zu messen, welche im Zuge einer Behebung anfallen würden. Wenn es sich bei der Metrik beispielsweise um “Anzahl zyklischer Abhängigkeiten zwischen Modulen” handelt, dann kann diese Umrechnung erfolgen, indem man eine Zeiteinheit (z.B.: 1 Manntag) definiert, welcher nötig wäre, um einen Zyklus im Code zu beheben. Die Aufwände berechnen sich dann wie folgt:

(Anzahl_Zyklen – Obergrenze_Anzahl_Zyklen) * Aufwand_pro_Zyklenbehebung

Wenn Sie das für all Ihre Kennzahlen machen, können Sie die Aufwände am Ende summieren. Das u.a. als Plugin für SonarQube erhältliche SQALE Rating tut etwas ähnliches. Es errechnet zuerst die Kosten der gefundenen Issues im Code (Technical Debt) und erstellt daraus ein Scoring indem es die Kosten für Issues zur Quantität des Codes in Relation setzt. Das Ergebnis geht dann von A (gut) bis F (schlecht) und ist somit sehr plakativ. Etwas problematisch an SQALE finde ich, dass es teilweise Kennzahlen verwendet, welche in meinen Augen “Kobras” sind, wie die Anzahl der dokumentierten public Methoden in Java. Diese sollte man nicht messen, da es dadurch dazu kommen kann, dass veraltete und unverstandene Kommentare von den Entwicklern nicht gelöscht werden. In so einem Fall ist aber kein Kommentar besser als ein schlechter Kommentar. Außerdem ist es möglich (und auch besser) Code auf eine Art und Weise zu schreiben, sodass er im Endeffekt selbsterklärend ist, wodurch es dann keinen expliziten Kommentar mehr braucht.

Gezielte Auswahl für einen bestimmten Anwendungsfall

Es gibt meiner Erfahrung nach durchaus Problemgebiete, deren Erfüllungsgrad durch einige sehr passende Kennzahlen sehr gut wiedergegeben werden. Die Qualität der Strukturen von Software ist so ein Beispiel. Wenn Sie dies messen möchten, so empfehle ich Ihnen die Kennzahl NCCD aus der Familien der Kennzahlen von John Lakos. Eine Alternative stellt die Messung und Kontrolle der Relativen Strukturzyklizität dar, welche auch gut Schritt-für-Schritt gezielt erreicht werden kann, was motivierende Effekte auf ein Team haben kann.

Lockerer Umgang mit dem Thema

Monetäre Anreize führen manchmal zu einer Übermotivation bei der Erfüllung einer bestimmten Metrik. Und das Team vernachlässigt dann andere Aspekte des Erfolgs. Ähnlich verhält es sich, wenn aufgrund einer Untererfüllung eines Kennzahl-Grenzwertes harte Entscheidungen getroffen werden. Wenn in so einem Fall nicht mehr deployt werden kann, dann werden sich die Mitarbeiter Tricks einfallen lassen, um diese Kennzahl zur Not irgendwie noch zu erfüllen. Stattdessen können Sie auf die intrinsische Motivation Ihrer Mitarbeiter setzen. Kommunizieren Sie Ihrem Team bei jeder Gelegenheit wie weit es bei der Erfüllung seiner Ziele bereits ist. Wenn die Mitarbeiter bei der Auswahl der Kennzahlen teilhaben durften, wird die Motivation umso höher sein.

Fitness Functions

Fitness Functions, als Idee aus dem Buch Building Evolutionary Architectures von Neal Ford, Rebecca Parsons und Patrick Kua, basieren nicht selten auf Metriken, gehen aber in ihrer Definition noch darüber hinaus. Es werden dabei entweder punktuell oder laufend, einzelne oder gesamtheitliche Aspekte der Software überwacht. So kann ein einfacher Unit-Test, der auf ArchUnit oder JDepend basiert prüfen, ob die Modulstruktur des Systems auch frei von zyklischen Abhängigkeiten ist. Dies wäre atomar und punktuell. Die Simian Army von Netflix wiederum prüft kontinuierlich und holistisch die Stabilität der Produktionsumgebung. Mehr Informationen dazu im Blog-Beitrag zum Thema Evolutionäre Architektur.

Werkzeuge

Hier noch ein Überblick welche Kennzahl in welchem Tool umgesetzt ist:

Tool Plattformen LCOM4 Relational Cohesion McCabe Visibility Depth-of-Inheritance Component Rank Software Package Metriken John Lakos Metriken Zyklen-Erkennung Architektur Soll/Ist Prüfung
Axivion Bauhaus Suite C/C++, C#, Java + + + +
Sonargraph C/C++, C#, Java, Python + + + + + + + + + +
JDepend Java + + +
Structure101 Java + + +
STAN Java + + + + +
NDepend / CppDepend / JArchitect C/C++, C#, Java + + + + + +
SDMetrics UML + + +

Fazit

Metriken können ein mächtiges Werkzeug zur Entwicklung und Kontrolle diverser Qualitätsaspekte im Unternehmen sein. Bei der Auswahl und dem Einsatz ist aber Vorsicht geboten. Im Zuge meines Trainings zum Thema Software-Design erlernen die Teilnehmer Schritt für Schritt worauf es bei Messung und Entwicklung effektiver Strukturqualität ankommt.

Nähere Informationen zu diesem Thema finden Sie in meinem Buch Grundlagen des modularen Softwareentwurfs, dessen Kapitel 9 zu diesem Zweck mit freundlicher Genehmigung des Carl Hanser Verlages zur Verfügung gestellt wurde:

Download: Grundlagen des modularen Softwareentwurfs / Kapitel 9