Tut es weh? Mach es nochmal (oder hör auf)!

23 Mai 2017

Softwareprojekte werden heutzutage in der Regel so abgewickelt, dass zunächst eine Spezifikation einer Anforderung erstellt wird. Anschließend überlegt sich jemand, wie man diese Anforderung umsetzen kann. Abschließend kommt es zur Umsetzung. Dieses Vorgehen ist in seiner Größe natürlich variabel. Statt nur eine Anforderung werden eventuell auch mehrere gleichzeitig spezifiziert. Es ändert aber nichts am generellen Vorgehen; auch nicht, wenn viele verschiedene Dokumente erstellt werden.

Bei Methoden wie Scrum gibt es dann Zyklen, vor denen eine Spezifikation erstellt wird. Während eines Zykluses findet dann die Implementierung statt. Abschließend gibt es ein Review und eine Retrospektive. Dieses Vorgehen wiederholt sich in Zyklen von zum Beispiel zwei Wochen. Reviews können insofern weh tun, als dass man nach zwei Wochen merkt, dass man in die falsche Richtung entwickelt hat. Es hat aber auch den Vorteil, dass es eben nur zwei Wochen sind.

Wenn man nun alle zwei Wochen eine Anwendung bereitstellt, muss man sich zwangsläufig auch über Migration Gedanken machen. Denn neue Anforderungen bedeuten in der Regel auch Änderungen an der Datenbank oder an Verzeichnissen. Wenn man dann nach zwei Wochen den Testern sagt, dass die Inhalte der Datenbank gelöscht werden, stößt das Vorgehen irgendwann auf seine Grenzen. Das bedeutet dann, dass man sich eine Strategie überlegen muss, wie man Skripte zur Migration organisiert.

Ebenso verhält es sich beim Erstellen eines Releases. Wenn alle zwei Wochen ein Release gebaut wird, kann das eventuell einen großen Teil der Zeit in Anspruch nehmen. Dass dadurch Zeit für die Implementierung von neuen Anforderungen wegfällt, liegt auf der Hand. Auch dafür ist dann eine Strategie zu entwickeln, um zum Beispiel die Erstellung eines Releases zu automatisieren.

Scrum schlägt einen Rahmen vor, wie man aus Projektsicht mit unangenehmen Vorkommnissen umgehen kann: In kleinen Zyklen wiederholen! Das sollte aber nicht nur aus Projektsicht so sein, sondern auf allen Ebenen der Softwareentwicklung.

Wenn es also "weh tut", hilft Routine durch häufiges Wiederholen. Manchmal ist es aber auch sinnvoll, aufzuhören und sich eine Alternative zu überlegen.

Software Engineering - Trennung von Schnittstellen

09 Mai 2017

Mal angenommen es gibt 4 Systeme, die über eine Datei als Schnittstelle miteinander gekoppelt sind. Jedes der 4 Systeme kann schreibend oder lesend darauf zugreifen.

Problematisch sind dabei nicht die verschiedenen Systeme, sondern dass von allen eine Schnittstelle verwendet wird. Wenn also ein System eine Änderung an der Schnittstelle benötigt, sind alle anderen Systeme ebenfalls betroffen. Dass dadurch die Wartbarkeit beinahe bei 0% liegt, macht ein solches Konstrukt die Optimierung von Prozessen fast unmöglich.

Fraglich ist bei einem solchen Konstrukt, ob es überhaupt fachlich Sinn macht. Aus meiner Sicht kann das in der Regel nicht so sein, weil es ja einen Grund hat, warum es verschiedene Systeme sind. Dieser Grund kann dann auch nur fachlich sein, weil die Systeme verschiedene Funktionalitäten implementieren.

Funktionalitäten haben wiederum in der Regel unterschiedliche Anforderungen. Das kann insbesondere auch die Granularität der zu liefernden Daten betreffen. Durch die eine Datei als Schnittstelle muss diese Granularität an das System angepasst werden, das die niedrigste Aggregation der Daten benötigt.

Die Zeit, die vielleicht bei der Implementierung durch nur eine Schnittstelle gespart wurde, geht natürlich spätestens bei einer eventuell nötigen Optimerung verloren. Noch mehr Zeit geht verloren, wenn bis dahin wegen Schnittstellenänderungen alle 4 Systeme angepasst werden müssen.

