Posts mit dem Label Agile Development werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Agile Development werden angezeigt. Alle Posts anzeigen

Dienstag, 3. Januar 2023

Model Driven Architecture ist tot

 Model Driven Architecture (MDA) und alle Verwandte sind seit den fruehen 2000er tot. Trotz viel Energie, Enthusiasmus, Zeit und Geld die in MDA Projekte geflossen sind, gibt es zwei Erkenntnisse: MDA ist sicher tot und UML ist sinnvoll zur Beschreibung von Software-Konzepten.

Weil es scheinbar zu wenige Senior Software Developer gibt, gibt es Heute MDA Zombies. MDA ist von den Toten auferstanden in Form der Generierung von Klasssen aus YAML Schnittstellenbeschreibungen die dann z.B. über Micro Services geteilt werden.

Bei genauerem Hinsehen sieht man, dass dieser Ansatz auch nicht funktioniert. Er hat folgende Nachteile:

  1. Aenderungen an der Schnittstelle fuehren zu aufwendigen Abstimmungsprozessen die multiple Teams, oft das ganze Projekt, einbeziehen. Das ist sehr, sehr teuer.
  2. Kein Team ist in der Verantwortung, shared  whatever sind gut Beispiele fuer Verantwortungsdiffusion.
  3. Selbst wenn ein Team Zeit fuer die Wartung aufwenden moechte, so werden die Kommunikationskosten zur Aufgabe fuehren.
  4. Weil sich die Softwareanforderungen aendern die Schnittstelle aber in Beton gegossen ist, fangen die Entwicklerteams an der 'offizielle' Schnittstelle vorbei zu arbeiten. Sie haben gar keinen anderen Weg.

Was lernen wir daraus:

  1. MDA in allen Varianten ist teuer und ineffizient.
  2. MDA ist das Gegenteil von agiler Softwareentwicklung .
  3. Share Nothing ist und bleibt eine Grundlage fuer agile Softwareentwicklung
  4. Die Entwicklung von (shared) Bibliotheken ist deutlich anders zur Entwicklung normaler Micro Services.

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.

Samstag, 17. März 2018

Warum ich keine mehr Konfigurationsdatei brauche.

In der heutigen Softwareentwicklung, also ich meine Java, Docker und die Cloud, brauche ich keine Konfigurationsdateien mehr. Warum? Ganz einfach, eine Konfigurationsdatei ermöglicht es, das Setup von Programmen an die eigenen Bedürfnisse anzupassen und die Software neu zu starten. So machen es viele Programme wie der Apache Server oder Postgres. Hier machen Konfigurationsdateien Sinn.

Wenn ich mich im Cloud Umfeld bewege und individuelle Wegwerf-Software mit Docker erstelle und deploye, dann gibt es diesen Anwendungsfall nicht mehr, dass ich ein Konfiguration anpasse und dann die Software neu starte.

Im der Welt von Docker, Cloud und Continuoude Deployments kann ich die Konfiguration im Code ändern, ins GIT einchecken und warten bis meine Continuouse Deployment Pipeline mir nach wenigen Minuten eine neue Softwareversion ausgerollt hat. Fertig, jetzt brauch ich eine Properties oder YAML Dateien mehr. Das ist für Softwareentwickler einfacher als sich via VPN auf Hosts, und dann auf Docker Container anzumelden und Änderungen an der Konfiguration durchzuführen. In den letzen Jahren in denen ich mich in diesem Umfeld bewege ist mir dieser Fall nicht vorgekommen.

Aber, Secrets wie Access-Keys, Passwörter oder Benutzernamen gehören natürlich nicht so plain in den Code und auch nicht ins GIT. Solche geheimen Daten kann man dann ggf. in verschlüsselten Konfigurationsdateien speichern.

Mittwoch, 13. Juli 2016

Run All Test on File Change

