Donnerstag, 11. Juli 2019

Die nutzloseste Software: Terraform

Terraform ist eine Software mit der man Infrastruktur as Code definiert und dies unabhängig vom Cloud Anbieter. Soweit die Idee von Terraform.

Immer wenn ein Kollege mit einem neuen Tool, Lib, Programmiersprache um die Ecke kommt, die die endgültige Erlösung aller Softwareprobleme ist, dann frage ich: "Welches Problem löst es?"

Linus Torwalds sagt mal das Subversion das sinnloseste Softwareprojekt sei (Link). Heute hat er Unrecht, das sinnloseste Softwareprojekt ist Terraform. Warum?

Terraform löst keine Probleme, Terraform ist selbst ein Problem. 

Punkt 1: Falsche Grundannahme

Die Grundannahme das nur Terraform selbst Cloud Ressourcen verändern kann, ist falsch. Das Terraform State-Handling erinnert an die Idee aus UML automatisch Code zu erzeugen und so Projekte als reines UML Konstrukt zu realisieren. Schon diese Idee scheiterte am Code Roundtrip und so scheitet Terraform an seinen eigenen States. Heute bauen wir Stateless Mikro Services und Terraform kommt mit einem komplexen State Modell daher. Wenn sich dieses State Modell von den Cloud Ressourcen unterscheidet ist Terraform und der Entwickler am Ende. Das Reparieren dieses inkonsistenten Zustandes ist kaum sinnvoll möglich. Terraform ist nicht robust. Vor allem bräuchte Terraform kein State Modell sondern nur die Referenz auf die Cloud Ressource selbst und könnte den State selbst ermitteln. Warum tun sie das nicht? Die Benutzung von Terraform schliesst alle anderen Cloud Tools und Consolen aus.

Punkt 2: Inkompatibilität

Instabile Terraform Versionen, inkompatible Konfigurationen und Plugins. Warum sind neue Terraform Versionen inkompatibel mit alten Plugins und Konfigurationen? Warum wurde nicht auf Kompatibilität geachtet? Warum wurden hier am laufenden Meter Breaking Changes implementiert?

Punkt 3: Nutzlos, kein Zusatznutzen vorhanden

Und zum Schluss, welchen Nutzen hat Terraform. Infrastruktur as Code als Code kann man bei der AWS sehr gut über die aws-cli oder andere AWS Libs realisieren. Bei Digital Ocean kann man das per Rest Calls. Jeder Cloud Anbieter hat entsprechende Schnittstellen. Diese Schnittstellen sind in der Regel hervorragend dokumentiert. Jetzt könnte man anführen, das Terraform eine Abstraktionsschicht über all diese verschiedenen Cloud Anbieter Schnittstellen legt. Das stimmt nur zum Teil weil die Terraform Features natürlich vom Provider und dem Provider Plugin abhängen. Also auch dieses Argument stimmt nicht. Dazu die Frage, wie oft wechselst du am Tag den Cloud Provider und zwischen wie vielen Cloud Providern wechselst du? Genau, Terraform löst ein Problem das gar nicht existiert! Zusätzlich verschwendet Terrafom Zeit durch seine eigenen Probleme, siehe Punkte 1 und 2. Terraform ist nutzlos und kontraproduktiv.


Noch eine kleine Anmerkung, auch vor der AWS wurde schon Infrastruktur als Code geschrieben und betrieben, damals mit BASH, SSH, SCP , DD und dem Paketmanager.

Mittwoch, 10. Juli 2019

Jeder Incident - ein neuer Test

Bad Code sind negativ Beispiele wie man nicht programmieren sollte. Aber wie macht man es dann richtig? Die Antwort ist Good Code, eine Sammlung bewährter Software Muster:

  1. Jeder Bug wird behoben und führt zu einer Code Verbesserung die über die Bug Behebung hinausgeht oder einem neuen Test.
  2. Jeder Incident führ zu einem neuen Test.

Freitag, 21. Juni 2019

Die Evolution der Datenaustausch-Formate: Binary, CSV, XML, Properties, JSON, YAML

