Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Constraint Code Generator

143 views
Skip to first unread message

ma...@heinerkuecker.de

unread,
Mar 1, 2013, 9:55:28 AM3/1/13
to
Hallo Java-Freunde,

ich habe meinen vor langer Zeit (März 2012) veröffentlichten Constraint Code Generator weiterentwickelt.

Die URL für den Download lautet

http://heinerkuecker.de/ConstraintCodeGenerator.html

Die Folien vom März 2012, welche längst nicht mehr aktuell sind, stehen dort auch.

Neue Folien mache ich in nächster Zeit.

Falls jemand mehr darüber erfahren will, kann derjenige das auf den Stuttgarter Testtagen am 22.03.2013.

http://www.jugs.org/tt2013/abstracts.html#link07

Ich habe den Code im Zip für die Veranstaltung in Stuttgart als Übungen vorbereitet, bin aber nicht nicht fertig.

Im Kaffeeklatsch ist dazu heute ein Artikel erschienen:

http://www.bookware.de/kaffeeklatsch/archiv

Das aktuelle Heft ist erst im Folgemonat im Archiv, für das aktuelle Heft dieses Monates muss man sich anmelden.

Der Artikel-Text ist aber als ASCII im Zip enthalten.

Falls jemand Interesse an detaillierten Infos hat, bitte hier posten oder per persönlicher Mail.

Grüße
Heiner

Patrick Roemer

unread,
Mar 4, 2013, 5:22:59 PM3/4/13
to
Responding to ma...@heinerkuecker.de:

> ich habe meinen vor langer Zeit (M�rz 2012) ver�ffentlichten Constraint Code Generator weiterentwickelt.
>
> Die URL f�r den Download lautet
>
> http://heinerkuecker.de/ConstraintCodeGenerator.html

Nach dem Lesen der Seite kann ich mir zwar ungefaehr vorstellen, worum
es geht, aber noch ueberhaupt nicht, wie das konkret im Code aussieht,
geschweige denn, wie man das in einen Build-Prozess einbauen sollte. Das
klaert sich auch bei erster Sichtung des Zip nicht: Die Textdatei ist
eher eine philosophische Abhandlung denn ein README, und auch nach dem
Punkt "Einfach Loslegen" bin ich so schlau wie zuvor (und habe keine
Ahnung, wie ich loslegen soll). Spaetestens da bin ich auch bei
groesstem initialen Interesse raus aus der Nummer.

Ein minimales, motivierendes Beispiel auf der Seite und ein (ggfs. genau
dieses Beispiel aufbauendes) Step-By-Step-Tutorial waeren hilfreich.

Viele Gruesse,
Patrick

ma...@heinerkuecker.de

unread,
Mar 5, 2013, 4:59:55 AM3/5/13
to
Patrick Roemer schrieb:
> Responding to Heiner Kücker:
> > ich habe meinen vor langer Zeit (März 2012) veröffentlichten Constraint Code Generator weiterentwickelt.
> Nach dem Lesen der Seite kann ich mir zwar ungefaehr vorstellen, worum
> es geht,

Oh, die erste Reaktion, Danke, Klasse.

> aber noch ueberhaupt nicht, wie das konkret im Code aussieht,
> geschweige denn, wie man das in einen Build-Prozess einbauen sollte.

Mit dem Build-Prozess ist das so eine Sache.
Eigentlich sollte generierter Code niemals eingecheckt werden
und bei jedem Build neu gebaut werden.

Ich hatte de Code-Generator im letzten Prijekt verwendet und irgendwann
waren die Constraints in Code drin, den der Generator zum Starten benötigte.

Als erstes sollte die Analyse (nur kurz im Kopf) des Projektes erfolgen.
Wo möchte ich Code (Methoden-Parameter) per Compiler absichern.

Als Beispiel eine Methode