Eines der besten Instrumente um Code zu verbessern sind Test, speziell Unit Tests. Unit Test sind für alle erdenklichen Programmiersprachen verfügbar und wenn nicht, dann schreibt man sich den Test selbst, ohne Frame Work. Mit Hilfe der Unit Test können Fehler einfach aufgedeckt werden dazu muss man nicht nur die Test haben, sondern sie auch permanent ausführen. Dieses permanente Ausführen ist die Aufgabe des Continouse Integration Servers, z.B. Jenkins. Alternativ gibt es auch die Unit Integration in die IDE. Wem selbst der Jenkins oder die IDE zu langsam ist, schnelle Roundtripzeiten bedeuten effizientes Entwickeln, der kann sich mit Hilfe eines einfachen Scripts seine Test ausführen, wenn sich etwas am Quellcode der Software oder der Test geändert hat (File save).

Hier ein Beispiel für den Mac, dass Unit Test für R ausführt und den Entwickler per Notification auf Fehler bei der Testdurchführung hinweist. Zuerst muss per Homebrew fswatch installiert werden. Dann muss dieses Script ins Root Verzeichnis deines Projektes abgelegt werden. Dann muss es starten. Es läuft ohne Unterbrechung solange, bis man via CRTL + C abbricht. Alternativ kann man das Script für andere Umgebungen anpassen.


#!/usr/bin/env bash

runX=true

finish (){
    runX=false
}
trap finish SIGINT


