Gabi und Sascha
Kategorien : Alle | Berlin | Bücher | Fotografie | Java | Linkhalde | Weichware | Verfassung

Es heisst Ted Kennedy sei im Bett gestorben. War er überhaupt ein richtiger Kennedy? Oder ist er im Bett erschossen worden? Wie es sich für einen Kennedy gehört.

Die Linke versucht sich auf ihre Art vom Casinokapitalismus inspirieren zu lasseen. Sie erfindet das Perpetuum Mobile für Reichtum – oder Armut – je nach Standpunkt.

[WAHLPLAKT "DIE LINKE" MIT AUFSCHRIFT "REICHTUM FÜR ALLE"]
Reichtum für alle
[WAHLPLAKT "DIE LINKE" MIT AUFSCHRIFT "REICHTUM BESTEUERN"]
Reichtum besteuern

KML ist nicht die eleganteste XML Applikation, aber eine effektive. Mit JAK gibt es jetzt ein API zur einfacheren Verarbeitung.

Die @ToString Java Annotation benötigt Werkzeugunterstützung, damit sie irgend einen Sinn macht. Ich hatte hier schon eine Beispielimplementierung verlinkt. Die Implementierung zeigt nur, wie es geht und das es geht. Sie ist weit von Vollständigkeit entfernt. Beispielsweise behandelt sie nicht alle Eventualitäten und skaliert auch nicht hinsichtlich Werkzeugunterstützung.

Werkzeugunterstützung

Die Werkzeugunterstützung soll sich nicht nur auf ein Frontend beschränken. Ich selbst bevorzuge Maven, kann aber die Vorbehalte dagegen nachvollziehen. Deswegen sollen auch Ant, Gradle oder Buildr User sollen unterstützt werden. Deswegen wird der eigentliche @ToString Prozessor von der @ToString Implementierung und den Frontends getrennt.

[UML PACKAGE DIAGRAMM: @TOSTRING<--PROZESSOR<--MAVEN]

Die Trennung zwischen der @ToString Annotation und dem Prozessor wird vorgenommen, da

  1. der Prozessor nichts in der Anwendung selbst zu suchen hat
  2. es weitere Prozessorimplementierungen geben kann

Der Prozessor

Der Prozessor muss zwei Dinge erledigen:

  1. den Bytecode von Klassen untersuchen, um die @ToString Annotationen aufzusammeln
  2. aus den aufgesammelten @ToString Annotationsinformationen gegebenenfalls eine toString() Methode in den untersuchten Bytecode einfügen

Analyse

Der Prozessor analysiert den Bytecode. Dies ist mit Unterstützung von Werkzeugen wie ASM trivial. Anders als bei einer Analyse mittels Reflection muss die Vererbungshierarchie allerdings manuell untersucht werden. Bei Reflection Analysen hat sich in anderen Projekten gezeigt, dass es öfter zu ExceptionInInitializerError kommt als gedacht. Insbesondere bei grösseren Projekten, in denen auch unerfahrene Entwickler mitarbeiten, ist dies ein Phänomen.

Die Analyse der Vererbung muss berücksichtigen, dass private Methoden und Felder in Oberklassen nicht berücksichtigt werden können. Bei package-private Feldern und Methoden muss geprüft werden, ob sich die Ober- bzw. Unterklasse im selben Package befindet. Ist dies der Fall, dürfen sie ausgewertet werden. Ist es nicht der Fall, so dürfen sie – wie bei private – nicht berücksichtigt werden.

protected und public Felder und Methoden sind kein Problem.

Das Analysewerkzeug muss auch statische und/oder finale Methoden und Felder berücksichtigen. Wie diese zu behandeln sind, wird dann später bei der toString() Methodenerzeugung berücksichtigt.

Erzeugung

Der Prozessor muss einfach sein und eine robuste toString() Methode implementieren. Hierbei wird stark auf Java Bordmittel zurückgegriffen. Innerhalb der toString() Implementierung wird ein StringBuilder verwendet. Mittels dessen append Methoden werden die Werte von Feldern und Methoden aneinandergereit.

