Dieses Blog durchsuchen

Donnerstag, 12. Mai 2011

Lombock - Fast schon eine DSL

Wer kennt das nicht. Eigentlich will ich nur einen Datenhalter haben, der ein 1:1 Mapping mit der Datenbank herstellt. Wer ist da nicht in Versuchung:

public class User {
public Long id;
public String name;
}

Ich habe ein kleines Framework gefunden, welches die Bean-Konventionen transparent setzt: Das Projekt Lobmbock. Just have a look:

@Data
@Entity
public class User {
@Id
@GeneratedValue
private Long id;

private String name;

@OneToMany
private Set roles = new HashSet();
}

Mehr will ich doch gar nicht formulieren. Ich habe zwei Attribute, davon ist eins der Key, außerdem habe ich ein Attribut (name) und eine Relation zu Rollen.

Durch die magic @Data Annotation wird mir jetzt im Bytecode alles generiert, was ich brauche: Getter, Setter, toString, equals .... alles was ich brauche um den Bean-Konventionen genüge zu tun. Und: Weil Eclipse den Syntaxcheck nicht auf Sourceebene sondern auf Ebene der Class-Files macht, läuft der folgende Test auch grün:


@Test
public void registerUser(){
User user = new User();
user.setName("bubu");
userService.register(user);
...
}


Cool. Fast schon eine interne DSL in Java, könnte man meinen. Ich konzentrier mich auf das Wesentliche aber nicht per "Metainformationen" außerhalb des Codes (UML, XML) und "Externen Generator" sondern mit den Sprachkonstrukten, die mir Java dafür bereit stellt. Daraus kann man ein schönes Tutorial für Spring machen. Ich werde das mal angehen, damit ich es nicht vergesse.

Der Geplante Trail:


  • Persistenz mit Daten Transferobjekten und Lombock (DTO)

  • Datenbanktests mit SpringJUnit4 formulieren

  • Konfiguration von Hibernate mit MySQL oder HSQL

  • Datenzugriff mit Data Access Objekten (DAO)

  • Höherwertige Services, die DAO für das Speichern der Daten benutzen

  • Spring Konfiguration für das "verdrahten" von Services (Dependency Injektion).

  • Workflow mit Spring MVC

Mittwoch, 26. Januar 2011

Unsägliche Strings

In einem Projekt Ende der 90er Jahre sagt mir mal ein geschätzter Kollege, der im Wesentlichen in der IBM Hostwelt zu Hause war: "Manfred, 90% der Programmierung ist doch eh' Zeichenkettenverarbeitung."

Tatsächlich ist man schnell dabei einen Datentyp als String zu identifizieren: Ein Name, ein Vorname ... aber wie ist das mit einer Rechnungsnummer, eine Lieferscheinnummer etc.

Tatsächlich ist ein String nicht wirklich ein "Datenentyp", denn ein Datentyp sollte z.B. einen Wertebereich haben und sollte auch Constraints beinhalten. Wie ist der Wertebereich eines Strings?

Und, meistens meint man ja auch gar nicht eine "beliebige Zeichenkette". Habe ich ein Attribut mit dem Typ String, dann sollte die Eingabe von "Hallo Welt" als Wert dieses Strings valide sein. Ist das Attribut ein Kommentar, wird das auch immer der Fall sein. Wie ist das aber jetzt bei der oben genannten Rechnungsnummer.

Der §14 UStG sieht vor, dass jede Rechnung eine "fortlaufende Nummer mit einer oder mehreren Zahlenreihen [enthalten muss], die zur Identifizierung der Rechnung vom Rechnungsaussteller einmalig vergeben wird (Rechnungsnummer)".

Das hört sich nicht nach "Hallo Welt" an, sondern nach einem Datentyp Rechnungsnummer, der bestimmte Constraints hat, unter anderem eine fortlaufende Nummer.

Auch sah ich jüngst eine API, in der GUI Eigenschaft etwas wie folgt notiert wurden:

Window win = new Window("enabled=true, visible=true");

Die API erwartet einen String.

Fazit: Strings sollten in der Objektmodellierung als Attribute verboten werden. Es sollte einen Datentyp AnyCharacter geben, der dann auch genau beschreibt, was er beinhalten darf: Eine beliebige Zeichenkette. Sobald die Zeichenkette Semantik enthält, taugt sie nicht mehr zum String.

Code Snibblet

Bis heute habe ich nicht verstanden, was mir dieses Stück Code sagen will:

this.enabled = (typ > 1 || typ < 4);