runTests(){
    for SCRIPT in src/test/*
    do
        if [ -f $SCRIPT -a -x $SCRIPT ]
        then
            $SCRIPT
            if [[ $? -ne 0 ]] 
            then
                FAILEDTESTS=${FAILEDTESTS}"\n"$SCRIPT
            fi
        fi                                                      
    done
    if [ ${#FAILEDTESTS} -ge 1 ]
    then
        osascript -e 'display notification  "'"$FAILEDTESTS"'" with title "R Test failed"'
        FAILEDTESTS=""
    fi
}

while $runX; do
    fswatch src/main/*.R src/test/*.R | runTests 
done



Mittwoch, 13. Januar 2016

Nerd Recruiting

Very sharp recruiting form OTTO E-Commerce Shop, from the IT City of Hamburg.


Donnerstag, 8. Oktober 2015

Avoid double software development? No!

In the many cases of software development like this, double work is a better opportunity. Reasons there for:

1)
If you try to avoid double work, you have to spend significant time to collect the requirements and to coordinate the work. You don’t reduce the time you need to develop a working software solution. Let me illustrate that, if you speak every week with 8 people for 1,5h for four weeks, then you have spend 60h of working time plus one week for software development, makes total 100h. If two developers build two solution, you spend only two weeks, total 80h. One additional reason, too much and too less communication frustrates developers easily.

2)
If you develop two proper working solutions, you can decide for better solution. This means, if you has developed only one solution, your chance is 50% to have the worst solution. If you select one solution from two, you chance is 100% to have not the worst solution.

My advise is in the first develop round, every team are allowed to develop his own solution. This mean share nothing. In the next round,  the development teams can decide to switch to one solution, to the better one or to decide to develop an better third solution with the experiences of booth early versions.

Samstag, 28. Dezember 2013

Make it run, make it right, make it fast.

Drei Grundsätze der Programmierung: "Make it run, make it right, make it fast.". Wichtig ist, dass sich hierbei um ein Periodisierung geht. D.h. zuerst muss das Programm laufen, erst wenn es läuft, mache es schön, dass es deinen eigenen Ansprüchen genügt und dann erst, zu aller letzt, mache es schnell.

Sonntag, 28. Oktober 2012

Grails Maven Integration

Es gibt verschieden Wege Grails in Maven zu integrieren, z.B. um den Nexus zu benutzen. Da wäre das Grails Plugin Maven Publisher (Link). Dieses ist für Grails 1.X geeignet, wird aber nicht mehr unterstützt. Damit fällt es aus. Ersetzt wurde das Grails Plugin Maven Publisher durch das Release Plugin (Link), welches für Grails 2.X verfügbar ist. Das funktioniert bei aktuellen Grails Projekten, leider wird das Passwort für den Nexus innerhalb des Projektes gespeichert (grails-app/conf/BuildConfig.groovy), das ist überhaupt nicht groovy, das ist fahrlässig. Damit fällt auch diese Lösung aus. Dritter Versuch, erstellen einer POM Datei aus Grails heraus. Das funktioniert nur leider kompiliert dann nichts mehr, unter Java 7 auf dem Mac (siehe Fehlerausgabe unten). Dies ist ein bekannter Bug (Link).

Fazit, drei Möglichkeiten, kein Treffer. Was macht eigentlich Ant?





[ERROR] Unresolveable build extension: Plugin org.grails:grails-maven-plugin:2.1.0 or one of its dependencies could not be resolved: Could not find artifact com.sun:tools:jar:1.6 at specified path /Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk/Contents/Home/jre/bundle/Classes/classes.jar @
[ERROR] Unknown packaging: grails-app @ line 8, column 16

at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:339)
at org.apache.maven.DefaultMaven.collectProjects(DefaultMaven.java:632)
at org.apache.maven.DefaultMaven.getProjectsForMavenReactor(DefaultMaven.java:581)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:233)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
[ERROR]  
[ERROR]   The project com.futuretv.userprofiledatasource:UserProfileDatasource:0.1 (/Users/mirkoebert/Documents/workspace-sts-2.9.0.RELEASE/UserProfileDatasource/pom.xml) has 2 errors
[ERROR]     Unresolveable build extension: Plugin org.grails:grails-maven-plugin:2.1.0 or one of its dependencies could not be resolved: Could not find artifact com.sun:tools:jar:1.6 at specified path /Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk/Contents/Home/jre/bundle/Classes/classes.jar -> [Help 2]
org.apache.maven.plugin.PluginResolutionException: Plugin org.grails:grails-maven-plugin:2.1.0 or one of its dependencies could not be resolved: Could not find artifact com.sun:tools:jar:1.6 at specified path /Library/Java/JavaVirtualMachines/jdk1.7.0_06.jdk/Contents/Home/jre/bundle/Classes/classes.jar
at org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver.resolve(DefaultPluginDependenciesResolver.java:215)
at org.apache.maven.project.DefaultProjectBuildingHelper.resolveExtensionArtifacts(DefaultProjectBuildingHelper.java:377)
at org.apache.maven.project.DefaultProjectBuildingHelper.createProjectRealm(DefaultProjectBuildingHelper.java:237)

Mittwoch, 24. Oktober 2012

Indikatoren fürs Refactoring

Refactoring ist in der Agilen Welt ein immer währender, fortlaufender Vorgang. Trotzdem gibt es in vielen Projekten Phasen des Refactorings. Woran erkennt man, das Refactoring dringend angeraten wird:
  • Zu viele globale Variablen
  • Der Programmierer sagt: "Die Methode kann ich nicht testen."
  • Das Projekt verwendet veraltete Bibliotheken oder Plugins
  • Hidden Features, niemand weiss von diesem Feature
  • Nicht benutzte Features
  • Es gibt Integrationstest an Stelle von Unit-Tests
  • Vererbung und Abstrakte Klassen (in den meisten Anwendungsfällen)
  • Verstoss gegen Clean Code wie:
    • Code Duplikate, Verstoß gegen die DRY Regel
    • Case Anweisungen mit den Werten 1, 2, 3 ... (Java)
    • Eval Anweisungen in JS
  • Methoden mit Boolean Parametern
  • Zu lange Klassen oder Methoden
  • Methoden mit drei oder mehr Parametern
  • Methoden mit Parametern die als Ausgabe die dienen

Die Liste ist nicht vollständig, bitte gebt mir Feedback zur Erweiterung der Liste.

Samstag, 22. Oktober 2011

Clean Code 2

Ich hatte schonen einen Post zu Thema Clean Code geschrieben, da wurde ich auf das Buch Clean Code von Robert C. Martin hingewiesen. Er beschreibt dort keine Techniken sondern eher Prinzipien, also mehr wie man Code schreibt. Immer wenn ich mit Programmierern über das Thema sprach, ergaben sich lebhafte Diskussionen über einzelne Prinzipien. In meiner Arbeit sind mir viele der Dinge im Buch begegnet. Klassen mit generischen Namen wie Statistik. Jeder mit dem ich sprach kennt eigene Episoden, die man auch in dieses Buches wiederfindet. An der ein oder anderen  Stelle an wird sich jeder Softwareentwickler wieder erkennen. So ist es hervorragend für Diskussionen unter Kollegen oder im Team geeignet. Schön an dem Buch ist, das man es auch quer lesen kann und wenn man genug Zeit hat auch sich die umfangreichen Codebeispiele ansehen. Es ist eines der wenigen Bücher bei denen ich dies wirklich getan habe. Dafür wird man dann aber auch meist mit einer neuen Einsicht belohnt.


Es ist aus meiner Sicht ein wichtiges Buch für alle Programmierer und unbedingt jedem zu empfehlen. Ich kann neben der englischen auch die deutsche Version empfehlen. Beide Versionen sind gelungen.

Freitag, 27. Mai 2011

Continuous Integration: Hudson

Brown Field Projekte sind oft in einem schlechten Zustand, oft wissen die Beteiligten gar nicht wie es um ein Projekt steht, oft haben sie nur eine Ahnung oder ein Gefühl. Um Brown Field Projekte unter Kontrolle zu bringen und Wartbarkeit, Qualität und Sicherheit zu erhöhen wird bei Brown Field Projekten als eine der ersten Massnahmen Continuous Integration (CI) etabliert. Zurzeit sind eine Reihe von CI-Systemen verfügbar. Dazu zählen die populären Systeme:
Alle drei Systeme eignen sich für Java-Projekte, sind aber offen und flexibel auch andere Programmiersprachen zu unterstützen. Der prinzipille Ablauf ist folgender:
  • Auschecken des Projektes aus der Codeverwaltung (CVS, SVN)
  • Build des Projektes (Maven, ANT)
  • Benachrichtung von Benutzern über das Ergebnis (Email)
In den Klammern hinter den Schritten stehen die populärsten Vertreter für diese Schritte. Sie werden in der Regel von allen CI-Systemen unterstützt. Oft unterstützen die CI-Systeme auch noch andere Systeme.

Continuum 1.3.7
Auf meinem Testrechner lief ein aktuelles Windows 7. Continuum ist sowohl aus Webapp für Tomcat als auch als Standalone-Version verfügbar. Letztere probierte ich zu installieren und zu benutzen. Leider liess sich Continuum nicht starten und eine Beschreibung war nicht zu finden. Das ist das AUS für Contiunuum. Continuum macht sonst den Eindruck sehr stark auf Maven zu fokussieren, also ist Continuum ein Tipp für alle Maven Benutzer.


Hudson 2.0
Auf meinem virtuelle Testrechner lief ein Fedora 14 Linux. Zusätzlich habe ich JAVA, ANT und Maven2 installiert. Leider ist keiner der CI-Systeme per YUM zu installieren. Schade, doch Hudson lies sich einfach von der Website über einen Link aus installieren. Das funktionierte sehr gut. Auch bei Hudson entschied ich mich für die Standalone-Variante. Nach der Installation lief Hudson schon als Demon, nur leider funktionierte Hudson nicht ganz, die Weboberfläche (http://localhost:8080) war da, liess sich aber nicht benutzen. Nach einem manuellen Start von Hudson als Root funktionierte alles.
/etc/init.d/hudson stop
java -jar /usr/lib/hudson/hudson.war
Strg+C
/etc/init.d/hudson start
Ich konnte Jobs einrichten und abarbeiten. Für den Zugriff aus CVS musst ich das Passwort und den Benutzernamen in Feld CVSROOT eingeben. Je nach dem wer (Root oder User) und wie (Demon oder Terminal) Hudson gestartet wird legt Hudson eine Verzeichnisstruktur an verschieden Orten auf dem Volume an. Also nicht erschrecken, wenn ihr Hudson als User startet und nicht die Jobs seht, die ihr vorhin angelegt habt, wahrscheinlich lief Hudsun da als Demon, also Huson beenden und als Demon neu starten. Dann ist alles wieder OK.
Zur CVS Integration kann Hudson auch die Datei .cvspass benutzen, das funktioniert aber nur eingeschränkt. So kann Hudson als Demon gestartet trotz richtiger Dateirechte nicht auf die .cvspass eines Benutzers zugreifen.
Ein schönes Feature ist auch die Möglichkeit von Hudson Programme wie ANT oder Maven selbständig aus dem Internet zu laden und sogar in verschiedenen Versionen dem Benutzer anzubieten. Auch wenn Fedora über ein aktuelles ANT verfügt ist es trotzdem zu empfehlen, das ANT via Hudson zu installieren, die erhöht die Konsistenz in der Softwareentwicklung und elemeniert ein potentielle Fehlerquelle, unterschiedliche ANT oder Maven Versionen.
Trotz dieser Hürden schien Hudson gut zu funktionieren, bis ich versuchte die Plugins zu aktualisieren. Dabei wurde meine Hudson Installation so beschädigt, dass Hudson nicht mehr zum Arbeiten zu überreden war. Schade.
Trotz dieser hidden Features ist Hudson zu empfehlen.

Samstag, 14. Mai 2011

Codeoptimierung: Wurzel allen Übels

Das erste mit dem Softwareentwickler in Projekten anfangen, ist die Optimierung ihres Codes. Wahrscheinlich dient dies als Beweis ihres Könnens. Klar, Optimierungen sind sind immer ein Fall für erfahrenen Entwickler. Aus diesem Grund ist dieses Streben nach optimiertem Code von Beginn an verständlich. Nur was nützt schneller (dazu kommen wir in einem andern Post) Code der schnell Fehler produziert aber nicht die gewünschte Funktion? Durch die aufwendige Fehlersuche und Fehlerbehebung kostet das oben beschriebene Vorgehen mehr Entwicklungszeit im Vergleich zum normalen Entwickeln. Was lernen wir daraus, Optimierungen sind prima, wenn man sie nicht macht.

The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson

Aus agiler Entwicklungssicht sind Optimierungen erst notwendig, wenn sie notwendig sind. Optimierungen sind Teil des Refactoringprozesses in der agilen Softwareentwicklung. Wichtiger ist die Verständlichkeit und die Wartbarkeit des Codes. Aber zurück zur Optimierung, der erste Schritt bei der Optimierung ist es, festzustellen das es ein Problem gibt, dass durch Optimierung gelöst werden kann, der zweite Schritt ist es das entsprechende Verhalten der Software zu dokumentieren und ein Testset aufzubauen mit dem die Ergebnisse nachvollziehbar sind. Im dritten Schritt wird das Problem analysiert (Profiling) und die beste Stelle (Bottleneck) zur Optimierung gefunden. Erst im vierten Schritt wird der Code optimiert. Dann wird der Effekt der Optimierung mittels des Testsets dokumentiert (fünfter Schritt). Die Optimierung von Code besteht aus folgenden Schritten:

  1. Feststellen und Dokumentieren das es ein Problem gibt.
  2. Definieren eines Testsets und Dokumentieren der Ergebnisse für den nichtoptimierten Code.
  3. Analyse des Problems z.B. mittels Profilings und finden der Codestelle für die Optimierung.
  4. Optimieren des Codes.
  5. Dokumentation der Ergebnisse des optimierten Codes mit Hilfe des Testsets.

Und eins sollte man nie vergessen, die Entwicklungszeit die in eine Optimierung fliesst, muss durch den Optimierungsgewinn gerechtfertigt sein.