Natürlich kostet es Zeit, verschiedene Schnittstellen zu implementieren. Wenn man sich die Zeit also nimmt, spart man sich langfristig Zeit und kann bei notwendigen Änderungen schneller reagieren und auf Absprachen zwischen vielen Systemen verzichten.

Software Engineering - Trennung von Informationen basiert auf Fachlichkeit

27 Januar 2017

Unter Meine Datenbank gehört mir schreibt Eberhard Wolff darüber, dass Module nicht ein Datenbankschema teilen sollten. Stattdessen sollte jedes Modul ein eigenes Datenbankschema verwenden. Er begründet das mit dem Konzept des Information Hidings, das nicht nur für Klassen gelte.

Das hört aus meiner Sicht natürlich nicht bei der Datenbank auf, sondern gilt auch auf allen anderen Ebenen. Informationen, die fachlich nichts miteinander zu tun haben, gehören nicht in ein Modul und auch nicht in einen Strukturbaum. Einen solchen Strukturbaum gibt es bei Entitätsklassen. Zwei Strukturbäume ließen sich einfach über bidirektionale Beziehungen verknüpfen. Das sollte unbedingt vermieden werden, weil auch hier die Änderbarkeit leidet. Dass wir Daten in verschiedenen Klassen oder Tabelllen unterbringen, gehört zum Alltag eines Software-Entwicklers.

Diese geschickte Trennung von Informationen gehört zum Software Engineering und basiert immer auf der Fachlichkeit. Das Konzept lässt sich nicht nur auf Klassen anwenden, sondern eben auch auf Module. Meine Erfahrung ist bisher leider, dass sich viele Entwickler mit der Fachlichkeit kaum auseinandersetzen wollen. Diesen Entwicklern Entscheidungen basierend auf der Fachlichkeit zu erläutern ist oft schwierig. Problematisch wird es, wenn diese Entscheidungen ignoriert werden. Umso wichtiger ist es für Software-Entwickler, sich nicht nur mit den neuesten Techniken zu beschäftigen, sondern einen genauen Blick auf die Fachlichtkeit zu werfen. Meine Erfahrung ist nämlich auch, dass man mit Wissen über die Fachlichkeit, Systeme viel einfacher umsetzen kann.

Wissenstransfer durch Review?

31 Oktober 2014

Es gibt ja diverse Ideen, Wissen über ein laufendes System und dessen Kontext von einem Wissenden zu einem Unwissenden zu übertragen. Dokumentationen zu schreiben ist sicherlich nicht die Lieblingsaufgabe eines Softwareentwicklers; aber es gehört dazu. Diese als Softwareentwickler auch zu lesen, ist meist ebenfalls wenig spannend, wenn man ein System kennen lernen möchte; insbesondere wenn diese dann auch noch veraltet ist und die Wahrheit sowieso im Code steht. Eine Dokumentation zu lesen ist also eher wenig geeignet. Es geht auch nicht in kurzer Zeit, sondern ist ein Prozess. Hier möchte ich einmal veranschaulichen, wie man Schritt für Schritt jemanden ein System näher bringen kann. Dabei soll darauf geachtet werden, dass beide Seiten nicht frustriert werden und für beide (gern auch für Dritte) ein Mehrwert entsteht.
Der fachliche Kontext eines Systems ist in der Regel schnell erklärt durch Fragen wie:
– Warum ist das System da?
– Was sind die Hauptfunktionen des Systems?

Wie etwas umgesetzt ist und warum interessiert an dieser Stelle nicht; das ist zuviel Detail für jemanden, der das System kennenlernen soll. Das langweilt in der Regel und die Aufnahmefähigkeit des Menschen ist eben auch nur begrenzt. Ein Wissender kann hier schnell über das Ziel hinausschießen. Natürlich sollen aber auch die Fragen der Unwissenden berücksichtigt und beantwortet werden.

