Freitag, 24. April 2020

Digitale Zeichnungen

Kurz nach dem Erscheinen des ersten iPad habe wieder angefangen zu Zeichnen, diesmal digital, mit einer genialen kleine App namens Adobe Ideas.

Hier ist eine Auswahl der Bilder, die dabei entstanden sind.

Dark Beauty


Friends on Ibiza

Manuel Neuer

Pink Lady

Posing Lady
My Son Nick

Lady with Necklace

Girl with Earmuffs

Crouching Lady

My Friend Boris the Photographer

Mittwoch, 25. Juni 2014

Test Driven Development - Some Practical Insights

Für mich wirken Softwareprojekte, in denen nicht testgetrieben entwickelt wird, wie Artefakte aus der Steinzeit. Erinnert ihr euch an die Zeit, in der es noch keine Gurtpflicht im Auto gab? Kaum zu glauben, oder? Ich fühle mich ohne TDD etwa genauso wie heute ohne angelegten Gurt.


Am Dienstag, den 24. Juni 2014, durfte ich einen Vortrag über meine Erfahrungen mit Test Driven Development (TDD) halten. Summa-Summarum habe ich dort eine Lanze für TDD gebrochen.
 
Meine Kernbehauptung war, dass TTD die "Silver Bullet" des Softwareengineering sein kann, sofern man richtig "zielen" kann und die passenden "Waffen" einsetzt. Man sollte verstehen, wie TDD funktioniert und mit welchen Mitteln das am besten geht.
Wenn's euch interessiert, hier sind die Folien.

https://www.dropbox.com/s/k1tlskfq3tvfkr2/TDD-final.pdf

Interessant fand ich auch, dass von zwanzig Teilnehmern grade mal zwei an ihrem Arbeitsplatz TDD einsetzen. Immerhin gibt es das Thema schon einige Zeit (aber ihr werdet kaum glauben, wie alt TDD ist). Wäre interessant mal zu untersuchen, woran das liegt. Vielleicht sind die Gründe ähnlich den unsrigen - wir wussten einfach nicht, wie man TDD richtig macht. Oder es liegt vielleicht daran, dass die Entscheider keinen Mehrwert erkennen können. Naja, wer das Problem hat, kann sich ja mal meine Folien ansehen, da ist der Mehrwert wohl kaum zu übersehen.



 
Der Vortrag hat im Rahmen des Arbeitskreises "Software Engineering Live" der GI/GChACM-Regionalgruppe München stattgefunden. Hier ist der Teaser dazu:

Thema: Praxiserfahrungen mit Test Driven Development
Referent: Michael Karneim, Sanacorp GmbH 

In diesem Vortrag erzählt der Softwarearchitekt Michael Karneim von der Einführung von Test Driven Development (TDD) bei einem Pharmagroßhandelsunternehmen. Er berichtet von den Erkenntnissen, die er während dieses Projekts gewonnen hat. Er gibt einen Überblick über die Techniken, die seiner Meinung nach essentiell für die erfolgreiche Einführung sind: Gute Testframeworks, Akzeptanztests, Test-DSLs, Test-Data-Factories, Backdoors und Continuous Integration. Er hat die Erfahrung gemacht, dass deren Einsatzaufwand sich schon in der Anfangsphase eines Projekts amortisieren kann. Insbesondere spricht er von den Auswirkungen, die TDD auf die Entwicklungsgeschwindigkeit, die Softwarearchitektur und Aspekte der Softwarequalität jenseits der Korrektheit hat. Seines Erachtens kann der positive Einfluss von TDD gar nicht hoch genug bewertet werden. Dennoch ist TDD keine Silver Bullet. Der Erfolg in einem Projekt ist neben der Auswahl der richtigen Techniken insbesondere davon abhängig, dass das Team diesen Ansatz verinnerlicht hat und sein Hauptaugenmerk nicht mehr allein auf den Code, sondern zu einem wesentlichen Teil auf die Tests legt.

Freitag, 27. September 2013

Video zum Beanfabrics-Vortrag