Zu beachten ist, dass StringBuilder keine Methoden für das Anhängen der primitiven Typen byte und short hat. Hier würde es beim Laden des Bytecodes zu einem verify-Fehler kommen. Mit byte und short muss deswegen die entsprechende int Methode aufgerufen werden. Ebenfalls sollte die append(char[]) des StringBuilders nicht aufgerufen werden. Grund: es sollen die Werte des Arrays dargestellt werden, nicht das Array als String.

Der Rückgriff auf den StringBuilder und die Arrays Hilfsklasse, die im folgenden Abschnitt erläutert wird, befreien auch von null Referenz Prüfung. Diese Aufgabe übernehmen diese beiden Systemklassen mit ihren Methoden.

Arrays

Für die Arrayunterstützung bietet Java mit der Klasse Arrays einige fundamentale Hilfsmethoden an. Uns interessieren dabei aktuell die toString(…) Methoden. Diese Methoden erzeugen aus einem eindimensionalen Array einen definierten String. Für mehrdimensionale Arrays steht die deepToString(Objet[]) Methode bereit. Der erzeugende Code muss also untersuchen, ob es sich um ein eindimensionales Array oder um ein mehrdimensionales Array handelt und entsprechend reagieren.

enum, Interfaces und Annotationen

Grundsätzlich ist es verboten Methoden in Java Interfaces oder Java Annotationen zu erzeugen. Der Classloader würde soetwas mit einem VerifyError quitieren und die entsprechende Klasse nicht laden.

Auf bei Enums sollte keine toString() Methode erzeugt werden, da diese bereits definiert ist. Der Prozessor soll also Enums, Interfaces und Annotationen ignorieren. Im Bytecode ist hinterlegt, um welchen Typen es sich handelt.

toString() Methode vorhanden?

Wird im Bytecode eine toString() Methode mit der entsprechenden Signatur gefunden, dann muss entschieden werden was zu tun ist. Ein konservativer Prozessor soll die bestehende Methode nicht ersetzen. Dennoch soll er so zu konfigurieren sein, dass er die bestehende Methode entfernt und eine eigene Methode erzeugt.

Ist keine toString() Methode vorhanden, dann wird eine toString() Methode erzeugt. In einem solchen Fall kann davon ausgegangen werden, das keine toString() Methode im Quelltext vorhanden ist. Deswegen muss der Prozessor die zu erzeugende Methode als synthetisch kennzeichnen. Dies schreibt Kaptitel 4.7.6 der Java Virtual Machine Specification (Second Edition) vor.

Anders verhält es sich bei einer Ersetzung der toString() Methode. Dabei kann davon ausgegangen werden, dass die toString() Methode im Quellcode vorhanden ist.

Abschluss

Wenn ich nichts übersehen habe, dann kann die Implementierung jetzt starten.

Gestern auf dem Weg zur Arbeit. Keine besonderen Vorkommnisse. Ecke Ebertystraße Kochanstraße. Für uns ist die Ampel rot. Ich – auf dem Fahrrad – warte, das Auto vor mir wartet. Dem Fahrer in seinem Auto dahinter dauert das alles zu lange. Er blinkt, fährt an und überquert die Kreuzung.

Weidenweg Ecke Friedenstraße. Wegen einer Baustelle ist die Zufahrt zur Friedenstraße gesperrt. Durch ein Einbahnstraßenschild. Ganze Fahrzeugkolonnen ignorieren das Schild. Es ist doch nur ein Schild.

Wieder eine Ampelkreuzung. Wieder rot. Straße der Pariser Kommune Ecke Rüdersdorfer Straße. Ein BMW mit polnischen Kennzeichen braust auf die Kreuzung zu und biegt mit quietschenden Reifen links ab. Das leuchtende Rot – vermutlich hat der Fahrer es übersehen.

Vor ein paar Tagen hatte ich dieses Problem. Ich habe es am Wocheende radikal gelöst. Die Java Annotation @ToString kann vor Felder und Methoden ohne Parameter gesetzt werden. Ein Prozessor liesst die Informationen aus und injiziert eine Java toString() Methode in den Bytecode. Ein Prototyp kann hier herunter geladen werden. Der Prototyp ist noch sehr rudimentär und prüft noch nicht alle Eventualitäten, berücksichtigt aber Vererbung (nicht jedoch Interfaces). Der injizierende Code funktioniert. Nächster Schritt dann, ein Tool drum basteln und ein entsprechendes Maven Plugin schreiben.