Offensichtlich ist der Fehler auch bis heute nie aufgetreten. Dann doch lieber:

this.enabled = true;

Freitag, 14. Januar 2011

Umwandlung von String in Integer

Um ein java.lang.Integer zu initialisieren gibt es die statische Methode valueOf(). So kann dieses Objekt z.B. über ein int oder über einen String initialiert werden.


Integer a = Integer.valueOf(22);
Integer b = Integer.valueOf("22");


Gleiches gilt für die Rückverwandlung. Die Methode intValue() oder toString() wandeln das java.lang.Integer wieder in ein int oder in einen String zurück.

Man kann es aber auch so machen:

Die Methode clasz.foo() gibt einen String zurück:


int bar = ((Integer) new Integer(clasz.foo())).intValue();


Da hat jemand bestimmt lange gebastelt, bis der Compiler "yes" gesagt hat. Die korrekte Lösung ist einfach und hat noch den Vorteil, dass kein Integer Objekt erzeugt werden muss.


int bar = Integer.valueOf(clasz.foo());

Mittwoch, 5. Januar 2011

Das Rad neu erfinden (1)

Manchmal machen auch die kleinen Dinge schon Probleme.

Da ist die Klasse Datum, die auch mit einer sprechenden Zeichenkette wie "TODAY" initialisiert werden soll.

Man sollte nun denken, dass folgender Test grün läuft, wenn er nicht gerade um 23:59:999 läuft:


Datum datum1 = new Datum(Datum.TODAY);
Thread.sleep(1);
Datum datum2 = new Datum(Datum.TODAY);
Assert.assertEquals(datum1, datum2);


Ein Blick in die Implementierung zeigt, warum der Test ROT läuft: Ein

new Datum(Datum.TODAY);

ruft nur ein

new GregorianCalendar();

auf. Der GregorianCalendar hält aber neben dem Datum auch die Zeit. Die equals - Methode der Datum Klasse stützt sich dann auch vollständig auf den GregorianCalender ab:

return this.cal.equals(cal);

Dieser wiederum hält die Millisekunden nach dem ....

Immerhin: Nach 5 Jahren Projekt ist das Problem dann auch mal zu Tage getreten. Ein Unit-Test war vorhanden, aber niemand ist auf die Idee gekommen, dass dieses ein sinnvoller Constraint sein könnte.

Merke: Wenn Du schon das Rad neu erfindest und ein "eigenes Datum" brauchst, dann teste besonders gründlich und .... vollständig.

Das CAP Theorem

Das CAP-Theorem oder Brewer's Theorem besagt, dass es in einem Datenbanksystem unmöglich ist, gleichzeitig die drei Eigenschaften Konsistenz, Verfügbarkeit und Partitionstoleranz (Verteilung) zu garantieren.

Da in verteilten Datenbanksystemen die Partitionstoleranz gesetzt ist, muss man sich entscheiden zwischen vollständiger Konsistenz und Verfügbarkeit.

Große Anwendungen wie Amazon, Facebook oder LinkedIn haben zu diesem Zweck ihre eigenen Datenbanken entwickelt, die unter dem Namen NoSQL geführt werden. Beispiele sind: Redis, CouchDB, MongoDB, Voldemort ...

Links:
http://blog.mongodb.org/post/475279604/on-distributed-consistency-part-1

Intro

Im Laufe der letzten 12 Jahre habe ich viel in Projekten gesehen. In (wirklich) großen Projekten oder auch in kleinen. Meistens schmunzele ich, raufe mir die Haare oder schreibe meine Freunde an (neulich habe ich folgendes gesehen ....). Vielleicht hilft es ja, mal ein paar Dinge einfach aufzuschreiben, dachte ich mir. So ist dieses Blog entstanden.

Ich sage nicht in welchem Projekt ich es gesehen habe und ich will auch nicht anprangern. Vielleicht findet sich "das Eine" oder auch "das Andere", was zu Gedankenanstößen im eigenen Projekt führt.

Ich will nicht nur von "anderen" reden, einige Böcke habe ich selbst verzapft. Immer im "guten Glauben", dass dieses eine sehr gute Idee ist.

Also schaun mer mal, ob mehr als zwei P-itfalls zusammenkommen, oder ob das Blog schnell verwaist.

Als zweites möchte ich dieses Blog nutzen um Dinge zu notieren, die ich in der Auseinandersetzung mit der realen IT-Welt interessant finde.

Schaun mer mal, wie der Kaiser sagt.