Es gibt eine Reihe von Datenformaten für den Datenaustausch zwischen Programmen bzw. für deren Konfiguration. Hier eine Übersicht über gängige Formate, deren Vor- und Nachteile.


BinaryCSVXMLJSONYAMLProperties
Geeignet für DatenauschJaJaJaJaJaSchlecht
Geeignet für KonfigurationNeinNeinJaJaJaJa
Verständlichkeit beim Lesen für den EntwicklerNeinGutGutSehr gutSehr gutSehr gut
SpeichereffizienzSehr gutGut bis Sehr gutSehr SchlechtSchlechtGutSchlecht
Unetrsctüzung in der BASHNeinSehr gutGutGutSchlechtSehr gut
Parser GeschwindigkeitSehrt hochHochGeringGeringGeringHoch
NachteileEingeschränkte Kompatibilität


Kein Kommentare


Vorteile

Sehr hohe VerbreitungSchema Definition



Dienstag, 18. Juni 2019

Was ist die optimale Sprint Länge in SCRUM?

Die klassische Zeitspanne eines SCRUM Sprints sind 4 Wochen. In meinen letzten Projekten wurde die Sprintdauer auf 2 Wochen genutzt. Die Idee den 2 Wochen Sprints war, durch kürze Iterationen soll das Produkt zielgenauer für den Kunden entwickelt werden. Die Idee ist gut und funktioniert auch.

Leider gibt es auch Nachteile dieser kurzen Sprints. Hier die typischen Symptome, wenn die Sprints zu kurz sind:

  1. Die Sprint Velocity springt extrem, weil 95% fertige Stories in den nächsten Sprint kommen.
  2. Auch kurze Ausfälle von Software Entwicklern sind deutliche in der Sprint Velocity zu erkennen.
  3. Dies führ aus Sicht der Project Owner zu einer schlechten Planbarkeit und Frustration.
Wenn diese Symptome wiederholt Auftreten, verlängert die Sprintdauer, Frust bei den Project Owner und beim Entwickler Team wird abgebaut und vermieden.

Die optimale Sprintlänge ist die kürzeste Zeitspanne, die euch ermöglicht eine stabile Menge an Features an den Kunden auszuliefern. Dann habt ihr die Balance zwischen Planbarkeit und zielorientiertem Arbeiten und Performance erreicht.

Der oft hervorgebracht Kritikpunkt, aber die anderen Teams arbeiten im z.B. 2 Wochen Sprint Takt, ist irrelevant, weil die Teams unabhängig arbeiten und unabhängig ihr Produkt-Increment deployen.

Vertikalisierung der Softwareentwicklung und Micro Services

Die Vertikalisierung der Softwareentwicklung ist ein erfolgreiche Modell für die Skalierung der Softwareentwicklung. Dabei betreut ein Entwicklerteam eine Kunden-Domäne und entwickelt die Software für diese Domäne autonom. Dies wird gerne durch das Share Nothing Prinzip umgesetzt. Das Entwicklerteam kann ohne Rücksicht auf andere Teams, also ohne Abstimmungsaufwand und Meeting-Marathons die Software für die Kunden-Domäne entwickeln. Dies spart Zeit und bring schnell gute Erfolge, es ist sehr effizient.

Vertikalisierung führt oft dazu, das das Team die Kunden-Domäne als einen Micro Service umsetzt. In der Praxis stösst dieses Vorgehen: eine Domäne, ein Team, ein Micro Service, recht schnell an seine Grenzen. Der Grund ist die Komplexität dieses fetten Micro Services, der verscheiden Aufgaben erfüllt. Oft kommt es zu komplexen Deployments, weil der fette Micro Service in verscheiden Funktionen deployed wird, z.B. zur Datenversorgung und Kunden-App. Aus meiner Erfahrung ist das Deployment und der Betrieb sehr komplex und führt zu zusätzlichen Fehlern. Ein Codebasis führt zu funktional unterschiedlichen Micro Services, die durch Konfiguration unterschieden werden. Diese funktional unterschiedlichen Micro Services sind nicht unabhängig von einander. Es kann zu fehlerhaften Konstellationen kommen, oft hilft nur eine gezieltes Überwachen des Betriebes diese Klasse von neuen Fehlern zu erkennen. D.h. wir haben eine neue Klasse von Runtime Fehlern, die schwerer zu erkennen sind und dazu noch sehr spä erkannt werden. Diese Fehler sind erst nach dem Deployment erkennbar. Dann ist der Service für den Kunden aber schon gestört. Oder aus einer anderen Perspektive, wenn wir die 12 Factors App Kriterien heranziehen, wäre dies ein Bruch mit dem Faktor 1!