Der nächste Schritt ist dann, den Unwissenden die Tücken des Systems entdecken zu lassen – selbstständig; ab ins kalte Wasser! Angenommen es gibt rund um das System wiederkehrende Aufgaben zu erledigen. Dann lässt man den Unwissenden diese erledigen. Er wird einen Teil vielleicht schon allein durch die beantworteten Fragen alleine lösen können. Für den anderen Teil wird er auf den Wissenden zugehen. So entdeckt der Unwissende nach und nach das System und kann vielleicht auch die ersten Zusammenhänge erkennen. Das Ganze immer zusammen mit dem Wissenden. Es ist also wichtig, dass sch der Unwissende traut, bei ihm im Zweifelsfall nachzufragen. Dazu sollte man abhängig vom System einen Zeitraum absprechen, der die Tücken auch erkennen lässt. Bei einem System, das jeden Tag läuft könnte das eine Woche sein.
Sollten die Tücken gar nicht oder nicht vollständig dokumentiert sein, wird der Unwissende in der Regel von sich aus dies nachholen. Dies dann für alle zugreifbar zu machen, ist anschließend nur noch ein kleiner Schritt.

Im nächsten Schritt geht es dann in den Code. Pair-Programming macht in einem solchen Fall keinen Sinn, da der Wissensstand einfach viel zu unterschiedlich ist. Der Wissende wird für den Unwissenden zu schnell zwischen den Klassen hin- und herspringen und der Unwissende fühlt sich unsicher, weil der Wissende ihm zeigt, wie es gehen muss; auf beiden Seiten Frust!
Der Unwissende soll also sein Tempo selbst bestimmen und seine eigenen Ideen entwickeln können. Dazu sollte er eine Aufgabe bekommen, die in sich abgeschlossen ist und in wenigen Stunden erledigt werden kann. Der Wissende sollte dann bereit sein, eine Einstiegshilfe zu geben; also Klassen nennen, die mit der Aufgabe zu tun haben. Anschließend kann der Unwissende den Kontext der Klassen analysieren und die Aufgabe lösen.
Anschließend legt der Unwissende die Lösung dem Wissenden zum Review vor. Dafür gibt es sehr gute Tools wie Atlassian Crucible. Am Anfang wird es unter Umständen viele Anmerkungen geben. Aber
der Unwissende wird immer mehr zum Wissenden, je mehr Aufgaben er löst. Wenn es viele Aufgaben in kurzer Zeit gibt, ist es sehr schnell soweit, dass der zunächst Unwissende mit dem Wissenden über Lösungen diskutieren kann. Dann ist auch die Zeit für Pair-Programming gekommen.

Speziell die Reviews sind eine sehr gute Unterstützung für Feedback und bieten die Möglichkeit für Diskussionen fokussiert auf den Code; nur von Änderungen betroffene Klassen werden betrachtet.
Die beschriebenen Schritte werden nicht unter allen Umständen funktionieren. Aber wenn beide Seiten motiviert sind, das Wissen zu teilen und auch Neues aufzunehmen (beides gilt für beide Seiten), profitieren beide Seiten und am Ende natürlich auch der Arbeitgeber oder Kunde.

SEPA-Dateien durchsuchbar machen

27 Oktober 2014