Im Juni 2013 hatte ich das Vergnügen einen kleinen Vortrag vor den Mitarbeitern der TNG halten zu dürfen. Das Thema war Beanfabrics, ein Software-Projekt, dass ich seit 1999 voran treibe. Freundlicherweise hat Gerhard Müller mir gestattet, einen Link auf das Video zu veröffentlichen.


Hier ist noch ein Link auf die Vortragsfolien.

Sonntag, 21. April 2013

Zahlenspiel für Erstklässler

Schnell Rechnen können ist, wie vieles, eine Frage der Übung. Wer oft rechnet, der kann es in der Regel auch besser. Mit dem folgenden Spiel können Kinder (und Erwachsene) spielerisch das Kopfrechnen üben. Mit wenig Aufwand kann jeder das Spiel selbst zusammen bauen.

Je nach bereits vorhandenen Fertigkeiten könnt ihr den Schwierigkeitsgrad anheben. In der Basisvariante beschränkt ihr euch auf das Addieren und Subtrahieren mit natürlichen Zahlen. Später könnt ihr Multiplizieren und Dividieren hinzunehmen.

Aufbau

Das Spiel besteht aus einem Stapel beklebter Karteikarten, den sogenannten Ziffernkarten, und einem Haufen Plastikchips. Die Ziffernkarten tragen Ziffern von 0 bis 9 und werden zum Stellen der Aufgabe und für deren Lösung verwendet. Jede Ziffernkarte gibt es mehrfach im Kartenstapel. Die Chips stellen die Punkte dar, mit denen die Spieler belohnt werden.


Das folgende Bild zeigt exemplarisch, wie sich das Spiel für zwei Spieler präsentiert.

Jeder Spieler (links und rechts) erhält 3 Karten vom Stapel (oben Mitte). Eine Karte wird vom Stapel gezogen und daneben aufgedeckt (Mitte). Die Chips werden zwischen die Spieler auf den Tisch geschüttet.

Spielregeln

Wann ist das Spiel zu Ende?

Das Spiel ist zu Ende, wenn alle Punkte verteilt sind. Die Punkte bestehen aus einem abgezählten Haufen kreisrunder, bunter Plasikchips. Je nach gewünschter Spieldauer und Anzahl der Mitspieler sollte die Zahl der Chips angepasst werden. Wir verwenden etwa 10 bis 20 Chips pro Spieler.

Welcher Spieler hat am Ende gewonnen?

Der Spieler mit den meisten Punkten hat gewonnen. Haben mehrere Spieler die gleiche Punktzahl, so haben sie gemeinsam gewonnen.

Wann bekommt ein Spieler einen Punkt?

Der Spieler bekommt einen Punkt, wenn er eine Aufgabe erfolgreich gelöst hat.

Wann darf ein Spieler eine Aufgabe lösen?

Der Spieler darf die aktuelle Aufgabe lösen, wenn er an der Reihe ist.

Wann ist ein Spieler an der Reihe?

Die Spieler sind abwechselnd an der Reihe. Der jüngste Spieler beginnt. Wenn ein Spieler an die Reihe kommt, dann zieht er eine neue Karte vom Stapel und fügt sie seinen Karten hinzu.

Wie und wann wird die aktuelle Aufgabe bestimmt?

Die aktuelle Aufgabe wird durch eine Ziffernkarte bestimmt, die vom Stapel gezogen und auf den Tisch gelegt wird. Dies geschieht am Anfang des Spiels, sowie nach der Lösung einer Aufgabe. Ist eine Aufgabe gelöst, wird die Karte entfernt und auf einem Ablagestapel abgelegt.

Was genau ist der Inhalt der Aufgabe?

Die Aufgabe wird durch die Ziffernkarte neben dem Stapel festgelegt. Deren Ziffer bestimmt den Zielwert, der zu errechnen ist. Die Aufgabe besteht darin, durch Addition, Subtraktion, Multiplikation, Division, sowie einer beliebigen Kombination dieser Operationen, den Zielwert zu erreichen. Dazu muss der Spieler mindestens zwei seiner eigenen Ziffernkarten verwenden.

Was passiert, wenn ein Spieler die Aufgabe nicht lösen kann?

Wenn der Spieler die aktuelle Aufgabe nicht lösen kann, dann passt er an den nächsten Spieler weiter.


Sonntag, 2. Dezember 2012