Eine erfolgreiche Alternative ist es aus diesen fetten Micro Service in einzelne kleine, in sich geschlossene, Micro Services zu zerlegen. Zum Beispiel kann man die Datenversorgung von der Bearbeitung von Kundenrequest trennen. Oft wird als Gegenargument angeführt, das es gemeinsamen Code gäbe. In der Praxis hat sich gezeigt, das die Menge des gemeinsamen Codes sehr gering ist. Das Problem des gemeinsame Codes kann bei Bedarf über Bibliothek gelöst werden.

Zusammengefasst die Vorteile der Zerlegung von fetten Micro Services einer Vertikalen in schlanke Micros Services:

  • Vereinfachung des Deployments
  • Vereinfachte Konfigurationen
  • Keine Fehler durch Fehlkonfigurationen, die Instanzen der Applikation sind unabhängig voneinander
  • Höhere Robustheit, Fehler in einem Micro Service stört nicht die gesamte Applikation, so führt der Ausfall der Datenversorgung nicht dazu das der Kunde nicht mehr bedient wird
  • Ein negativen Performance-Einflüsse durch Daten-Imports oder Wartungsjobs.
  • Bessere Wartbarkeit, Codebasis beleibt schlank und übersichtlich

Mittwoch, 12. Juni 2019

Bad Developer

Über schlechten Code gibt es viel zu Lesen. Aber es gibt nicht nur Bad Code und Clean Code sondern auch Bad Developer. Hier eine Episode aus meinem Alltag als Softwareentwickler.


Gestern im SCRUM Planungsmeeting.

Softwareentwickler Jack: "Ich bin hier nicht um zu programmieren, ... "

Ich: ??? (fassungslos)


Im Nachhinein hatte der Entwickler Jack sogar recht, er hat innerhalb von über zwei Monaten keinen einzigen Story-Punkt abgearbeitet. Die Frage, warum bezahlt der Kunde für solche Softwareentwickler? Um die die Sache zu verschlimmern arbeitet der Entwickler keine Stories ab sondern er raubt auch noch den anderen Entwicklern die Zeit. Ein absolutes Minusgeschäft.


Hier mal als O-Ton von der Velocity, was für ein Unterschied in mentalen Einstellung.

"There are only two things your organization should be spending time on: making your customers happy, or making your people happy.". -@lizthegrey at o11y meetup. #velocityconf

Freitag, 7. Juni 2019

Datenschutz: Es dürfen keine persönlichen Daten geloggt werden.

Ein Hauptquelle für das Exponieren von persönlichen Daten ist das Logging. Programmierer loggen einfach Objekt zu Debug-Zwecken oder in Fehlerfall. Diese Daten landen in Log-Dateien oder im ELK Stack. Dort gehören sie nicht hin.

Hier ein Weg dies zu verhindern. Für das Logging wird in der der Regel die toString() Methode in Java benutzt. Diese muss man bei allen Klassen deren Objekte persönlich Daten enthalten überschreiben. Hier ein Beispiel:

    @Override
    public String toString() {
        return "DATENSCHUTZ";
    }
    

Mit diesem einfachen Overwrite der toString() Methode verhindert man das persönliche Daten geloggt werden und gleichzeitig kann man die Verwendung potentiell kritischer Aufrufe im Log finden und diese Stellen entfernen. Bei Bedarf sollte man auch die Methode asString() genauso überschreiben.