Es ist nicht der erste Code, der soetwas macht. Beispielsweise beschreibt Dennis Sosnoski auf IBM Developer Works etwas ähnliches.

Mein Kind (knapp 1 Jahr) brachte mir heute bei, wie man beim Mac einen Film wieder startet, ohne die Maus zu benutzen! Einfach "home" drücken :-)

Vater zum Kind: "Mama hat Füße wie ein Neger."

 

Ein kleiner Schritt für mich… im Pankower Staub.

[FUSS IM STAUB DER GREIFSWALDER STRAßE IN BERLIN, PANKOW]

 

Nett, aber auf Dauer doch ein klein wenig langweilig.

[IT'S HARD TO BE A CITIZEN]
Künstler: El Bocho — Ort

 

Wie teilt sich jetzt eigentlich die Welt mit, dass Twitter down ist?

Wenn gegen §212 StGB verstossen wird, um das Land vor so einem Politiker zu schützen, dann kann das in Kauf genommen werden?

Mein Handy zeigt etwas, was Du nicht siehst ist eine Geschichte auf Spiegel Online überschrieben. Ich hatte vor Jahren einmal ein Konzept für solch ein System auf dem Tisch, für eine technische Begutachtung. Das Konzept basierte nicht auf einer Kombination von GPS und Kompassdaten, sondern auf Pattern Recognition. Das Konzept hatte gegenüber der GPS/Kompass-Lösung den Vorteil nicht auf diese und ihr funktionieren angewiesen zu sein. Beispielsweise hat GPS Probleme in Innenräumen, unter der Erde usw. Erschwerend kommt hinzu, dass GPS in Häuserschluchten unpräzise ist. Viele Sehenswürdigkeiten gibt es nun einmal innerhalb von Städten.

Der Anspruch der Erfinder mit dem Pattern Recognition Ansatz ging aber weiter als grob Wikipedias Geokoordinaten weiter zu verwenden. Sie wollten den Menschen nicht nur zeigen was sie sowieso schon grob kannten sondern tiefer in die Materie gehen. Neuschwanstein ist bekannt, aber was für eine spannende Geschichte gibt es zum Torbereich zu erzählen? Andererseits was aber wenn Nebel die Sicht versperrt. Ebenfalls hat der Ansatz auch Probleme mit unsichtbaren oder grossen Sehenswürdigkeiten. Das Schlachtfeld von Kalkriese ist damit eher schwer zu erkennen.

Die Kamera des Handies hat ein Bild aufgenommen, ein Muster wurde daraus berechnet (z.B. mittels genetischer Algorithmen). Dieses wurde an einen Server gesendet, der verglich das Muster und lieferte Informationen zum gesehenen, welches in die Kamera eingeblendet werden sollte. Einen Prototypen gab es bereits. Jetzt benötigten sie Geld. Viel Geld, denn der Mustererkennungsansatz erfordert eine genaue Erfassung der abzubildenden Sehenwürdigkeiten und ihre permanente Aktualisierung. 25 Millionen Euro wollte das Unternehmen vom Starnberger See damals haben — um Deutschland zu erfassen. Ob es letztlich am Geld gescheitert ist weiss ich nicht.

Ich halte eine Kombination aus GPS und Kompassdaten auf der einen Seite und Pattern Recognition auf der anderen Seite für das effektivste Vorgehen. Die Vorteile beider Seiten werden vereinigt und die Nachteile fast komplett eliminiert. Ich bin auch überzeugt, das Augment Reality in 5 Jahren etwas ganz natürliches sein wird. Sei es als Add-on in Handies oder als zusätzliches Feature in Navigationsgeräten.

I prefer flat key-value based configuration structures. They are not domain specific and can be widely used in different development environments. Also flat key-value based configuration structures are widley used in a lot of commercial project. But they have some disadvantages. The development team must maintain a central document, where the keys are stored. It always happens that developer forget to keep documentatiom up to date. Sourcecode documentation like javadoc is a poor administrator documentation, even for bigger projects with a bunch of moduls. As a solution, the development team must maintain the semantic documentation of the key-value pair away from the sourcecode. Maybe in a wiki or other technical documentations sheets.

A solution may be the metadata programming model of languages like Java (Annotation since Java 5) or C# (System.Attribute). In the following, I describe a simple system to get out of the dilemma, based on my experience with Java. The idiom is implemented in 5 different projects “– only the hibernating εos-toolkit is open source. At this time there are no negative side effects.

I define the configuration keys in the sourcecode as String constants. Other types are also possible, but the make no sense. Also none constant fields make no sense. Constants in Java are static final fields. The may be public, private or protected. The public visibility has less side effects as you'll see later. The value of the constant defines the configuration key. To avaoid naming conflicts, I prefer full qualified names.

Example:


    public class ConstantExample {

        public static final String CONFIGURATION_KEY =
            ConstantExample.class.getName() + ".something";
    }

In the root package (namespace), the value is "ConstantExample.something". This technique is safe enough in order to avoid naming conflicts. The constant may be refered somewhere in the sourcecode to access the configured value. Its out of scope of this articel how to do that.

In the εos-tooklkit project I have defined a annotation to mark a constant as configuration key. The annotation contains also some information to document the semantic of the configuration key, supporting an optional default value, a type of the value and an optional predicate to check the value of the configuration key. In the εos-toolkit project the documentation is also optional. But it is always a good idea to make the documentation mandatory.

The current implementation:


    import  static java.lang.annotation.ElementType.FIELD;
    import  static java.lang.annotation.RetentionPolicy.RUNTIME;

    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;

    @Documented
    @Retention(value = RUNTIME)
    @Target(value = FIELD)
    public @interface ConfigurationKey {

        String description();

        String defaultValue() default "";
        Type type() default Type.STRING;
        Class<? extends Predicate<String>>[] validators() default AlwaysTruePredicate.class;

        public enum Type {
            BOOLEAN,
            INTEGER,
            FLOAT,
            STRING,
            CLASSNAME
        }

    }

The annotation field definitions are marked. If you don't understand the annotations of the annotation definition, please refer the Javadoc pages. The Retention was set to RUNTIME to get the default value at runtime if no value is configured (e.g. null). Cause of this the key constant should also be public.

The usage is quite easy:


    public class ConstantExample {

        @ConfigurationKey(description =  "Something is a simple random value.")
        public static final String CONFIGURATION_KEY =
            ConstantExample.class.getName() + ".something";
    }

The constant field is now marked as a configuration key. The other possible settings are:

defaultValue

During my software development experience I've found, that many configuration values have a meaningful value. With this field it is possible to define such a default value. In a further artcile I'll describe a utility class to lookup the configuration value in the from the configuration system or returns the default value if the configuration system does not contain such a value.

If the developer does not define a default value, the value is an empty String.

type

Defines the possible type of the configuration value. The field is for configuration tool support. Based of the value a configuration tool can supply spezialized widgets for entering configuration values.

The defined enums above are only a recommendation of possible values. Also possible and used are the type CLASSNAME for factory configurations or DATE for a… yes date or IP4 and so on.

validators

Defines a list of Predicate class that validates the configuration value. This part is also to support configuration tools. A Predicate recieves a value, validates it and returns only a true or false. The implementation should support a default constructor.

If the developer does not support a Predicate or reuse an existing one, the defalut used implementation should always return true.

More complex example:


    public class Ip4SubnetConfigurator {

        @ConfigurationKey(description =  "Useable IP4 net.",
                          defaultValue = "10.0.0.10/20",
                          type = IP4,
                          validators = {Ip4NetPredicate.class})
        public static final String CONFIGURATION_KEY =
            Ip4SubnetConfigurator.class.getName() + ".start.subnet.ip4";
    }

Currently there are no other useful values known. An experiment with a module definition has been identified as not useful. The module can be represented with the package or JAR. Also in an upcomming blog entry, the module is represented by the Maven artifact identifier.

With special tools, it is now possible, to introspect a bulk off classes, to generate a key-value file with the configuration values. Its also possible generate a file for configure a system and to generate documentation pages in APT, Docbook or DITA. It's also possible to supply the value directly during a nightly build via Webservices to an existing wiki system like Cobertura or Trac.

Conclusion

The ConfigurationKey annotation is a simple mechanism to mark keys for key-value configuration systems. With tools it's easy to collect them back and aggregate them. No centralized repository (e.g. wiki) are needed to document the keys.

Upcomming

Tool support with Maven.