Runtime Generic Type Resolution for Java

Bekanntlich stehen in Java die meisten generische Typinformationen zur Laufzeit nicht zur Verfügung. Insbesondere können sie nicht mittels Reflection ausgelesen werden. Doch stimmt diese Aussage unter allen Umständen?

Das Verfahren, bei dem die Typinformationen gelöscht werden, heisst Type Erasure. Damit soll das sogenannte "Generic Legacy Problem" gelöst werden.

Aus Gründen der Rückwärtskompatibilität mit altem Code, hat man sich damals entschieden, beim Kompiliervorgang die Generics weitgehend zu löschen oder in andere Konstrukte zu transformieren. Im Detail löscht der Kompiler die Typparameter, ersetzt die Typrariablen durch ihren Grenztyp, fügt Typecasts hinzu, und erweitert Klassen um sogenannte Brückenmethoden, damit das Overriding auch weiterhin funktioniert.

Folglich kann zur Laufzeit nicht herausgefunden werden, welchen Typ die unten stehende Liste "myList" hat:

public class Scribble { 

    public static void main(String[] args) {
        List<String> myList = new ArrayList<String>();

        Class elementType = getElementTypeOf(myList);
        System.out.println(elementType);
    }

    /**
    * Returns the generic element type of the given list.
    */
    public static Class getElementTypeOf(List list) {
        // This is not possible in Java !?!
    }
}

Für das obige Beispiel ist das tatsächlich unmöglich. Allerdings ist das nicht die ganze Wahrheit. Wenn wir den Code etwas abwandeln, dann lässt sich die Typinformation auslesen:

public class Scribble { 

    static List<String> myList = new ArrayList<String>();

    public static void main(String[] args) {
        Class elementType = getElementTypeOf("myList");
        System.out.println(elementType);
    }

    /**
    * Returns the generic element type of the field with the given name
    */
    public static Class getElementTypeOf(String fieldname) {
        return new GenericType(Scribble.class)
                   .getFieldType( fieldname)
                   .getTypeParameter(List.class.getTypeParameters()[0])
                   .asClass();
    }
}

Das liegt daran, dass die Variable "myList" nun als Member der Klasse deklariert ist, d.h. mit vollständigen Metainformationen im Classfile abgelegt wird.

Die Klasse "GenericType" kapselt die Suche nach dem Wert des Typparameters, welche mit Hilfe der etwas umständlichen Reflection API realisiert ist. Sie ist Teil des gleichnamigen Github-Projekt GenericType.

Dienstag, 1. November 2011

Ein Codegenerator für POJO-Builders


Seit Ende September beschäftige ich mich auf Github mit einem Open-Source-Projekt mit dem Namen PojoBuilder.

Ich entwickle dort einen Java-Codegenerator, der für ein beliebiges POJO einen passenden Pojo-Builder erzeugen kann. Dieser bietet die folgende Funktionalitäten:

  • ein "fluent interface" zum Festlegen der Eigenschaftswerte des POJOs
  • und eine build-Methode für die Erstellung einer neuen POJO Instanz mit diesen Werten
Unter anderem eignet sich so ein Builder besonders für die Erstellung von Testdaten im Rahmen von automatisierten Tests, wie das Nat Pryce anschaulich beschrieben hat.

Ein kleines Beispiel

Der Codegenerator lässt sich naheliegenderweise am einfachsten anhand eines Code-Beispiels erläutern. Nehmen wir an, wir haben die folgende Javaklasse erstellt und benötigen dafür einen Builder.
public class Contact { 
    private final String name;
    private String email;

    public Contact(String aName) {
        this.name = aName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }
}

Der dazugehörige Builder sollte beispielsweise auf die folgende Weise bedient werden können:

Contact james = new ContactBuilder()
    .withName("James Bond")
    .withEmail("007@secretservice.org")
    .build();

Mit dem Einsatz von PojoBuilder lässt sich dieses Ziel durch die Markierung der Klasse mit zwei Annotations erreichen.

@GeneratePojoBuilder(intoPackage = "samples.builder")
public class Contact { 
    private final String name;
    private String email;

    @ConstructorProperties({ "name"})
    public Contact(String aName) {
        this.name = aName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }
}

