Posts mit dem Label Bad Code werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Bad Code werden angezeigt. Alle Posts anzeigen

Samstag, 25. Juli 2020

Default Values

Um Default Values gibt es immer wieder Diskussion unter Softwareentwicklern und oft sieht man das es scheinbar nicht ausreichend darüber nachgedacht wurde. Bezüglich der Default Values haben sich folgende zwei Regeln bewährt:
  1. Ein guter Name, der keinen Interpretationsspielraum lässt.
  2. Less Surprising Value
Hier ein Beispiel, in Kafka  gibt es ein  Replaction-Factor=1 der dazu benutzt wird die Replikation der Kafka Topics zu konfigurieren um so eine robuste Umgebung zu erhalten.

Was ist daran nun sub-optimal?
  1. Schnellen Programmierern werden leicht übersehen das es sich um den Faktor und nicht die Anzahl der Replikas handelt. So könnte man annehmen das es mindesten ein Replika gibt. Diese Annahme trügt, beim Wert 1 gibt keine Topic Replikation, weil 1 * 1 = 1 ist . Besser wäre wenn das Property nicht Replica-Factor heissen würde sondern Replica-Count. Der Softwareentwickler muss nicht die Hürde der Multiplikation überwinden. Je weniger mentale Barrieren, desto besser.
  2. Der Wert ist 1, das klingt erstmal gut. Trotzdem würde ich erwarten, das wenn man Kafka einsetzt, das die Replikation aktiv ist und das ist hier nicht der Fall. Besser wäre also hier der Wert 2 als Default Value.

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.

Montag, 12. Juni 2017

Bad Code: Multiple Exit Point Problem

Lange war mir nicht klar warum multiple Exit Points ein Problem sein sollen. Sei sind eine einfache Möglichkeit schlanken und einfachen Code zu schreiben. Bis jetzt.

Ich muss gerade bestehenden Code für Monitoring instrumentalisieren, das mache ich auf sehr einfache und verständliche Art mittels System.currentTimeMillis().  Das Hauptproblem sind multiple Exit Points:

  1. Exit Points können übersehen werden. Das passiert bei langen Methoden manchmal nicht sehr schnell. 
  2. Das Code auf Try Blöcken entfernt werden (Premature Optimization) und ich Code umkopieren muss um die Logik zu erhalten. Oder anders ausgedrückt: Code der eigentlich zum Try gehört aber sich nicht im Try Block befindet. Er steht nach dem letzten Catch, welche return Anweisungen enthalten. Dieser Code muss wieder in den Try Block eingefügt werden.


Fazit:

  1. Multiple Exit Points sind keine gut Idee, 
  2. Ausser die Methode ist ein 5-Zeiler.
  3. Unit-Test sind die Basis des erfolgreichen Refactorings.



Dienstag, 12. April 2016

Keep Simple Things Simple

Einige Skriptsprache bieten das Feature, dass der letzte Wert einer Methode der Returnwert dieser Methode ist. Man muss ihn also nicht explizite zurückgeben. Das ist ein durchaus hilfreiches Feature, was den zu schreibenden Code reduziert. In der Regel ist Convention zutreffend und damit hilfreich. Leider kann man diese Hilfe auch zu seltsamen Code führen. Hier ein R Beispiel.

Hier wird die Variable visitData explizit noch einmal aufgeführt damit sie von der Methode zurückgeben wird. Und dazu kommt noch der Kommentar der dieses Verhalten beschreibt. Besser wäre hier die konventionelle Schreibweise mit explizitem Return. Sie ist besser zu verstehen und kürzer.

Freitag, 26. Juni 2015

Robust Code: Security Counter and Endless Loop

Eines der typischen Probleme bei der Entwicklung von Code sind Endlos-Schleifen. Von Ausnahmen mal abgesehen sind Endlos-Schleifen in der Regel nicht erwünscht. Leider entstehen sie durch scheinbar einfachen Code, der scheinbar korrekt ist. Hier ein Beispiel, von der Initialisierung eines Objektes, das selbst ein externes Subsystem (ZAP) initialisiert und dem entsprechend darauf wartet:

private void waitForStart() {
    while(!this.isZapDaemonUp() ) {
  sleep(1000);
        }
}

Das Problem an dieser Schleife ist, dass wenn das Subsystem nicht startet, dann hängt das eigentliche Programm in einer Endlosschleife. Der Benutzer kann das nicht erkennen. Eine robuste Lösung besteht darin einen Sicherheit-Counter einzuführen, der nach er gewissen Menge an Versuchen den Code abbricht.

private void waitForStart() {
     def secCounterStartup = 0;
     while(!this.isZapDaemonUp() ) {
         secCounterStartup++;
         log.debug "waiting for ZAP"
         sleep(1000);
         if (secCounterStartup > 20){
                throw new Exception("Zap does't start up.");                                           
         }
  }
  sleep(2000)
}