void bestellungFreigeben(
// User mit Rolle und weiteren Infos (Abteilungsnummer)
final User user ,
// zu bearbeitende fachliche Entität
final Bestellung bestellung )
{
...

Da die Prädikate nur ein Objekt als Parameter entgegennehmen,
benötigt man ein Kontext-Objekt (dies war in meiner App schon
vorhanden und war einfach praktisch in der Anwendung)

public final class BestellungKontextObj
{
public final User user;

public final Bestellung bestellung;

/**
* Konstruktor
*/
public BestellungKontextObj(...
}


Dann müssen die Prädikate geschrieben werden

public final BestellungFreigebenRole
extends PrimitivPredicate<BestellungKontextObj>
{
public boolean test(
final BestellungKontextObj bestellungKtxObj )
{
return bestellungKtxObj.user.getRole().equals(
Role.FreigebenRole );
}

}

public final BestellungFreigebenStatus
extends PrimitivPredicate<BestellungKontextObj>
{
public boolean test(
final BestellungKontextObj bestellungKtxObj )
{
return bestellungKtxObj.bestellung.getStatus().equals(
// hier fällt mir kein besserer Name ein
BestellungStatus.NochNichtFreigegebenStatus );
}

}

Dann muss der Code-Generator aufgesetzt werden:
(zu beachten ist dabei, dass bei mir (WinXP, Eclipse 3.7)
der Pfad aus System.getProperty( "user.dir" ) auf das
aktuelle Eclipse-Projekt zeigt, so dass der
src-Ordner darunter liegt)

public final class BestellungConstraintCodeGenerator
{
/**
* Start Generierung.
*
* @param args unused
* @throws IOException rethrown
*/
public static void main(
final String [] args )
throws IOException
{
new AbstractConstraintCodeGenerator<Rolle>(
//cacheFolder
null ,
//srcDirPathStr
System.getProperty(
"user.dir" ) +
File.separator +
"src" ,
//packageName
"bestellapp.constraints" ,
//importStrArr ,
new String[]{
"bestellapp.types.User" ,
"bestellapp.types.Bestellung" ,
"bestellapp.predicates.*" } ,
//contextObjClassName
"BestellungKontextObj" ,
//contextObjName
"bestellungKtxObj" ,
//writeToDisc
true ,
//deleteUnusedConstraintJavaFiles (hier Vorsicht, besser erst mal false)
true ,
//exclude
new Exclude<BestellungKontextObj>() )
{{
add(
and(
new BestellungFreigebenRole() ,
new BestellungFreigebenStatus() ) );

// zwei einfache Constraints zum Test Konvertierung
add(
new BestellungFreigebenRole() );
add(
new BestellungFreigebenStatus() );
}}.execute();
}

}


Eigentlich ist das alles in dem Beispiel-Package

_01_simple

enthalten.

Wenn es noch Fragen gibt, bitte stellen, das hilft mir,
die Doku/Anleitung zu verbessern.

Ich würde dann auch gern die weiteren Beispiel-Packages
durcharbeiten.

Diese sollen auf den Stuttgarter Testtagen als Workshop dienen.

> Das klärt sich auch bei erster Sichtung des Zip nicht: Die Textdatei ist
eher eine philosophische Abhandlung denn ein README, und auch nach dem
>
> Punkt "Einfach Loslegen" bin ich so schlau wie zuvor (und habe keine
>
> Ahnung, wie ich loslegen soll).


> Spaetestens da bin ich auch bei
> groesstem initialen Interesse raus aus der Nummer.
>
> Ein minimales, motivierendes Beispiel auf der Seite und ein (ggfs. genau
> dieses Beispiel aufbauendes) Step-By-Step-Tutorial waeren hilfreich.

Ich bin dabei, dies zu erstellen.

> Viele Gruesse,
> Patrick


Grüsse
Heiner

ma...@heinerkuecker.de

unread,
Mar 5, 2013, 5:03:24 AM3/5/13
to
Heiner schrieb:
> /**
>
> * Start Generierung.
> *
> * @param args unused
> * @throws IOException rethrown
> */
> public static void main(
> final String [] args )
> throws IOException
> {
> new AbstractConstraintCodeGenerator<Rolle>(

kleine Korrektur

new AbstractConstraintCodeGenerator<BestellungKontextObj>(

> Grüsse
> Heiner

ma...@heinerkuecker.de

unread,
Mar 5, 2013, 5:22:29 AM3/5/13
to
> Heiner schrieb:
> new AbstractConstraintCodeGenerator<BestellungKontextObj>(

Die im constraint-Package oder so entstandenen Constraints müssen
dann natürlich im Code verwendet werden:

void bestellungFreigeben(
// User mit Rolle und weiteren Infos (Abteilungsnummer)
//final User user ,
// zu bearbeitende fachliche Entität
//final Bestellung bestellung
final ANDB_BestellungFreigebenRole_BestellungFreigebenStatus_ANDE constraint )
{
if ( constraint == null )
{
throw new IllegalArgumentException( "constraint is null" );
}

constraint.bestellung.setStatus(
BestellungStatus.FreigegebenStatus );

constraint.bestellung.save();
}



Grüsse
Heiner

ma...@heinerkuecker.de

unread,
Mar 5, 2013, 11:36:20 AM3/5/13
to
> Heiner schrieb:
> Die im constraint-Package oder so entstandenen Constraints müssen
> dann natürlich im Code verwendet werden:

Der Fehlerteufel war wieder fleißig:

constraint.bestellungKtxObj.bestellung.setStatus(
BestellungStatus.FreigegebenStatus );

constraint.bestellungKtxObj.bestellung.save();

Grüsse
Heiner

ma...@heinerkuecker.de

unread,
Mar 5, 2013, 4:16:22 PM3/5/13
to
>Heiner schrieb:

Ich habe eben noch ein frisches Zip hochgeladen:

http://heinerkuecker.de/ConstraintCodeGenerator.html

Grüsse
Heiner

ma...@heinerkuecker.de

unread,
Mar 6, 2013, 5:02:39 AM3/6/13
to
> Heiner schrieb:

Da hier auch Kollegen schreiben, die Scala-Erfahrung haben,
würde mich mal interessieren, ob man solche Expressions auch
in Scala formulieren kann.

Irgendsoetwas scheint es in Scala selbst zu geben:

http://apocalisp.wordpress.com/2010/06/13/type-level-programming-in-scala-part-3-boolean/

Dann gibt es noch was in Scalaz.

Leider habe ich nicht verstanden, wie das funktioniert und wie man es verwendet. Geht eventuell auch anderen so.


Grüsse
Heiner

Patrick Roemer

unread,
Mar 6, 2013, 7:28:49 AM3/6/13
to
Responding to ma...@heinerkuecker.de:

Danke fuer die Erlaeuterungen!

>> aber noch ueberhaupt nicht, wie das konkret im Code aussieht,
>> geschweige denn, wie man das in einen Build-Prozess einbauen sollte.
>
> Mit dem Build-Prozess ist das so eine Sache.
> Eigentlich sollte generierter Code niemals eingecheckt werden
> und bei jedem Build neu gebaut werden.

Das ist klar. Ich meinte:

- Wie konkret wird der Generator im Buildprozess aufgerufen? Ich hatte
zwar gesehen, dass da irgendwo von AbstractConstraintCodeGenerator
abgeleitet wurde, dachte aber, dass das eher didaktischen Charakter
habe, und dass es da irgendwo noch eine standalone-Mainklasse (oder
einen Ant-Task) geben koennte. Hat sich jetzt geklaert.

- Wie organisiert man seinen Code, so dass man nicht alles rot hat,
solange der Generator nicht gelaufen ist? Im Beispiel ist das ja alles
in einem src-Verzeichnis (inklusive generierter Klassen)
zusammengeworfen. In der Praxis wuerde ich denken, dass man z.B. drei
unterschiedliche Sourcefolder (src-core, src-gen, src-app) haben will.

> Eigentlich ist das alles in dem Beispiel-Package
>
> _01_simple
>
> enthalten.

Naja, das sind 2kLoC - das ist nicht so richtig einladend fuer einen
ersten Blick.

> Wenn es noch Fragen gibt, bitte stellen, das hilft mir,
> die Doku/Anleitung zu verbessern.

Was mir zum Verstaendnis immer noch fehlt, ist der Aufruf der derart
"gesicherten" Methode. Ich sehe jetzt, wie der Generator konfiguriert
und bedient wird, aber nicht, wie der Code dann schlussendlich verwendet
wird. Ich haette da auf den Testcase gehofft, aber der zeigt das auch nicht.

Ideal waere sicher ein vollstaendiges Step-by-Step-Tutorial in der
Groessenordnung des Beispiels, das Du hier jetzt vorgestellt hast,
inklusive einer Mainklasse fuer die tatsaechliche "Anwendung".

Ach so, warum muss man eigentlich das Verzeichnis der Constraint-Package
von Hand erstellen?

>> Ein minimales, motivierendes Beispiel auf der Seite und ein (ggfs. genau
>> dieses Beispiel aufbauendes) Step-By-Step-Tutorial waeren hilfreich.
>
> Ich bin dabei, dies zu erstellen.

Prima.

Was mich persoenlich angeht, muss ich sagen, dass mich das Projekt nicht
so richtig anspricht - nette Idee, aber in der Praxis viel zuviel
Boilerplate-Overhead fuer zuwenig Sicherheitsgewinn. Aber das ist
natuerlich subjektiv - mir geht ja schon die Geschwaetzigkeit im
Java-Typsystem gehoerig auf den Senkel. Und ich mag es auch nicht,
"Core-Code" zu schreiben, der von generiertem Code abhaengt. Ok, das
Problem hat man z.B. mit ANTLR auch, aber da ist es wenigstens nur eine
einzige Klasse, die man wegkapseln kann.

Viele Gruesse,
Patrick

Patrick Roemer

unread,
Mar 6, 2013, 7:47:50 AM3/6/13
to
Responding to ma...@heinerkuecker.de:

> Da hier auch Kollegen schreiben, die Scala-Erfahrung haben,
> würde mich mal interessieren, ob man solche Expressions auch
> in Scala formulieren kann.
>
> Irgendsoetwas scheint es in Scala selbst zu geben:
>
> http://apocalisp.wordpress.com/2010/06/13/type-level-programming-in-scala-part-3-boolean/

Das Scala-Typsystem ist turing-vollstaendig. Damit gehen auch so Scherze
wie eine Berechnung der Loesung fuer Towers of Hanoi zur Compilezeit[1],
oder ein TicTacToe-Spiel, bei dem ungueltige Zuege ein Compilerfehler
sind[2]. Das ist aber auch fuer Scala schon ziemlich esoterisch.

Im Prinzip sollte man Constraints also auch ueber phantom types codieren
koennen - aber dann braeuchte man wohl einen Typparameter pro
Constraint, da wuerde man auch bei kleinen Anwendungen schon in einem
Generics-Meer ertrinken. Klingt mir nicht wirklich praktikabel.

Ein bisschen in die Richtung gehen Typesafe Builders via Phantom Types.[3]

> Dann gibt es noch was in Scalaz.

Nicht, dass ich wuesste. (Aber ich bin auch kein passionierter
scalaz-Benutzer, vielleicht kenne ich es auch nur nicht.)

Da gibt es Validation[4], eine deutlich maechtigere Alternative zu
Either und Co. um Eingaben zu pruefen (und diese Pruefungen zu
kombinieren), aber das ist eine Runtime-Angelegenheit.

Wenn ich solche Constraints in Scala basteln wollte, wuerde ich
vermutlich ueberlegen, ob man da mit Macros[5] was drehen kann, aber da
habe ich auch noch nichts mit gemacht.

Viele Gruesse,
Patrick

[1] https://gist.github.com/jrudolph/66925
[2] http://blog.vasilrem.com/tic-tac-toe-api-with-phantom-types
[3]
http://jim-mcbeath.blogspot.de/2009/09/type-safe-builder-in-scala-part-3.html
[4] http://blog.lunatech.com/2012/03/02/validation-scala
[5] http://scalamacros.org/

ma...@heinerkuecker.de

unread,
Mar 6, 2013, 11:15:59 AM3/6/13
to
Patrick Roemer schrieb:
> Responding to Heiner Kücker:
> Danke fuer die Erlaeuterungen!
> >> aber noch ueberhaupt nicht, wie das konkret im Code aussieht,
> >> geschweige denn, wie man das in einen Build-Prozess einbauen sollte.
>
> > Mit dem Build-Prozess ist das so eine Sache.
>
> > Eigentlich sollte generierter Code niemals eingecheckt werden
> > und bei jedem Build neu gebaut werden.
>
> Das ist klar. Ich meinte:
>
> - Wie konkret wird der Generator im Buildprozess aufgerufen? Ich hatte
> zwar gesehen, dass da irgendwo von AbstractConstraintCodeGenerator
> abgeleitet wurde, dachte aber, dass das eher didaktischen Charakter
> habe, und dass es da irgendwo noch eine standalone-Mainklasse (oder
> einen Ant-Task) geben koennte. Hat sich jetzt geklaert.

Ich habe es immer über den grünen Run-Pfeil
in der Eclipse gestartet.

> - Wie organisiert man seinen Code, so dass man nicht alles rot hat,
> solange der Generator nicht gelaufen ist? Im Beispiel ist das ja alles
> in einem src-Verzeichnis (inklusive generierter Klassen)
> zusammengeworfen. In der Praxis wuerde ich denken, dass man z.B. drei
> unterschiedliche Sourcefolder (src-core, src-gen, src-app) haben will.

Dafür habe ich keine Idee,
wenn diese drei src-Verzeichnisse
normale Eclipse src-verzeichnisse
sind kann man es einfach so organisieren.

> > Eigentlich ist das alles in dem Beispiel-Package
> > _01_simple
> > enthalten.
>
> Naja, das sind 2kLoC - das ist nicht so richtig
> einladend fuer einen ersten Blick.

Es gibt noch die Aufgaben.txt

Ich werde für die Stuttgarter Testtage
einzufügenden Code auskommentieren und
anzulegende Klassen in *.java-TODO
umbenennen.

Faule Zuhörer haben es dann ganz leicht,
wer Interesse hat kann sich mehr engagieren.

> > Wenn es noch Fragen gibt, bitte stellen, das hilft mir,
> > die Doku/Anleitung zu verbessern.
> Was mir zum Verständnis immer noch fehlt, ist der Aufruf der derart
> "gesicherten" Methode. Ich sehe jetzt, wie der Generator konfiguriert
> und bedient wird, aber nicht, wie der Code dann schlussendlich verwendet
> wird. Ich hätte da auf den Testcase gehofft, aber der zeigt das auch nicht.

Wenn die Methode abgesichert wurde (Constraint als Parameter
verwendet) findet der Compiler die Aufruf-Stellen.

Dort muss man einfach wiederum das Constraint einsetzen.

Irgendwo geht das nicht mehr, die Daten kommen aus
einer externen Quelle. Hier ruft man den Konstruktor
des Constraints auf (siehe Abschnitt sicherer und unsicherer
Bereich im Text)

> Ideal waere sicher ein vollstaendiges Step-by-Step-Tutorial in der
> Groessenordnung des Beispiels, das Du hier jetzt vorgestellt hast,
> inklusive einer Mainklasse fuer die tatsaechliche "Anwendung".

Ok, das muss ich ergänzen, ich hatte den
Konstruktor-Aufruf nicht als
Anwendungs-Hindernis im Scope.

> Ach so, warum muss man eigentlich das Verzeichnis der Constraint-Package
> von Hand erstellen?

Prinzipiell kann man in Java mit File#mkdirs leicht
Verzeichnis-Pfade erstellen, falls der aber falsch
ist, landen die generierten Klassen irgendwo auf
der Platte, fand ich nicht so sicher.

> >> Ein minimales, motivierendes Beispiel auf der Seite und ein (ggfs. genau
> >> dieses Beispiel aufbauendes) Step-By-Step-Tutorial waeren hilfreich.
> >
> > Ich bin dabei, dies zu erstellen.
>
> Prima.
>
> Was mich persönlich angeht, muss ich sagen, dass mich das Projekt nicht
> so richtig anspricht - nette Idee, aber in der Praxis viel zuviel
> Boilerplate-Overhead für zuwenig Sicherheitsgewinn.

In altem Java ist es nicht so einfach,
ein Parser mit der kompletten Analyse
des AST wäre noch eine Lösung.
Auch nicht so einfach.

> Aber das ist
> natuerlich subjektiv - mir geht ja schon die Geschwaetzigkeit im
> Java-Typsystem gehoerig auf den Senkel. Und ich mag es auch nicht,
> "Core-Code" zu schreiben, der von generiertem Code abhaengt.

Das ist bei MDA, MDD, DSL auch nicht zu vermeiden.

> Ok, das
> Problem hat man z.B. mit ANTLR auch, aber da ist es wenigstens nur eine
> einzige Klasse, die man wegkapseln kann.

Scala scheinen die Kunden nicht zu wollen.
Gib hier mal Scala als Suchbegriff ein:

http://www.gulp.de/cgi-gulp/robot.exe/SSEEK

Rein theoretisch gesehen, ist der Aufwand für einen
Sicherheitsgewinn immer größer als der Sicherheitsgewinn,
also eine absolute Sicherheit gibt es beim Programmieren
nicht.
Trotzdem möchte ich die Java-Typisierung nicht missen,
ich kannte anderes mit Qualen.

Meine Motivation steht im Anleitungs-Text unter
dem Abschnitt 'das verfluchte if'.

ma...@heinerkuecker.de

unread,
Mar 6, 2013, 1:42:29 PM3/6/13
to
Patrick Roemer schrieb:
> Responding to Heiner Kücker:
>
> > Da hier auch Kollegen schreiben, die Scala-Erfahrung haben,
> > würde mich mal interessieren, ob man solche Expressions auch
> > in Scala formulieren kann.
> > Irgendsoetwas scheint es in Scala selbst zu geben:
>
> Das Scala-Typsystem ist Turing-vollständig. Damit gehen auch so Scherze
> wie eine Berechnung der Loesung fuer Towers of Hanoi zur Compilezeit[1],
> oder ein TicTacToe-Spiel, bei dem ungültige Zuege ein Compilerfehler
> sind[2]. Das ist aber auch fuer Scala schon ziemlich esoterisch.
> [2] http://blog.vasilrem.com/tic-tac-toe-api-with-phantom-types

Das Tic-Tac-Toe-Beispiel gefällt mir,

Das sollte ich als Beispiel verwenden.

Es gibt 27 Spielstellungen (9 * 3).

Die könnte ich über parametrisierte Prädikate kodieren:

E - Empty
C -Cross
N -Noun

ANDB_E00_E01_E02_E10_...

Da würde ich die Dateinamens-Begrenzug auf 255 Zeichen noch einhalten.

Dazu kommt noch ein Prädikat, wer als nächstes dran ist:

NC - Next Cross
NN - Next Noun

ANDB_NC_E00_E01_E02_E10_...

Die erlaubten Nachfolge-Stellungen werden über
sichere Operationen erreicht.

constraint.setC00();

Ein schönes Beispiel.

> Im Prinzip sollte man Constraints also auch ueber phantom types codieren
> koennen - aber dann braeuchte man wohl einen Typparameter pro
> Constraint, da wuerde man auch bei kleinen Anwendungen schon in einem
> Generics-Meer ertrinken. Klingt mir nicht wirklich praktikabel.
>
> Ein bisschen in die Richtung gehen Typesafe Builders via Phantom Types.[3]
> [3]http://jim-mcbeath.blogspot.de/2009/09/type-safe-builder-in-scala-part-3.html

Das ist mir im Moment zu hoch, muss ich noch mal lesen.

Grüsse
Heiner

Patrick Roemer

unread,
Mar 6, 2013, 2:27:09 PM3/6/13
to
Responding to ma...@heinerkuecker.de:
> Patrick Roemer schrieb:
>> Was mir zum Verst�ndnis immer noch fehlt, ist der Aufruf der derart
>> "gesicherten" Methode. Ich sehe jetzt, wie der Generator konfiguriert
>> und bedient wird, aber nicht, wie der Code dann schlussendlich verwendet
>> wird. Ich h�tte da auf den Testcase gehofft, aber der zeigt das auch nicht.
>
> Wenn die Methode abgesichert wurde (Constraint als Parameter
> verwendet) findet der Compiler die Aufruf-Stellen.
>
> Dort muss man einfach wiederum das Constraint einsetzen.

Genau das wuerde ich aber halt in einem motivierenden Beispiel auch zeigen.

>> Aber das ist
>> natuerlich subjektiv - mir geht ja schon die Geschwaetzigkeit im
>> Java-Typsystem gehoerig auf den Senkel. Und ich mag es auch nicht,
>> "Core-Code" zu schreiben, der von generiertem Code abhaengt.
>
> Das ist bei MDA, MDD, DSL auch nicht zu vermeiden.

Verstehe ich nicht. Mit MDA kenne ich mich nicht aus, aber bei
"internen" DSLs bewegt man sich doch sowieso in der Hostsprache, und
Scripte in "externen" DSLs sind meist Gluecode, den man nicht wieder aus
der Hostsprache aufrufen will (und wenn das mal vorkommt, wird man eher
auf die hinter dem Parser liegenden AST-Konstrukte zugreifen, die
wiederum eine API in der Hostsprache bieten).

>> Ok, das
>> Problem hat man z.B. mit ANTLR auch, aber da ist es wenigstens nur eine
>> einzige Klasse, die man wegkapseln kann.
>
> Scala scheinen die Kunden nicht zu wollen.

Das hat ja mit Scala nichts zu tun, im Gegenteil: In Scala wuerde ich
keinen Parsergenerator a la ANTLR verwenden wollen, sondern Parser
Combinators (eine "interne" DSL).

> Rein theoretisch gesehen, ist der Aufwand f�r einen
> Sicherheitsgewinn immer gr��er als der Sicherheitsgewinn,
> also eine absolute Sicherheit gibt es beim Programmieren
> nicht.

Es ist eben ein Tradeoff zwischen zusaetzlichem Aufwand (und
verminderter Lesbarkeit) und gewonnener Sicherheit, und Aufwand und
Lesbarkeitsverlust scheinen mir persoenlich bei diesem Ansatz
entschieden zu hoch.

> Trotzdem m�chte ich die Java-Typisierung nicht missen,
> ich kannte anderes mit Qualen.

Schlechtes Beispiel. :) Das Scala-Typsystem z.B. ist maechtiger als das
von Java, und trotzdem muss man da weniger redundanten Kram tippen.

Viele Gruesse,
Patrick

ma...@heinerkuecker.de

unread,
Mar 6, 2013, 4:33:53 PM3/6/13
to
Patrick Roemer schrieb:
> Responding to Heiner Kücker:

Warum postest Du eigentlich immer meine Klar-Mail-Adresse,
ich bekomme ausreichend Spam, ist ok, muss nicht mehr sein.

> > Patrick Römer schrieb:
> >> Was mir zum Verst�ndnis immer noch fehlt, ist der Aufruf der derart
> >> "gesicherten" Methode. Ich sehe jetzt, wie der Generator konfiguriert
> >> und bedient wird, aber nicht, wie der Code dann schlussendlich verwendet
> >> wird. Ich h�tte da auf den Testcase gehofft, aber der zeigt das auch nicht.
> >
> > Wenn die Methode abgesichert wurde (Constraint als Parameter
> > verwendet) findet der Compiler die Aufruf-Stellen.
> > Dort muss man einfach wiederum das Constraint einsetzen.
>
> Genau das wuerde ich aber halt in einem motivierenden Beispiel auch zeigen.

Hm, das wird umfangreich,
zu umfangreich zum Lesen oder
alternativ zu wenig,
schwierig.

> >> Aber das ist
> >> natuerlich subjektiv - mir geht ja schon die Geschwaetzigkeit im
> >> Java-Typsystem gehoerig auf den Senkel. Und ich mag es auch nicht,
> >> "Core-Code" zu schreiben, der von generiertem Code abhaengt.
> > Das ist bei MDA, MDD, DSL auch nicht zu vermeiden.
> Verstehe ich nicht. Mit MDA kenne ich mich nicht aus, aber bei
> "internen" DSLs bewegt man sich doch sowieso in der Hostsprache, und
> Scripte in "externen" DSLs sind meist Gluecode, den man nicht wieder aus
> der Hostsprache aufrufen will (und wenn das mal vorkommt, wird man eher
> auf die hinter dem Parser liegenden AST-Konstrukte zugreifen, die
> wiederum eine API in der Hostsprache bieten).

Für interne DSLs gilt das nicht.

Aber die meisten Modellierungs-Technologien
haben als Ergebnis generierten Code.

Horch mal den Heise Developer Podcast

http://www.heise.de/developer/artikel/Episode-36-Modellierst-du-schon-oder-programmierst-du-noch-1674170.html

Oder die Sachen von Markus Völter.

In C# gibt es extra ein Vererbungskonstrukt
zum Trennen von generiertem und eingefügtem
Code.

> > Scala scheinen die Kunden nicht zu wollen.
> Das hat ja mit Scala nichts zu tun, im Gegenteil: In Scala wuerde ich
> keinen Parsergenerator a la ANTLR verwenden wollen, sondern Parser
> Combinators (eine "interne" DSL).
>
> > Rein theoretisch gesehen, ist der Aufwand f�r einen
> > Sicherheitsgewinn immer gr��er als der Sicherheitsgewinn,
> > also eine absolute Sicherheit gibt es beim Programmieren
> > nicht.
>
> Es ist eben ein Tradeoff zwischen zusätzlichem Aufwand (und
> verminderter Lesbarkeit) und gewonnener Sicherheit, und Aufwand und
> Lesbarkeitsverlust scheinen mir persönlich bei diesem Ansatz
> entschieden zu hoch.

Klar, dass ich anderer Meinung bin,
ich müsste mich sonst selbst verleugnen.

Es ist aber wirklich ein Fremdkörper im Java-Programm.

Es ist nicht einfach möglich, an der Constraint-Definition
Strg-Shift-G zu drücken und alle Benutzungs-Stellen zu finden

Ein geändertes Constraint muss auch manuell im Code
nachgezogen werden.

Für meinen Zweck war es ok, aber der initiale
Aufwand lohnt sich nicht für ein Projekt, den
habe ich aber jetzt geleistet.

> > Trotzdem möchte ich die Java-Typisierung nicht missen,
> > ich kannte anderes mit Qualen.
> Schlechtes Beispiel. :) Das Scala-Typsystem z.B. ist maechtiger als das
> von Java, und trotzdem muss man da weniger redundanten Kram tippen.

Ich meinte den Clipper-Compiler oder vielleicht Perl,
das werden mehr Leute kennen.

Grüsse
Heiner

Joerg Meier

unread,
Mar 6, 2013, 6:43:08 PM3/6/13
to
On Wed, 6 Mar 2013 08:15:59 -0800 (PST), ma...@heinerkuecker.de wrote:

> Patrick Roemer schrieb:
>> Responding to Heiner Kücker:
>> Danke fuer die Erlaeuterungen!
>>>> aber noch ueberhaupt nicht, wie das konkret im Code aussieht,
>>>> geschweige denn, wie man das in einen Build-Prozess einbauen sollte.
>>> Mit dem Build-Prozess ist das so eine Sache.

>>> Eigentlich sollte generierter Code niemals eingecheckt werden
>>> und bei jedem Build neu gebaut werden.
>> Das ist klar. Ich meinte:

>> - Wie konkret wird der Generator im Buildprozess aufgerufen? Ich hatte
>> zwar gesehen, dass da irgendwo von AbstractConstraintCodeGenerator
>> abgeleitet wurde, dachte aber, dass das eher didaktischen Charakter
>> habe, und dass es da irgendwo noch eine standalone-Mainklasse (oder
>> einen Ant-Task) geben koennte. Hat sich jetzt geklaert.
> Ich habe es immer über den grünen Run-Pfeil
> in der Eclipse gestartet.

Oh je. Nichts fuer ungut, aber das ist als Antwort vielleicht fuer ein
bisschen Langeweile-Coden am Sonntagnachmittag genug, aber nicht fuer ein
auch nur ansatzweise professionelles Projekt.

Mein Tipp: guck Dir mal Lombok an. Da wird auch Code generiert, aber dank
Annotations waerend dem Kompillieren, und dank Eclipse-Integration gibt es
auch keine 'roten Kreuze' oder aehnliche Probleme.

Liebe Gruesse,
Joerg

--
Ich lese meine Emails nicht, replies to Email bleiben also leider
ungelesen.

Patrick Roemer

unread,
Mar 6, 2013, 7:29:55 PM3/6/13
to
Responding to ma...@heinerkuecker.de:
> Patrick Roemer schrieb:
>> Responding to Heiner Kücker:
>
> Warum postest Du eigentlich immer meine Klar-Mail-Adresse,
> ich bekomme ausreichend Spam, ist ok, muss nicht mehr sein.

Weil Dein From-Header einfach nicht mehr hergibt...?

>>> Wenn die Methode abgesichert wurde (Constraint als Parameter
>>> verwendet) findet der Compiler die Aufruf-Stellen.
>>> Dort muss man einfach wiederum das Constraint einsetzen.
>>
>> Genau das wuerde ich aber halt in einem motivierenden Beispiel auch zeigen.
>
> Hm, das wird umfangreich,
> zu umfangreich zum Lesen oder
> alternativ zu wenig,
> schwierig.

Irgendwo musst Du doch eh mal kohaerent dokumentieren, wie eine
Verwendung Deines Tools aussieht. Ich wuerde an Deiner Stelle wirklich
erst mal konkret vorfuehren, worum (und wie!) es geht, und dafuer z.B.
Betrachtungen, welche Implementierungsansaetze nicht zielfuehrend
sind/waren, nach ganz weit hinten im Text verbannen. Aber vielleicht bin
ich auch einfach nicht Zielgruppe. (Ich halte ja auch Podcasts fuer eine
eher ineffiziente Art der Informationsaufnahme.)

Viele Gruesse,
Patrick

ma...@heinerkuecker.de

unread,
Mar 7, 2013, 4:56:52 AM3/7/13
to
Joerg Meier schrieb:
> Oh je. Nichts fuer ungut, aber das ist als Antwort vielleicht fuer ein
> bisschen Langeweile-Coden am Sonntagnachmittag genug, aber nicht fuer ein
> auch nur ansatzweise professionelles Projekt.

Aus meiner Praxis weiß ich, dass professionell
nicht gut bedeutet.

Abhängigkeiten von einem Tool habe ich schon oft,
erlebt, so dass die App nu mit dem WSAD oder
NetBeans zu starten war.
Bei einem Kunden habe die Oracle sogar nach
einem Headless JDeveloper gefragt.

> Mein Tipp: guck Dir mal Lombok an. Da wird auch Code generiert, aber dank
> Annotations waerend dem Kompillieren, und dank Eclipse-Integration gibt es
> auch keine 'roten Kreuze' oder aehnliche Probleme.

Ja, Lombok ist elegant, sicher haben die auch was
für den Build-Prozess, da wird sicher keine
Eclipse-IDE laufen.

Aber Annotations setzen vorhandene Klassen voraus
und Expressions kann man in Annotations nur in
Strings codieren, also ist wieder eine Parser
erforderlich.

Da finde ich die Notation der Expressions
durch statische Methoden mit varargs
leichter.

> Liebe Gruesse,
> Joerg

Grüsse
Heiner

ma...@heinerkuecker.de

unread,
Mar 7, 2013, 5:18:07 AM3/7/13
to
Patrick Roemer schrieb:
> Responding to Heiner Kücker:
> >>> Wenn die Methode abgesichert wurde (Constraint als Parameter
> >>> verwendet) findet der Compiler die Aufruf-Stellen.
> >>> Dort muss man einfach wiederum das Constraint einsetzen.
> >> Genau das wuerde ich aber halt in einem motivierenden Beispiel auch zeigen.
> > Hm, das wird umfangreich,
> > zu umfangreich zum Lesen oder
> > alternativ zu wenig,
> > schwierig.
> Irgendwo musst Du doch eh mal kohaerent dokumentieren, wie eine
> Verwendung Deines Tools aussieht.

http://de.wikipedia.org/wiki/Koh%C3%A4renz

Zitat: Widerspruchsfreiheit einer wissenschaftlichen Aussage mit anderen sachverhaltsbezogenen Aussagen

starker Tobak,

ich arbeite die Info mit dem Konstruktor nach,
aber eigentlich steht schon was unter
'Sicherer und unsicherer Bereich'.

> Ich wuerde an Deiner Stelle wirklich
> erst mal konkret vorfuehren, worum (und wie!) es geht, und dafuer z.B.
> Betrachtungen, welche Implementierungsansaetze nicht zielfuehrend
> sind/waren, nach ganz weit hinten im Text verbannen.

Texte haben meist am Anfang den allgemeinen Teil
und am Ende die konkrete Anleitung/Referenz.

Der Leser will sicher erst mal wissen, was
die Motivation und der grobe Lösungsweg ist.

> Aber vielleicht bin ich auch einfach nicht Zielgruppe.
> (Ich halte ja auch Podcasts fuer eine
> eher ineffiziente Art der Informationsaufnahme.)

Ich hatte jetzt keinen anderen Link zur Hand.
Im Podcast wird über das Problem des Schützens
manuell eingelagerten Codes in generierten
Code gesprochen.

Etwas schwierig ist, wenn Du auf einmal schreibst,
Du meinst interne DSLs, die meist in dynamischen
Sprachen auftauchen, selten in Java (außer
Fluent-Interface oder Builder).

Auch die Argumentation, dass Java sowieso Scheiße
ist und es doch in Scala anders geht, hilft nicht
viel.
Sicher ist der übergreifende Blick notwendig und
mit dem Hinweis auf die Phantom-Typen hast Du mir
sehr geholfen, aber der Code-Generator ist für
Java und die (professionellen) Kunden wollen
leider kaum Scala.

Einen kleinen Code-Generator kann man schon mal
verwenden, aber unerlaubt Scala im Projekt
einzuführen wird wahrscheinlich ein schnelles
Vertragsende bewirken.

Du schriebst auch (ich finde die Stelle jetzt
nicht) dass Du Abhängigkeit des Core-Codes
(ich nehme an Du meinst App-Code) vom
generierten Code nicht magst.

Also, die Situation, dass irgendwann in
meinem Code der Generator generierten
Code zum Starten brauchte
(Aufruf einer constraint-geschützten
Methode in einem Prädikat,
Benutzung von Constraints in einem
Zustandsautomaten, dessen Status in
Prädikaten referenziert werden)
ist schon etwas riskant,
muss man nicht machen.

Das Risiko ist aber nach meiner Meinung
kleiner als die Risiken durch ungeschützten
Code.


> Viele Gruesse,
> Patrick

Schöne Grüße
Heiner

Patrick Roemer

unread,
Mar 7, 2013, 9:24:10 AM3/7/13
to
Responding to ma...@heinerkuecker.de:
> Patrick Roemer schrieb:
>> Responding to Heiner Kücker:
>
>> Irgendwo musst Du doch eh mal kohaerent dokumentieren, wie eine
>> Verwendung Deines Tools aussieht.
>
> http://de.wikipedia.org/wiki/Koh%C3%A4renz
>
> Zitat: Widerspruchsfreiheit einer wissenschaftlichen Aussage mit anderen sachverhaltsbezogenen Aussagen
>
> starker Tobak,

...oder schlicht: "zusammenhaengend".

Beim Text auf Deiner Einfuehrungsseite stellen sich mir Fragen wie:

- Was soll eine Konvertierungsmethode sein?
- Welcher Zwang, eine abstrakte Klasse zu implementieren?
- Was meint er jetzt genau mit Range-Check?
- usw.

Und das wirkt insgesamt auf mich nicht kohaerent - YMMV.

> Texte haben meist am Anfang den allgemeinen Teil
> und am Ende die konkrete Anleitung/Referenz.
>
> Der Leser will sicher erst mal wissen, was
> die Motivation und der grobe Lösungsweg ist.

Eben. Und das weiss ich nach dem Anlesen des Texts nicht - YMMV again.
So ziemlich alle Projektseiten, die ich mir in der letzten Zeit
angeschaut habe, hatten direkt einen "Getting Started"-Absatz oder einen
prominenten Link auf eine entsprechende Seite. Und da war dann
ueblicherweise das von mir erwartete minimale, vollstaendige
Anwendungsbeispiel zu finden.

Inzwischen bin ich mir recht sicher, nicht Zielgruppe fuer dieses
Projekt zu sein, also kann es mir ja egal sein. Aber Du hattest nach
Feedback gefragt, und das sind nun mal meine 2 Cent.

> Etwas schwierig ist, wenn Du auf einmal schreibst,
> Du meinst interne DSLs, die meist in dynamischen
> Sprachen auftauchen, selten in Java (außer
> Fluent-Interface oder Builder).

Du hast DSLs als Beispiel dafuer erwaehnt, dass man Code schreibt, der
direkt von generiertem Code abhaengt, und ich habe beschrieben, warum
mir das sowohl fuer interne wie externe DSLs eher ungewoehnlich erschiene.

> Einen kleinen Code-Generator kann man schon mal
> verwenden, aber unerlaubt Scala im Projekt
> einzuführen wird wahrscheinlich ein schnelles
> Vertragsende bewirken.

Du wirst lachen, aber fuer so enorm halte ich den Unterschied gar nicht:
In beiden Faellen fuehre ich eine zusaetzliche Bibliothek und einen
zusaetzlichen Buildschritt ein, einhergehend mit Code, den mir meine
Kollegen als "vollkommen unleserlich" um die Ohren hauen wuerden. ;)

> Du schriebst auch (ich finde die Stelle jetzt
> nicht) dass Du Abhängigkeit des Core-Codes
> (ich nehme an Du meinst App-Code) vom
> generierten Code nicht magst.
>
> Also, die Situation, dass irgendwann in
> meinem Code der Generator generierten
> Code zum Starten brauchte
> (Aufruf einer constraint-geschützten
> Methode in einem Prädikat,
> Benutzung von Constraints in einem
> Zustandsautomaten, dessen Status in
> Prädikaten referenziert werden)
> ist schon etwas riskant,
> muss man nicht machen.

In Deinem "simple"-Beispiel ist das Package "use" schon abhaengig von
den generierten Constraints.

Aber wir muessen das nicht weiterfuehren. Mein Taesschen Tee ist das
Tool offenkundig nicht, und mein Feedback hast Du. Wenn es Dir geholfen
hat, freut mich das, wenn wir uns nur einig sind, uns nicht einig zu
sein, ist das auch nicht weiter schlimm.

Viele Gruesse,
Patrick

ma...@heinerkuecker.de

unread,
Mar 7, 2013, 11:50:36 AM3/7/13
to
Patrick Roemer schrieb:
> Responding to Heiner Kücker:
> > Patrick Römer schrieb:
> >> Irgendwo musst Du doch eh mal kohaerent dokumentieren, wie eine
> >> Verwendung Deines Tools aussieht.
> Beim Text auf Deiner Einfuehrungsseite stellen sich mir Fragen wie:
> - Was soll eine Konvertierungsmethode sein?

Die Konvertierungsmethoden zur allgemeineren Constraint-Expression
werden automatisch generiert.

Zum Beispiel sind kompatibel

speziellere Expression: A and B
allgemeinere Expression: A

ANDB_A_B_ANDE#convertToAconstraint.

Voraussetzung ist die einfache Implikation:

(A and B) => A

(A and B) => B

Die Konvertierungsmethoden sind die Alternative zur Java-Typ-Kompatibilität
(kompatibel zur Oberklasse/Interface)

Die Java-Typ-Kompatibilität wird nicht genutzt,
weil sich dort kein Ausschluss absichern lässt
(man kann nur was erlauben, nichts verbieten)

Beispiele dafür finden sich im Package

_01_simple

> - Welcher Zwang, eine abstrakte Klasse zu implementieren?

Hier geht es um die Spezialisierung von Constraints.
Um ein Constraint zu spezialisieren muss eine
Switch-Definition vorgenommen werden.

Ein Beispiel dazu findet sich im Package

_05_switch

Anhand der Switch-Definition wird in der
generierten Constraint-Java-Klasse eine
nicht-statische innere Klasse generiert,
welche implementiert werden muss.
Eine abstrakte Klasse ist die einzige
Möglichkeit (die ich kenne) um in Java
die Implementierung jedes Zweiges per
Compiler abzusichern (im Gegensatz zum
Java-Switch oder if-else).

In Scala gibt es dafür sealed case Klassen
oder Option.

Die spezialisierenden Zweig-Expressions dürfen
sich in ihrer erfüllenden boolschen Belegung
(Model) nicht überlappen (müssen disjoint sein),
damit nicht ein zufällig vor einem anderen Zweig
geprüfter Zweig gewinnt.

Werden nicht alle erfüllenden boolschen Belegungen
des ursprünglichen Constraints von den Zweig-Expressions
abgedeckt, wird eine zu implementierende caseDefault-Methode
generiert.

> - Was meint er jetzt genau mit Range-Check?

Das Range-Check-beispiel befindet sich im Package

_12_int_range

Es basiert auf parametrisierbaren Prädikaten
zum Beispiel

new IntLesser ( 0 ) , // x < 0
new IntEqual ( 0 ) , // x == 0
new IntGreater( 0 ) // x > 0

Für die Feststellung der einfachen Implikation
verwende ich die erweiterte Funktionalität
der Includes, DynamicInclude

new IntLesser ( 0 ) => new IntLesser ( 1 )

(x < 0) => (x < 1)

Für die Feststellung des Ausschlusses (Kontradiktion)
verwende ich die erweiterte Funktionalität der
Excludes, DynamicExclude:

Das Symbol für den Exclude ist so ein eingekreistes Plus
(xor) welches ich hier nicht darstellen kann:

new IntLesser ( 0 ) excludes new IntGreater( 0 )

(x < 0) excludes (x> 0)

Eine Anwendung für dieses Feature habe ich nicht,
das sollte sich finden.

> - usw.

Ich freue mich, wenn Du noch ein paar Fragen stellst,
es liest eventuell noch jemand mit.

> > Der Leser will sicher erst mal wissen, was
> > die Motivation und der grobe Lösungsweg ist.
> Eben. Und das weiß ich nach dem Anlesen des Texts nicht.

Ich weiß jetzt auch nicht so genau,
wie ich es besser formulieren soll,
für den gemeinen Java-Programmierer
ist es sicher strange, für die Scala-
und Haskell-Welt eher langweilig.

> So ziemlich alle Projektseiten, die ich mir in der letzten Zeit
> angeschaut habe, hatten direkt einen "Getting Started"-Absatz oder einen
> prominenten Link auf eine entsprechende Seite. Und da war dann
> üblicherweise das von mir erwartete minimale, vollständige
> Anwendungsbeispiel zu finden.

Minimal und vollständig, die Quadratur des Kreises.

> Inzwischen bin ich mir recht sicher, nicht Zielgruppe für dieses
> Projekt zu sein, also kann es mir ja egal sein. Aber Du hattest nach
> Feedback gefragt, und das sind nun mal meine 2 Cent.

Vielen dank für das Feedback, es war bisher das einzige
außer das von dem professionellen Poster.

> > Etwas schwierig ist, wenn Du auf einmal schreibst,
> > Du meinst interne DSLs, die meist in dynamischen
> > Sprachen auftauchen, selten in Java (außer
> > Fluent-Interface oder Builder).
> Du hast DSLs als Beispiel dafuer erwaehnt, dass man Code schreibt, der
> direkt von generiertem Code abhaengt, und ich habe beschrieben, warum
> mir das sowohl für interne wie externe DSLs eher ungewöhnlich erschien.

Aha.

> > Einen kleinen Code-Generator kann man schon mal
> > verwenden, aber unerlaubt Scala im Projekt
> > einzuführen wird wahrscheinlich ein schnelles
> > Vertragsende bewirken.

> Du wirst lachen, aber für so enorm halte ich den Unterschied gar nicht:
> In beiden Fällen fuehre ich eine zusaetzliche Bibliothek und einen
> zusaetzlichen Buildschritt ein, einhergehend mit Code, den mir meine
> Kollegen als "vollkommen unleserlich" um die Ohren hauen wuerden. ;)

In so einem Projekt gibt es technische und fachliche Teamleiter
sowie eine verantwortlichen Kollegen für Build und versionierung.

Das tägliche Bauen erfolgt im Hudson.
Wie soll ich da subversiv (lustig SVN)
einen Scala-Compiler und die Bibliotheken
einschleusen.
Die fühlen sich schon auf den Schlips getreten,
wenn man im util-Package was fixt, ohne dafür
einen Tracker zu haben.

> In Deinem "simple"-Beispiel ist das Package "use"
> schon abhaengig von den generierten Constraints.

Das soll ja auch so sein, anders können
die Constraints auch gar nicht wirken.

> Aber wir müssen das nicht weiterfuehren.

Müssen wir nicht, ich danke Dir für die Hinweise.
Ich wollte aber nicht einfach Dein Posting
unbeantwortet lassen, das wirkt ignorant.

> Mein Tässchen Tee ist das Tool offenkundig nicht,
> und mein Feedback hast Du. Wenn es Dir geholfen hat,
> freut mich das, wenn wir uns nur einig sind, uns nicht einig zu
> sein, ist das auch nicht weiter schlimm.

Vielen Dank, es hat mir geholfen,
wir haben die Meinung oft genug getauscht,
so dass jeder die eigene zurück hat.

ma...@heinerkuecker.de

unread,
Mar 7, 2013, 12:02:52 PM3/7/13
to
> Patrick Römer schrieb:
> > So ziemlich alle Projektseiten, die ich mir in der letzten Zeit
> > angeschaut habe, hatten direkt einen "Getting Started"-Absatz oder einen
> > prominenten Link auf eine entsprechende Seite. Und da war dann
> > üblicherweise das von mir erwartete minimale, vollständige
> > Anwendungsbeispiel zu finden.
> Minimal und vollständig, die Quadratur des Kreises.

Ok, Du meinst das minimale Beispiel,
dieses dann aber vollständig.

Eine richtige App als Beispiel zu schreiben,
ist schon eine Menge Code, den keiner lesen will.

Unit-Test sind kleiner und damit besser geeignet.

Man kann den Code-Generator in kleinen Schritten
an irgendeiner Ecke einer App beginnend einsetzen.

Big-Bang ist nicht notwendig,
es ist kein App-Framework.


Grüsse
Heiner

Patrick Roemer

unread,
Mar 7, 2013, 1:50:16 PM3/7/13
to
Responding to ma...@heinerkuecker.de:
> Patrick Roemer schrieb:
>> Responding to Heiner K锟絚ker:
>> Beim Text auf Deiner Einfuehrungsseite stellen sich mir Fragen wie:
>> - Was soll eine Konvertierungsmethode sein?
[Erlaeuterungen]
> Ich freue mich, wenn Du noch ein paar Fragen stellst,
> es liest eventuell noch jemand mit.

Danke fuer die Erklaerungen. Aber mein Punkt war eher: Diese Fragen
sollten sich beim Lesen eines Einfuehrungstextes gar nicht erst stellen.
Entweder sollten sie an der Stelle, an der ein Begriff eingefuehrt wird,
gleich beantwortet werden, oder man sollte ihn einfach erst mal komplett
weglassen. "Durch den Zwang, eine abstrakte Klasse zu implementieren..."
ist irritierend, wenn ueberhaupt noch nicht gezeigt wurde, wo welche
abstrakte Klasse wozu implementiert werden muss. Ebenso ist "So ein
Feature wie den Range-Check hat nach meiner Kenntnis nicht mal Scala."
IMO nutzlos, wenn der Erstleser ueberhaupt keinen Schimmer haben kann,
was genau ein Range-Check im Kontext dieses Tools ist.

Der Text liest sich fuer mich ein bisschen so, als wende er sich an
jemanden, der das Tool bereits benutzt hat, und sich nun fuer
Motivation, Geschichte und Hintergruende interessiert.

>> > Einen kleinen Code-Generator kann man schon mal
>> > verwenden, aber unerlaubt Scala im Projekt
>> > einzuf锟絟ren wird wahrscheinlich ein schnelles
>> > Vertragsende bewirken.
>
>> Du wirst lachen, aber f锟絩 so enorm halte ich den Unterschied gar nicht:
>> In beiden F锟絣len fuehre ich eine zusaetzliche Bibliothek und einen
>> zusaetzlichen Buildschritt ein, einhergehend mit Code, den mir meine
>> Kollegen als "vollkommen unleserlich" um die Ohren hauen wuerden. ;)
>
> In so einem Projekt gibt es technische und fachliche Teamleiter
> sowie eine verantwortlichen Kollegen f锟絩 Build und versionierung.
>
> Das t锟絞liche Bauen erfolgt im Hudson.
> Wie soll ich da subversiv (lustig SVN)
> einen Scala-Compiler und die Bibliotheken
> einschleusen.

Ich gehe davon aus, dass alle Schritte vom Buildsystem ausgefuehrt
werden sollten, und dass alle dazu benoetigten Ressourcen im Repo sind.
Dazu muessten das Generator-Jar und die spezialisierte Generatorklasse
im Repo landen und die Generierung als Target im Buildscript auftauchen.
Scala in einen Build einzubauen erfordert grundsaetzlich auch nicht
mehr, schliesslich sind Compiler und Runtime auch nur Jars.

Wenn Du hingegen die Generierung lokal in Deinem Eclipse ausfuehrst und
nur die Resultate eincheckst, akkumulierst Du "Herrschaftswissen", und
ein beliebiger Kollege kann den Code und den Build ggfs. nicht genauso
warten wie Du.

Viele Gruesse,
Patrick

ma...@heinerkuecker.de

unread,
Mar 7, 2013, 1:53:22 PM3/7/13
to
> > > Patrick Römer schrieb:
> > > Der Leser will sicher erst mal wissen, was
> > > die Motivation und der grobe Lösungsweg ist.
> > Eben. Und das weiß ich nach dem Anlesen des Texts nicht.
> Heiner schrieb:
> Ich weiß jetzt auch nicht so genau,
> wie ich es besser formulieren soll,
> für den gemeinen Java-Programmierer
> ist es sicher strange, für die Scala-
> und Haskell-Welt eher langweilig.

Nun habe ich noch mal Luft geholt,
also was soll das ganze eigentlich.

Also erst mal geht es um Design by contract

http://de.wikipedia.org/wiki/Design_by_contract

Ok, ich kümmere mich nur um Vorbedingungen,
Nachbedingungen und Klassen-Invarianten
ignoriere ich erst mal.

Ein Problem dabei ist, dass die Vorbedingungen
durch einen Test ins leben gebracht werden
müssen, es soll ja nicht erst in der Produktion
knallen.

Nehmen wir als Beispiel eine Methode mit einem
int-Parameter, der als Array-Index dient.

public void arrayAccess(
final int index )
{
...

Klar, dass dieser int-Wert nicht negativ sein darf.

In Java kann man keine eigenen primitiven Typen
deklarieren, also muss man eine Klasse verwenden.

public final class NonNegativeInt
{
final int value;

public NonNegativeInt(
final int value )
{
if ( value < 0 )
{
throw new IllealArgumentException(
"value lesser zero: " + value );
}
this.value = value;
}
}


Diese Klasse verwenden wir jetzt als Parameter-Typ

public void arrayAccess(
final NonNegativeInt index )
{
...

Dies wirkt viral, an allen Aufruf-Stellen
muss nun die Klasse NonNegativeInt übergeben
werden.

Meine generierten Constraints funktionieren
genauso, bieten aber noch einiges mehr an
Infrastruktur.



Der andere Ansatz war meine damals gepflegte
Anwendung (siehe im Text 'Das verfluchte if').

Die Anwendung bildete einen Business-Process
(Workflow) mit Rollen, fachlichen Entitäten
mit jeweils einem bestimmten Status ab.

Es war ein Wald von if-else-Verteilern.

Da es noch Fehler gab (wahrscheinlich war
die Fachabteilung nach einem Jahr
rumpfriemeln einfach froh, dass überhaupt
was funktioniert hat) habe ich den letzten
else-Zweig mit einer Exception abgesichert.

}
else
{
throw new UnreachableException();
}

Diese Technik habe ich bereits in den 80er-Jahren
beigebracht bekommen.

Eine Aktion an einer fachlichen Entität setzte
voraus, dass der aktuelle Benutzer die Entität
in ihrem aktuellen Status überhaupt sehen darf,
dass der Status der fachlichen Entität die
Aktion erlaubt und dass die Rolle und
Nebeninformationen(Abteilungsnummer)
die Aktion erlauben.

(HasPermission and Status and Role)

Für eine Aktion gab es eine Fassaden-Methode.

Diese Fassaden-Methode muss erst mal die
fachliche Entität aus der Datenbank
laden.

Die Lade-Methode benötigt nur die Absicherung
der Berechtigung zum Sehen der fachlichen Entität.

Hier wirkt die einfache Implikation
(Konvertierungs-Methode).

Manche Fassaden-Methoden enthielten eine
if-else-Kaskade nach der Rolle des
Benutzers, die Fassaden-Methode wurde
mehrfach verwendet.

Mit dem AbstractSwitch konnte ich die
else-Zweige mit der UnreachableException
loswerden, alle möglichen Zweige
mussten ausimplementiert sein.

Wenn ich die verschiedenen if-else-Kaskaden
mal den Entscheidungskern nenne, so war
dieser dann komplett über den Compiler
abgesichert, dass jeder mögliche Zweig
implementiert war und jede Methode mit der
korrekten Berechtigung aufgerufen wurde,
ohne dass dieser Entscheidungskern über
Depency-Injection/Mocking testbar
gemacht werden musste.

Includes und Excludes sind Schreibvereinfachungen.

Dann habe ich mich noch ein wenig mit der
closed world assumption herumgeschlagen.

Das war es schon.

Grüsse
Heiner
Message has been deleted

Heiner Kücker

unread,
Mar 7, 2013, 2:49:54 PM3/7/13
to
Heiner Kücker schrieb:
> Ein Problem dabei ist, dass die Vorbedingungen
> durch einen Test ins Leben gebracht werden
> müssen, es soll ja nicht erst in der Produktion
> knallen.
>
>
>
> Nehmen wir als Beispiel eine Methode mit einem
> int-Parameter, der als Array-Index dient.
>
> public void arrayAccess(
> final int index )
> {
> ...
>
> Klar, dass dieser int-Wert nicht negativ sein darf.

Nun wäre es schön, wenn der Compiler mithelfen würde,
Code-Stellen zu finden, an denen negative Werte
an diese Methode übergeben werden.
habe ich den letzten else-zweig in diesen
if-else-Kaskaden mit einer Exception
abgesichert:

Meine Vorgänger (ich hatte meist weiniger
schmeichelhafte Bezeichnungen für diese
Herrschaften) arbeiteten mit üblen
imperativen Tricks,

Variable initialsieren,
in irgendwelchen if-Zweigen überschreiben,
wenn kein if-zweig zutraf war es irgendein
unklarer Default oder einfach ein Fehler.
Ich habe auch ein wenig in den Bereich
SAT-Solver hineingerochen, im Code findet
man auch Methoden, um Klammern in boolschen
Expressions auszumultiplizieren, De Morgan,
BruteForce-Solver, einfache Implikation,
Äquivalenz und Kontradiktion.

Durch die Excludes können Expressions
äquivalent sein, die keine gemeinsamen
Prädikate haben:

Exclude-Group

A
B
C

not( A ) <=> (B or C)

Das hat schon ein paar Stunden gekostet.

> Grüsse
> Heiner

Heiner Kücker

unread,
Mar 9, 2013, 10:01:44 AM3/9/13
to
Patrick Roemer schrieb:
>Das Scala-Typsystem ist turing-vollstaendig. Damit gehen auch so Scherze
>wie eine Berechnung der Loesung fuer Towers of Hanoi zur Compilezeit[1],
>oder ein TicTacToe-Spiel, bei dem ungueltige Zuege ein Compilerfehler
>sind[2]. Das ist aber auch fuer Scala schon ziemlich esoterisch.

Ich habe das Beispiel mit dem Tic Tac Toe
in den Code mit aufgenommen.

Package

_14_transform_safeoperation_tic_tac_toe

Wie man sieht, benötigt man mit meinem Code-Generator
erheblich mehr Code als mit den Scala-Phantom-Types,
weil jede benutzte Klasse auch wirklich generiert
werden muss.

Wahrscheinlich ist man mit diesem Beispiel schon
an der Grenze dessen, was man mit dem Code-Generator
sinnvoll machen kann.

Eine Möglichkeit wäre, den Code-Generator
per Script zu treiben, also alle notwendigen
Permutationen/Kombinationen generieren zu
lassen.

Das kann aber schnell zur kombinatorischen
Explosion führen, es werden tausende
Klassen generiert.

In einer frühen Phase des jetzigen
Code-Generators hatte ich dieses Problem
bereits.

Ein Gedankenspiel wäre, die erforderlichen
Klassen on demand generieren zu lassen.

Dazu müsste man dem Compiler ein
virtuelles Datei-System vorgauckeln,
welches die Java-Constraint-Dateien
bei Bedarf liefert.

Zur Laufzeit bräuchte man einen
ClassLoader, hinter dem der Code-Generator
mit einem on the fly compiler steckt.

Heinz Kabutz hat einiges geschrieben,
wie man so was machen kann.

Aber wie man es konkret machen könnte,
weiß ich auch nicht.


Grüße
Heiner

Heiner Kücker

unread,
Mar 10, 2013, 9:21:37 AM3/10/13
to
Scheinbar sind andere Leute auf ähnliche Ideen wie ich gekommen,
meist verwenden diese aber OCL als Notation:


https://www.google.de/webhp?q=constraint+code+generator+java


http://www.amazon.de/Building-OCL-Code-Generator-Java/dp/3843385386/ref=sr_1_cc_1?s=aps&ie=UTF8&qid=1362921398&sr=1-1-catcorr


Grüße
Heiner

Jochen Theodorou

unread,
Mar 11, 2013, 9:09:03 AM3/11/13
to
Am 01.03.2013 15:55, schrieb ma...@heinerkuecker.de:
> Hallo Java-Freunde,
>
> ich habe meinen vor langer Zeit (März 2012) veröffentlichten
> Constraint Code Generator weiterentwickelt.
>
> Die URL für den Download lautet
>
> http://heinerkuecker.de/ConstraintCodeGenerator.html


Da es ja im Prinzip im Contracts geht, wie vergleichen sich
https://github.com/andresteingress/gcontracts/wiki und dein Projekt?
Natürlich abgesehen davon, dass ersteres für Groovy und nicht für Java ist.

Gruss theo

--
Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
blog: http://blackdragsview.blogspot.com/
german groovy discussion newsgroup: de.comp.lang.misc
For Groovy programming sources visit http://groovy-lang.org

Heiner Kücker

unread,
Mar 11, 2013, 10:25:35 AM3/11/13
to
Jochen Theodorou schrieb:
> Da es ja im Prinzip im Contracts geht, wie vergleichen sich
> https://github.com/andresteingress/gcontracts/wiki und dein Projekt?
> Natürlich abgesehen davon, dass ersteres für Groovy und nicht für Java ist.

Ja, ich adressiere nur Java, prinzipiell könnte man den
Code-Generator aber auch auf andere Sprachen umstellen.


Zitat aus dem von Dir angegebenen Link

@Invariant({ speed() >= 0 })


Aha, Groovy-Annotationen können Ausdrücke,
das können Java--Annotationen nicht
(nur String, Primitive, Klassen und Enums).

Also prinzipiell will ich den Compiler zum
Prüfen der Constraints einsetzen, die
Runtime-Exception ist nur Nebensache.

Für mein Framework ist eine compiler-geprüfte
Sprache notwendig (sonst gibt es nur die
Laufzeit-Wirkung).

Es sollte doch mal ein voll compiliertes
Groovy geben?

Ich vergleiche mal die Features

- definition of class invariants, pre- and post-conditions

Mich haben nur die Pre-Conditions interessiert,
und da auch nur die Parameter.

Wenn die generierten Constraints als Member
einers Klasse verwendet werden, kann man auch
Invarianten machen.

Constraints als Return-Typen wären Post-Konditionen.

-inheritance of class invariants, pre- and post-conditions

Da meine Constraints Methoden-Parameter sind
(bzw Klassen-Member) klappt es mit der Vererbung
sowieso.


-inheritance of class invariants, pre- and post-conditions in implemented interfaces

Hier gilt das Gleiche


-usage of old and result variable in post-condition assertions

Hierfür habe ich nichts

-custom implementation of the Groovydoc Ant task to generate Javadocs with contract information

Meine Constraints sollten auch in einer
Javadoc auftauchen.

-assertion injection in Plain Old Groovy Objects (POGOs)

Habe ich nicht.

-human-readable assertion messages, based on Groovy power asserts

Das ist ein offener Punkt,
dafür sind BoolStrTupel geplant.

-enabling contracts at package- or class-level with @AssertionsEnabled

Gibt es bei mir nicht.

-enable or disable contract checking with Java’s -ea and -da VM parameters

Habe ich nicht (finde ich auch nicht sinnvoll)

-annotation contracts: a way to reuse reappearing contract elements in a project domain model

Dafür habe ich auch nichts

-detection of circular assertion method calls

Habe ich nicht.

-multi-module Gradle projcet

Nicht meine Baustelle.



Das besondere an meiner Idee sind die
Prädikate (einfach Java, damit steht aber
auch der komplette Java-Sprachumfang zur
Verfügung).

Des weiteren die Definition von
Constraints als boolesche Expressions
aus Prädikaten.

Die Ablehnung der Java-Typ-Kompatibilität,
weil dort kein Ausschluss (Not)
möglich ist, statt dessen Konvertierungs-Methoden.

Die Spezialisierung von Constraints in
abstrakten Switch-Klassen als Alternative
zum verfluchten ungeprüften if
(sowie if-else-Kaskaden).

Includes und Excludes.

Ganz besonders ist aber die Prüfung
zur Compile-Zeit, um Code ohne
Tests absichern zu können
(Nachteile des Testens sind der
Zwang zum testbar machen
(depency injection, mocking) und
die kombinatorische Explosion.

> Gruss theo
> --
> Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
> blog: http://blackdragsview.blogspot.com/
> german groovy discussion newsgroup: de.comp.lang.misc
> For Groovy programming sources visit http://groovy-lang.org

Grüsse
Heiner

Jochen Theodorou

unread,
Mar 11, 2013, 12:24:31 PM3/11/13
to
Am 11.03.2013 15:25, schrieb Heiner K�cker:
[...]
> @Invariant({ speed() >= 0 })
>
> Aha, Groovy-Annotationen k�nnen Ausdr�cke,
> das k�nnen Java--Annotationen nicht
> (nur String, Primitive, Klassen und Enums).

Nunja, Groovy-Annotation sind da eigentlich nicht anders, weil es sind
eigentlich genau die gleichen wie f�r Java, da dies auf VM-Ebene sicher
gestellt wird. Was passiert ist dass f�r diesen Ausdruck eine Klasse
erzeugt wird und die Klasse dann refereziert wird. Ist ein bischen eine
Trickserei, funktioniert aber eigentlich ganz gut.

[...]
> Es sollte doch mal ein voll compiliertes Groovy geben?

Groovy ist immer voll kompiliert. Du meinst sicher mit statischen
Typisierung ;) Es gibt erste Ans�tze eines statischen Compilers, samt
Erweiterungsm�glichkeiten.

[...]
> Ganz besonders ist aber die Pr�fung
> zur Compile-Zeit, um Code ohne
> Tests absichern zu k�nnen
> (Nachteile des Testens sind der
> Zwang zum testbar machen
> (depency injection, mocking) und
> die kombinatorische Explosion.

Nunja.... angenommen du hast eine Methode foo(x) und x sei ein int und
soll immer im Bereich 0..5 sein. Und jetzt hast du sowas:

while (condition()) {
int i = System.nanoTime() % 5;
foo(i)
}

wird da jetzt dein Constraint Code Generator meckern?

Heiner Kücker

unread,
Mar 11, 2013, 1:19:07 PM3/11/13
to
Jochen Theodorou schrieb:
> > Aha, Groovy-Annotationen können Ausdrücke,
> > das können Java--Annotationen nicht
> > (nur String, Primitive, Klassen und Enums).
>
> Nunja, Groovy-Annotation sind da eigentlich nicht anders, weil es sind
> eigentlich genau die gleichen wie für Java, da dies auf VM-Ebene sicher
> gestellt wird. Was passiert ist dass für diesen Ausdruck eine Klasse
> erzeugt wird und die Klasse dann referenziert wird. Ist ein bischen eine
> Trickserei, funktioniert aber eigentlich ganz gut.

Aha, Klasse.

> > Es sollte doch mal ein voll compiliertes Groovy geben?
> Groovy ist immer voll kompiliert. Du meinst sicher mit statischen
> Typisierung ;) Es gibt erste Ansätze eines statischen Compilers, samt
> Erweiterungsmöglichkeiten.

Du hast es erfasst, ich hatte mich nicht genau ausgedrückt.

> > Ganz besonders ist aber die Prüfung
> > zur Compile-Zeit, um Code ohne
> > Tests absichern zu können
> > (Nachteile des Testens sind der
> > Zwang zum testbar machen
> > (depency injection, mocking) und
> > die kombinatorische Explosion.
>
> Nunja.... angenommen du hast eine Methode foo(x) und x sei ein int und
> soll immer im Bereich 0..5 sein. Und jetzt hast du sowas:
>
> while (condition()) {
> int i = System.nanoTime() % 5;
> foo(i)
> }
>
> wird da jetzt dein Constraint Code Generator meckern?

Beispiele sind mir immer willkommen:

Ich würde die foo-Methode mit einem Constraint schützen
(siehe Beispiel-Package _07_int_range)

public void foo(
final IntLesser5Constraint iConstraint )
{
...

Die Schleife sähe dann so aus:

while ( condition() ) {
final IntLesser5Constraint iConstraint =
new IntLesser5Constraint(
System.nanoTime() % 5 );

foo( iConstraint );
}


Das Constraint an der foo-Methode ist
damit compiler-geprüft und dokumentiert
(da die Aufruf-Stelle foo() und die
Definitions-Stelle der Methode foo
immer eine bestimmte Entfernung hat
(andere Zeile, Datei) hilft das schon)


Noch witziger wäre der Schutz der
Modulo-Operation


Constraint:
LongConstraint

(ein Integer, keine weitere Prüfung)

sichere Operation:
Modulo

(Return-Type wäre die Instanz einer
sicheren Operation mit einem
Int-Parameter)

Dann sähe die Schleife etwa so aus:

while ( condition() ) {
final IntLesser5Constraint iConstraint =
new LongConstraint(
System.nanoTime() ).
// der Name der generierten Methode ist in der
// Definition der sicheren Operation festgelegt,
// der Wert 5 ist konstant und kann daher dem
// Code-Generator mitgeteilt werden
modulo5();

foo( iConstraint );
}


Ich finde das Beispiel gut und werde es
in den Beispiel-Code aufnehmen.

Der Sinn hält sich in Grenzen, weil die Operation

long % 5

lokal(bezogen auf Quellcode-Entfernung)
leicht zu überblicken ist.

Wenn sich die Zusammenhänge über weite
Quellcode-Entfernung erstrecken, ist
Compiler-Hilfe willkommen.

Ich werde es wahrscheinlich erst morgen oder
übermorgen(am Mittwoch) hochladen, weil ich
immer naoch am Tic Tac Toe rumpfriemele
(dynamische sichere Operationen)

Aufgrund der kombinatorischen Explosion
( 3 ^ 9 Stellungen) dauert das.
Ich habe ein paar fiese tricks zur
Beschleunigung eingebaut, nur für mich
lokal, nichts zum Tausgeben.

>Gruss theo
>--
>Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
>blog: http://blackdragsview.blogspot.com/
>german groovy discussion newsgroup: de.comp.lang.misc
>For Groovy programming sources visit http://groovy-lang.org

Gruss und vielen Dank
Heiner

Heiner Kücker

unread,
Mar 11, 2013, 1:22:56 PM3/11/13
to
Heiner Kücker verbrach:
> Constraint:
> LongConstraint
>
> (ein Integer, keine weitere Prüfung)

natürlich Long nicht Integer

Jochen Theodorou

unread,
Mar 13, 2013, 7:07:08 AM3/13/13
to
Am 11.03.2013 18:19, schrieb Heiner K�cker:
> Jochen Theodorou schrieb:
[...]
> Ich w�rde die foo-Methode mit einem Constraint sch�tzen
> (siehe Beispiel-Package _07_int_range)
>
> public void foo(
> final IntLesser5Constraint iConstraint )
> {
> ...
>
> Die Schleife s�he dann so aus:
>
> while ( condition() ) {
> final IntLesser5Constraint iConstraint =
> new IntLesser5Constraint(
> System.nanoTime() % 5 );
>
> foo( iConstraint );
> }
>
>
> Das Constraint an der foo-Methode ist
> damit compiler-gepr�ft und dokumentiert

aber was genau pr�ft da der Compiler? Wenn ich statt %5 einfach %6
schreibe wird das doch noch immer compilieren, oder? So stellst du zwar
sicher dass foo nur was in 0..5 bekommt, aber beim Erzeugen des
Constraint verl�sst du dich wieder auf Laufzeitpr�fungen... bzw. wenn
ich richtig verstanden habe was du zuvor sagtest, dann wird die �nderung
einfach akzeptiert werden, obwohl sie falsch ist, weil du ja keine
Laufzeitpr�fungen machen willst. Das heisst, um das wirklich korrekt zu
haben, *musst* du den Modulo pr�fen.

[...]
> Dann s�he die Schleife etwa so aus:
>
> while ( condition() ) {
> final IntLesser5Constraint iConstraint =
> new LongConstraint(
> System.nanoTime() ).
> // der Name der generierten Methode ist in der
> // Definition der sicheren Operation festgelegt,
> // der Wert 5 ist konstant und kann daher dem
> // Code-Generator mitgeteilt werden
> modulo5();
>
> foo( iConstraint );
> }

und das ist dann was ich in den Code schreibe?

> Ich finde das Beispiel gut und werde es
> in den Beispiel-Code aufnehmen.
>
> Der Sinn h�lt sich in Grenzen, weil die Operation
>
> long % 5
>
> lokal(bezogen auf Quellcode-Entfernung)
> leicht zu �berblicken ist.
>
> Wenn sich die Zusammenh�nge �ber weite
> Quellcode-Entfernung erstrecken, ist
> Compiler-Hilfe willkommen.

stell dir vor der Wert 5 kommt aus einer anderen Methode... wie s�he es
dann aus, und wie stellst du sicher, dass die Methode dann nicht zum
Beispiel 6 zur�ck gibt?

Heiner Kücker

unread,
Mar 13, 2013, 9:28:03 AM3/13/13
to
Jochen Theodorou schrieb:
> Am 11.03.2013 18:19, schrieb Heiner K�cker:
> > Jochen Theodorou schrieb:
> [...]
> > Ich w�rde die foo-Methode mit einem Constraint sch�tzen
> > (siehe Beispiel-Package _07_int_range)
> >
> > public void foo(
> > final IntLesser5Constraint iConstraint )
> > {
> > ...
> >
> > Die Schleife s�he dann so aus:
> >
> > while ( condition() ) {
> > final IntLesser5Constraint iConstraint =
> > new IntLesser5Constraint(
> > System.nanoTime() % 5 );
> >
> > foo( iConstraint );
> > }
> >
> >
> > Das Constraint an der foo-Methode ist
> > damit compiler-gepr�ft und dokumentiert
> aber was genau pr�ft da der Compiler?

Es geht um den von mir verwendeten Begriff
der Quellcode-Entfernung.
Dieser Begriff ist nicht wissenschaftlich,
ergonomisch fundiert, ich ahne aber, dass
es so was gibt.

Die Verwendungsstelle der Methode foo
(der Aufruf) und die Definitionsstelle
sind endlich weit voneinander entfernt.

Ein int-Parameter enthält nicht die
Semantik, Bedingung x < 5 (&& x >= 0).

Die generierte und verwendet Constraint-
Java-Klasse prüft (im Konstruktor) und
dokumentiert die oben genannte Bedingung.

> Wenn ich statt %5 einfach %6
> schreibe wird das doch noch immer compilieren, oder?

Ja, aber die Exception tritt an der
Verursacherstelle(Aufruf) auf und nicht
erst in der Methode foor.

> So stellst du zwar
> sicher dass foo nur was in 0..5 bekommt, aber beim Erzeugen des
> Constraint verl�sst du dich wieder auf Laufzeitpr�fungen...

Ja, richtig, hat alles seine Grenzen,
entweder man erzeugt das Constraint literal

public static final IntLesser5Constraint iConstraint =
new IntLesser5Constraint( ...

oder

es entsteht aus einem unbekannten(ungeprüften) Wert.

> bzw. wenn
> ich richtig verstanden habe was du zuvor sagtest, dann wird die �nderung
> einfach akzeptiert werden, obwohl sie falsch ist, weil du ja keine
> Laufzeitpr�fungen machen willst.

Doch, die Prüfung erfolgt im Konstruktor des Constraints.

> Das heisst, um das wirklich korrekt zu
> haben, *musst* du den Modulo pr�fen.

Das wäre die sichere Operation,
wie in meinem Code-Beispiel oben.

Um die Operation zu prüfen, muss
man die Semantik kennen, also
ob hier ein Modulo überhaupt
richtig ist.

Wenn man die sichere Operation
generiert, muss man sich darauf
verlassen können, daß die Operation
der Spezifikation entspricht
(hier überhaupt richtig ist)
und daß die Definitions-Klasse
der sicheren Operation, aus welcher
der Constraint-Code generiert
wird, korrekt ist.

> [...]
> > Dann s�he die Schleife etwa so aus:
> >
> > while ( condition() ) {
> > final IntLesser5Constraint iConstraint =
> > new LongConstraint(
> > System.nanoTime() ).
> > // der Name der generierten Methode ist in der
> > // Definition der sicheren Operation festgelegt,
> > // der Wert 5 ist konstant und kann daher dem
> > // Code-Generator mitgeteilt werden
> > modulo5();
> >
> > foo( iConstraint );
> > }

> und das ist dann was ich in den Code schreibe?

Ja, ist eben in Java etwas umständlich.

> > Ich finde das Beispiel gut und werde es
> > in den Beispiel-Code aufnehmen.
> >
> > Der Sinn h�lt sich in Grenzen, weil die Operation
> >
> > long % 5
> >
> > lokal(bezogen auf Quellcode-Entfernung)
> > leicht zu �berblicken ist.
> >
> > Wenn sich die Zusammenh�nge �ber weite
> > Quellcode-Entfernung erstrecken, ist
> > Compiler-Hilfe willkommen.
>
> stell dir vor der Wert 5 kommt aus einer anderen Methode...
> wie s�he es dann aus, und wie stellst du sicher, dass
> die Methode dann nicht zum Beispiel 6 zur�ck gibt?

Wenn der Wert als int aus einer anderen
Methode kommt, muss er an der Aufrufstelle
in das Constraint verpackt werden.

Besser wäre natürlich, die andere Methode
gäbe bereits das Constraint zurück,
wäre somit abgesichert (virale Wirkung
des Compilers).

> Gruss theo
> --
> Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
> blog: http://blackdragsview.blogspot.com/
> german groovy discussion newsgroup: de.comp.lang.misc
> For Groovy programming sources visit http://groovy-lang.org

Grüße
Heiner

Heiner Kücker

unread,
Mar 19, 2013, 5:48:30 AM3/19/13
to
Heiner Kücker schrieb:
> Hallo Java-Freunde,
> ich habe meinen vor langer Zeit (März 2012) veröffentlichten Constraint Code Generator weiterentwickelt.
>
> Die URL für den Download lautet
>
> http://heinerkuecker.de/ConstraintCodeGenerator.html
>
> Falls jemand mehr darüber erfahren will, kann derjenige das auf den Stuttgarter Testtagen am 22.03.2013.
>
> http://www.jugs.org/tt2013/abstracts.html#link07
>
> Im Kaffeeklatsch ist dazu heute ein Artikel erschienen:
>
> http://www.bookware.de/kaffeeklatsch/archiv
>
> Das aktuelle Heft ist erst im Folgemonat im Archiv, für das aktuelle Heft dieses Monates muss man sich anmelden.
>
> Der Artikel-Text ist aber als ASCII im Zip enthalten.

Gestern war das aktuelle Eclipse-Magazin in der Post

http://it-republik.de/jaxenter/eclipse-magazin-ausgaben/Eclipse-%26-ALM-000543.html

Darin ist ein Artikel über das Constraint-Framework C4J.

http://c4j-team.github.com/C4J/

Ich möchte die Eigenschaften dieser Lösung
kurz mit meinem Constraint-Code-Generator
vergleichen:

-Contracts consist of preconditions and postconditions,
which are systematically defined method by method.

Mein Code-Generator kümmert sich hautsächich
um Pre-Conditions, Post-Conditions kann man
über die Rückgabe von Constraints und über
die Benutzung von Constraints als Member
nachbilden, ist aber nicht optimal.

-The class invariant ensures the DRY principle
(Don't Repeat Yourself) for contracts by defining all
those assertions, which must be fulfilled at any
visible state of an object, only once.

Wie oben, man kann die generierten
Constraint-Java-Klassen als Member
benutzen, ist aber nicht optimal.

-Contracts can be linked to classes and interfaces.

Das sollte selbstverständlich sein.

-Contracts are inherited by extending a class or
by implementing an interface which is guarded
by a contract.

Durch die Benutzung der generierten
Constraint-Java-Klassen als Parameter
ist dies abgesichert.

-To be able to define meaningful contracts you are
forced to split lengthy methods into small,
well defined, methods with a single responsibility.

Wohl mehr ein Hinweis als ein Feature.

-As your contracts are checked at runtime,
your classes are validated against the real
usage of your application, not against some
test cases that may not even be real use cases.

Das sollte selbstverständlich sein.

-If you are dealing with legacy code that you
are afraid of refactoring, external contracts
are perfect to add to existing code with no risk
involved.

Keine Ahnung, warum beim Refactoring Angst
vor dem Ändern von Code haben sollte,
was soll das externe Hinzufügen?

-checking constraints at compile time

Nun, das kann nur mein Ding.

-define constraints as expressions of java predicates

Dieses Feature hat meine Lösung.

Viel Spass beim Lesen Eures Eclipse-Magazins.

Grüße
Heiner

Heiner Kücker

unread,
Mar 20, 2013, 5:58:44 PM3/20/13
to
Heiner Kücker schrieb:
> Ich finde das Beispiel gut und werde es
> in den Beispiel-Code aufnehmen.

Leider habe ich es noch nicht geschafft,
das Modulo-Beispiel in den Code einzubauen.

Wahrscheinlich klappt es nächste Woche,
bis dahin sehen wir uns eventuell in
Stuttgart zu den Testtagen 2013

http://www.jugs.org/tt2013/abstracts.html#link07

Jochen Theodorou

unread,
Mar 21, 2013, 1:56:52 AM3/21/13
to
Am 20.03.2013 22:58, schrieb Heiner K�cker:
> Heiner K�cker schrieb:
>> Ich finde das Beispiel gut und werde es
>> in den Beispiel-Code aufnehmen.
>
> Leider habe ich es noch nicht geschafft,
> das Modulo-Beispiel in den Code einzubauen.
>
> Wahrscheinlich klappt es n�chste Woche,
> bis dahin sehen wir uns eventuell in
> Stuttgart zu den Testtagen 2013
>
> http://www.jugs.org/tt2013/abstracts.html#link07


w�re ich gerne hingegangen, aber hab aus famili�ren Gr�nden keine Zeit

Heiner Kücker

unread,
Mar 30, 2013, 7:06:05 AM3/30/13
to
Jochen Theodorou schrieb:
> Am 20.03.2013 22:58, schrieb Heiner K�cker:
> > Heiner K�cker schrieb:
> >> Ich finde das Beispiel gut und werde es
> >> in den Beispiel-Code aufnehmen.
> >
> > Leider habe ich es noch nicht geschafft,
> > das Modulo-Beispiel in den Code einzubauen.
> >
> > Wahrscheinlich klappt es n�chste Woche,
> > bis dahin sehen wir uns eventuell in
> > Stuttgart zu den Testtagen 2013
> >
> > http://www.jugs.org/tt2013/abstracts.html#link07
>
>
> wäre ich gerne hingegangen, aber hab aus familiären Gründen keine Zeit
>

Schade, da hätte man sich mal ohne die lästige Tipperei
unterhalten können.

Das Modulo-Beispiel ist jetzt fertig.

Es befindet im Zip auf

http://www.heinerkuecker.de/ConstraintCodeGenerator.html

im Verzeichnis

12_OTHER_SAFEOPERATION_INT_LONG_RANGE

>
> Gruss theo
> --
> Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
> blog: http://blackdragsview.blogspot.com/
> german groovy discussion newsgroup: de.comp.lang.misc
> For Groovy programming sources visit http://groovy-lang.org

Gruesse
Heiner

Heiner Kücker

unread,
Nov 3, 2013, 5:21:49 AM11/3/13
to
Hier noch mal ein Update,

beim letzten Upload des Projektes habe ich noch eine Möglichkeit zum Scannen des zu instrumentierenden Quellcodes auf qualifizierte Kommentare mit Constraint-Expressions eingebaut.

Dazu allgemeines Bugfixing und Performance-Tuning sowie Verbesserungen an den Beispielen/Übungen.

Am 07.11.2013 gibt es noch einen Vortrag von mir

http://www.qs-tag.de/abstracts/constraints-design-by-contract-aber-mit-compiler-pruefung/

Gruesse
Heiner
http://heinerkuecker.de/ConstraintCodeGenerator.html

Heiner Kücker

unread,
Aug 30, 2014, 7:32:39 AM8/30/14
to
Am 02.09.2014 gibt es zu diesem Thema einen Vortrag von mir in Nürnberg

http://www.herbstcampus.de/hc14/program/sessions.html#57

http://www.herbstcampus.de/hc14/program/speakers.html#R57

Morgen lade ich den aktuellen Stand
einschließlich Vortragsfolien
auf meiner Webseite hoch:

http://heinerkuecker.de/ConstraintCodeGenerator.html

Es gibt ein paar neue Features:

Integration der totalen Ordnung
(ist-gleich, kleiner-als, grösser-als)
für diskrete Werte
(int, long, short, enums)

Ein Beispiel-Projekt zur
Demonstration von Constraints
zum Vermeiden von int-Überläufen
zur Compile-Zeit.

Ein weiteres Beispiel-Projekt
zur Demonstration von Constraints
zum Vermeiden von Division
durch 0 zur Compile-Zeit.

Beide Projekte basieren auf
sicheren Operationen,
welche sozusagen eine
Realisierung des Hoare-Kalküls
sind.

Zur Zeit wird nur vorwärts
geschlossen, so dass bei
Zahlenbereichsverletzung
die vorher-Constraints
manuell angepasst werden
müssen.

Demnächst (irgendwann)
baue ich rückwärts Schliessen
ein.
Dann wird nur das Ziel-Constraint
(konstant Überlauf sowie
Division durch 0 vermeiden)
und die Operation festgelegt
und das passende
Ursprungs-Constraint
automatisch generiert.

Totale Ordnung für kontinuierliche
Werte (float, double, BigDecimal)
gibt es noch nicht.


Gruesse
Heiner Kücker
0 new messages