Mit @GeneratePojoBuilder wird der Codegenerator angewiesen, für die annotierte Klasse einen Builder zu generieren. Das Attribut intoPackage ist optional und bestimmt das Java-Package, in das der Builder generiert werden soll. Mit @ConstructorProperties legt man fest, welcher Konstruktor verwendet werden soll und wie die Parameter auf Properties abgebildet werden.

Der generierte Builder sieht dann so aus (Kommentare habe ich entfernt):

public class ContactBuilder implements Cloneable {

   protected String value$email$java$lang$String; 
   protected boolean isSet$email$java$lang$String = false; 

   protected String value$name$java$lang$String; 
   protected boolean isSet$name$java$lang$String = false; 

   public ContactBuilder() {
   }

   public ContactBuilder withEmail( String value) {
      this.value$email$java$lang$String = value;
      this.isSet$email$java$lang$String = true;
      return this;
   }

   public ContactBuilder withName( String value) {
      this.value$name$java$lang$String = value;
      this.isSet$name$java$lang$String = true;
      return this;
   }

   public Object clone() {
      try {
            ContactBuilder result = (ContactBuilder)super.clone();
            return result;
      } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
      }        
   }
   
   public ContactBuilder but() {
      return (ContactBuilder)clone();
   }

   public Contact build() {
      Contact result = new Contact( this.value$name$java$lang$String );
      if ( this.isSet$email$java$lang$String) {    
           result.setEmail( this.value$email$java$lang$String);  
      }
      return result;
   }
}

Wie ist das ganze nun implementiert?

Für die eigentliche Codegenerierung nutze ich, wie schon in früheren Projekten, die Stringtemplate Engine. Offen war ursprünglich lediglich die Frage, wie der Generator angestoßen werden sollte. Ich wollte erreichen, dass er sowohl in einem Build-Lauf als auch in einer IDE genutzt werden kann. Da sie sich für beides sehr gut eignet, habe ich mich für die Annotation Processor API entschieden, die seit Java 5 verfügbar ist. Somit war auch festgelegt, dass der Generator über Annotations gesteuert wird (und nicht etwa über XML oder eine andere Beschreibungssprache).

Automatisierte Tests

Eine Schwierigkeit im Projekt ist allerdings die Frage, wie man einen Annotation-Processor ordentlich testet, und zwar im Rahmen von Acceptance-Tests sowie Unit-Tests (ja, ich gebe zu, die Tests nicht vorher geschrieben zu haben). Bislang meine ich immerhin einen guten Weg für die Acceptance-Tests gefunden zu haben, und zwar mittels einer JavaProject-Fassade für die Java Compiler API, mit der ich tatsächlich on-the-fly ein kleines Java-Projekt komplett mit Sourcen erstellen und kompilieren kann. Anschließend kann ich in meinem TestCase die generierten Klassen per Classloader laden und mittels Reflection prüfen, oder alternativ dazu, könnte ich auch vorbereitete Unit-Tests laufen lassen, welche die generierten Builder testen.

Was allerdings das Unit-Testen des AnnotationProcessor angeht, tappe ich noch im Dunkeln. Grundsätzlich bin ich ein ein Fan von Interaction-Based-Testing, allerdings erscheint mir in diesem Fall mit Mock-Objekten zu arbeiten sehr aufwändig. Alternativ dazu bleibt wohl nur ein State-Based Ansatz, wie etwa in diesem Post auf Stackoverflow beschrieben.

Dienstag, 9. August 2011

Tower Deconstruction in 3D

Wie im letzten Post erwähnt, beschäftige ich mich gelegentlich und sehr Hobby-mäßig mit Spieleentwicklung. Aktuell versuche ich mein Glück mit Unity3d.

Nun habe ich ein kleines aber vollständiges Spiel online gestellt, komplett mit serverseitiger Highscore-Liste.

Towers ist ein kleines Casual Game für alle, die gerne Türme einreißen. Ziel ist es, mit nur 10 Feuerbällen möglichst viele Bauklötze vom Tisch zu schubsen.

Steuerung
"Cursor rechts" & "Cursor links: Kamera bewegen
Maus bewegen: Zielen
Linker Mausknopf: Feuern