Am 09.10.2014 wurde mein insgesamt 4. Pressebericht von meinem Arbeitgeber veröffentlicht: Big Data durch SEPA: Mehr Zahlungen, mehr Transaktionen, mehr Kosten.
Dort habe ich beschrieben, wie man mit einer nicht relationalen Datenbank Transaktionen abspeichern könnte. In meinem aktuellen Projekt setzen wir dafür Elasticsearch ein.
Dies war allerdings nicht unsere erste Lösung. Zunächst haben wir Apache Lucene verwendet. Dies wird auch in Elasticsearch verwendet. Allerdings kapselt Elasticsearch einiges an Komplexität weg, sodass mit Einstellungen im Auslieferungszustand sehr schnell Informationen durchsuchbar gemacht werden können. Elasticsearch hatte zu Beginn allerdings einen Nachteil: Man kann die Informationen nicht auf einen Schlag sichtbar machen. Da man Transaktionen getrennt von einander speichern möchte, kann man bei z.B. 10.000 Transaktionen innerhalb einer Datei nicht erst alle Transaktionen für eine Suche sichtbar machen, wenn die 10.000. Transaktion indiziert wurde. Die suchende Applikation muss mit diesem Umstand umgehen können. Deshalb haben wir zunächst Apache Lucene direkt verwendet, da man dort einen commit-Mechanismus hat, der das Beschriebene bietet. Allerdings haben wir dazu für die gesamte Datenmenge einen einzelnen Index verwendet. Das hat die Anwendung so sehr verlangsamt, dass wir Gefahr liefen, einen Tag mit etwa 10 Millionen Transaktionen nicht innerhalb von 24 Stunden verarbeiten zu können. Da wir bisher maximal die Menge der letzten 8 Wochen vorhalten müssen, machte es für uns Sinn, die Transaktionen in mehreren Indizes zu unterteilen. Da sich außerdem die Indizes der vergangenen Tage nicht verändern, sondern nur der aktuelle Tag, ist ein Tag die beste Größe für einen Index aus unserer Sicht.
Dafür bringt Elasticsearch einiges mit. Denn eigentlich ist es für den Aufbau eines Clusters, also Verteilung auf mehrere Server-Instanzen, konzipiert, um die Last zu verteilen. Mit Hilfe von Index-Aliasen lassen sich dann mehrere Indizes durch nur einen Namen ansprechen. Jede Abfrage wird ja zu einem bestimmten Zeitpunkt ausgeführt. Da wird der Datumsteil entnommen und der entsprechende Alias draus erzeugt. Anschließend wird abgefragt, ob es den Index gibt. Ist dies nicht der Fall, wird für den vorherigen Tag das gleiche Vorgehen ausgeführt, solange bis ein Index gefunden wird oder eine andere Abbruchbedingung greift. Damit nicht bei jeder Abfrage überprüft werden muss, ob es den Index gibt, sollte man natürlich den aktuellen Alias cachen, wenn man ihn bereits geprüft hat.
Der Entwickler bekommt also einiges an die Hand, um ein solches Konstrukt aufzubauen. Nur den Commit-Mechanismus verliert man mit Elasticsearch. Wie man diesen soweit wie möglich nachbilden kann, beschreibt Patrick Peschlow unter Transactions in Elasticsearch.
Zu den Informationen, nach denen wir suchen wollen, werden die notwendigen Informationen für die Prozesse abgespeichert. Das ist unter anderem auch der Dateiname und die Positionen der maximal drei Ebenen einer Datei (Datei-, Gruppe- und Transaktionsebene) innerhalb der Datei. Mit Hilfe dieser Informationen können zu jeder in der Recherche vorliegenden Transaktion die drei Ebenen einer Transaktion als XML-Zeichenkette ermittelt werden. Mit Hilfe dieser Zeichenkette von Original-Transaktionen (pacs.003 (Lastschrift) und pacs.008 (Gutschrift)) lassen sich dann automatisch R-Transaktionen mit Hilfe eines entsprechenden Konverters erzeugen. Dies lässt sich z.B. nutzen, um Validation-Files von anderen Clearing-Häusern automatisch zu verarbeiten. Auch eine Maske mit den bereits vorerfassten Daten einer Original-Transaktion lässt sich so umsetzen. Es sind viele Möglichkeiten denkbar.
Mit dem beschriebenen Konstrukt ist es möglich, über eine Milliarde Dokumente schnell zu durchsuchen; ohne große Wartezeit selbst an Tagen mit über 40 Mio. Transaktionen. Die größte Hürde stellt bisher noch die Bereitstellung der Daten dar: Innerhalb kürzester Zeit sollen mehrere hundert Megabyte-große Dateien durchsuchbar sein. Dies lässt sich nur durch parallele Verarbeitung lösen. Bisher ist diese leider nicht effizient genug, da mehrere große Dateien auch mal einen Prozess verstopfen können, während alle anderen Prozesse auf Dateien warten. Dies ist aber unbestritten der Art der Bereitstellung geschuldet: Die Dateien kommen in einem Verzeichnis an und werden dann von einem Prozess auf verschiedene Unterverzeichnisse verteilt. Für jedes Unterverzeichnis gibt es dann einen eigenen Prozess, der die Dateien verarbeitet. Leider ist die Verteilung nicht “schlau” genug, um zu erkennen, ob in dem Unterverzeichnis nicht bereits mehrere große Dateien liegen. Wenn diese Parallelisierung verbessert werden könnte, wäre die Echtzeit-Suche nicht mehr weit entfernt, um die automatischen Massenzahlungsverkehrsprozesse noch weiter zu verbessern.


Alte Einträge sind verfügbar im Archiv.