XML als CodeP

Wie bemerke ich, dass die ausserordentlich wichtige Datei xyz nicht vorhanden ist? Wie bemerke ich, dass eine andere Datei ABC heute nicht neu erzeugt wurde? Wie bemerke ich, dass sich ein Wert in einer SQL-Datenbank ändert? Diese und ähnlich Fragen stellen sich immer wieder.

SCOM könnte hier Antworten geben und die Aufgabe fiele daher in den Beritt der Kollegen von der Systemtruppe. Aber mein Chef möchte kurze Wege: Hausinterne Programme erzeugen und verändern Dateien. Also kümmert sich das Programmier-Team um deren Überwachung.

Skizze
Meine Idee dazu ist die: Ich schaffe eine Java-Klasse, die prüfen kann, ob eine Datei existiert. Für n Prüfungen jeweils unterschiedlicher Dateien instanziiere ich diese Klasse n mal mit jeweils unterschiedlichen Parametern. Ich schaffe eine weitere Java-Klasse, die prüfen kann, ob das Erzeugungsdatum einer Datei passt. Für n Prüfungen … s.o. Und ich schreibe eine weitere Java-Klasse für die Prüfung in Zusammenhang mit einer SQL-Datenbank.
Allgemein formuliert: Jede Prüfung wird in einer getrennten Java-Klasse abgebildet.

Wie erzeuge ich die Prüfungs-Objekte?
Wenn ich die Objekte jeweils mit dem new-Operator erzeuge, dann handel ich mir einen Nachteil ein: Jedes Mal, wenn eine neue Prüfung dazu kommt, muss ich den Code verändern, der die Objekte erzeugt. Das ist ein No-Brainer und zieht Verwaltungsaufwand nach sich: Dokumentation, Versionsverwaltung, Deployment. Mir ist es lieber, den Code unberührt zu lassen und nur eine Konfiguration zu ändern.

Gibt es eine andere Möglichkeit, die Objekte zu erzeugen? Ja.
Java macht es möglich, ein Objekt in XML-Form abzubilden. Und der umgekehrte Weg, man bemerke die Symmetrie, ist auch gangbar: Wenn ein entsprechender XML-Text vorhanden ist, dann kann daraus ein Objekt erzeugt werden. Wenn ich den XML-Text verändere, dann verändere ich das potentielle Objekt. So kann ich n unterschiedliche XML-Texte erzeugen, die sich jeweils beispielsweise nur um einen Pfadnamen der zu prüfenden Datei unterscheiden. Das ist prima, weil es eine Konfiguration ist.

Ein Weg, den ich nicht gehe: Es gibt eine Liste mit Dateinamen, für die geprüft werden soll, ob die entsprechenden Dateien vorhanden sind, und ein Programm A liest diese Liste und führt die Prüfungen durch. Es gibt eine weitere Liste mit Dateinamen für die Datumsprüfung und ein Programm B, das diese Liste liest und entsprechende Antworten gibt. Und so weiter für alle geforderten Prüf-Typen.
Dieser Ansatz ist nicht komfortabel, weil ich mit mehr als einer Konfigurationsdatei hantieren muss. Mein Ansatz erlaubt mir eine einzelne Datei, die die Prüfungen steuert.

Code
… ohne Drumherum, damit die Idee deutlich wird.

Command ist sehr allgemein.

FileExistsP war der Ausgangspunkt der Überlegungen.

FileCreatedTodayP ist so ähnlich wie FileExistsP

FileCommand gibt es, weil bestimmter Code sich wiederholt.

CommandList ist die Klammer, die die Commands zusammenhält. Ich brauche so aus der XML-Datei nur ein Objekt zu lesen, weil die darin enthaltenen Objekte ebenfalls erzeugt werden.

Main startet die Prüfungen, die in einer Datei konfiguriert sind.

Hier ist ein Beispiel für eine solche XML-Datei.

Decoder zeigt mir, wie die XML-Darstellung eines Objekts ist.
Nur für den Fall, dass ich das nicht im Kopf ausrechnen kann ;)

Eine Jar-Datei inklusive Quelltext gibt es hier.

Die Prüfung in Zusammenhang mit der SQL-Datenbank habe ich nicht ausformuliert. Fleissarbeit. Werde ich vermutlich implementieren, wenn die Handarbeit mich bei der täglichen Arbeit ausreichend nervt.

Das Thema “Zeitplanung der Ausführung” könnte interessant werden. Vielleicht will ich nicht jede Prüfung bei jedem Programmdurchlauf ausführen. Die oben genannten Prüfungen führe ich jeden Morgen aus und nur einmal am Tag. Den Zustand eines SQL-Datensatzes möchte ich vielleicht im 5-Minuten-Takt prüfen. Es wird nie langweilig.

An die Stelle des System.out.println wird etwas anders treten: Email schreiben, Eintrag in Logdatei schreiben oder ähnliches. Konfigurierbar, natürlich! Und natürlich reicht ein Ausdruck auf der Console nicht als Fehlerbehandlung.

Hier erledigt der Code in XML-Form Überwachungsaufgaben. Aber das ist nicht wesentlich. Jede Programmierung kann so abgebildet werden. Und es wird auch gemacht, Beispiel ant, das mich auf die Idee gebracht hat.

Warum das “P” im Namen? Weil ein P ein bisschen aussieht wie ?.

Veröffentlicht unter Allgemein | Kommentare deaktiviert für XML als CodeP

xslt erzeugt Code


Kurzfassung

In der Programmierung mit Lotus Notes nutzt man gerne Profil-Dokumente, siehe hier und hier. Eine Wrapper-Klasse macht das Profil-Dokument für Objekt-Orientierte Programmierung verfügbar. Die Wrapper-Klasse zu schreiben ist stupide und fehleranfällig. Ich habe deshalb etwas gebaut, das mir aus der Maske eines Profil-Dokuments die Wrapper-Klasse erzeugt.


Detail: Profil-Dokument

In der vergangenen Woche habe ich ein Projekt vollendet. Sein wesentlicher Bestandteil ist der Export von Daten aus einer Notes-Datenbank in eine Datei für die Controlling-Abteilung. “Nebenbei” kann ein Administrator etliche Einstellungen vornehmen: Adresse der Datenquelle, Adresse der Ziel-Datei, Backup-anlegen-oder-nicht – um nur drei zu nennen. In Notes liegen diese Einstellungen in einem Dokument – wie alle Daten in Notes. Und wie in Notes üblich gibt es auch eine Maske, die in diesem Zusammenhang benutzt wird. Dieses Dokument mit den Einstellungen nennt man Profil-Dokument und die Maske Profil-Maske.

Detail: Programmierung

In Notes kann ich objektorientiert programmieren :-)) Um auf einen Feld-Wert in einem Dokument zuzugreifen, muss ich den Namen des Feldes kennen. Das ist etwas umständlich, denn ich muss immer wieder auf die Maske schielen :-(( Muss ich?!? Nein. Ich schreibe eine Wrapper-Klasse. Dann kann mir die IDE helfen,wie ein Sausewind zu programmieren.

Um die Wrapper-Klasse zu schreiben braucht man nicht viel zu denken: Der Name der Klasse setzt sich zusammen aus dem Namen der Maske, im Beispiel “Test”, und dem Wort “Class”. Die Klasse enthält für jedes Feld einen Getter, dessen Name “get”-plus-Feldname ist.

Ich kann die Wrapper-Klasse “einfach so” ‘runtertippen. Das habe ich auch schon ein paar mal gemacht. Es ist langweilig und fehleranfällig. Deswegen nutze ich die Notes-interne Darstellung der Maske als XML und meine Transformation. Der Notes-interne XMLTransformator macht aus den beiden eine Datei. Und diese Datei füge ich als Script-Bibliothek in das fragliche Projekt ein. Voila! Ein Beispiel für eine Maske in XML-Form findet sich hier. Und meine Transformation hier. Die beiden Dateien haben die falsche Endung, weil es so in WordPress einfacher ist.

Die Sache funktioniert mit dem XMLTransfomator in Notes. Und mit xsltproc auch: hier ist das Ergebnis.

Ausblick

Wenn ich auf ein Profil-Dokument zugreife, dann lesend. Geschrieben und verändert wird es anderswo. Deswegen hat die Wrapper-Klasse nur get-Methoden. Es ist einfach, eine andere Transformation zu erschaffen, die sowohl Getter als auch Setter hat.

Der Rückgabe-Wert ist hier immer “Variant”. Das ist in diesem Fall ok, aber vielleicht will ich Typensicherheit – so gut das in Notes möglich ist. Im field-Tag sieht man das Attribute “type”. Hier ist noch Potential.

Supercool wäre ein Verfahren, das direkt den Code in einer Script-Bibliothek in einem Notes-Template erzeugt. Das spart mir den Weg über eine Datei.

Fazit

Dieses Verfahren ist nicht auch Profil-Masken beschränkt. Ein kleines Dingelchen, das meine Prodktivität steigert. Möge es auch der Notes-Welt nutzen.

Veröffentlicht unter Allgemein | Kommentare deaktiviert für xslt erzeugt Code

#ifdebug objektorientiert

Ein Puzzleteilchen im letzten Projekt ist der DocFilter. Seine Aufgabe ist, ein Notes-Dokument zu prüfen. Wenn das Dokument bestimmte Bedingungen erfüllt, dann akzeptiert das DocFilter-Objekt das Dokument. DocFilter implementiert das Interface Filter. NullFilter ist eine andere Klasse, die Filter implementiert. Ein NullFilter-Objekt akzeptiert alle Dokumente.

<Exkurs NullImplementierung>
Ich “programmiere gegen Interfaces”. Dabei erstelle ich oft eine Null-Implementierung – eine, die “nichts” tut, aber die ich verwenden kann, statt null in Java zurückzugeben. NullPointerExceptions werden so vermieden.
</Exkurs NullImplementierung>

Ein NullFilter-Objekt ist im Testbetrieb sehr hilfreich, denn es ist kompliziert, ein Notes-Dokument zu erzeugen, das alle Bedingungen erfüllt. Anstelle dessen kann ich nun irgendeins benutzen.

Gretchenfrage: Wie geschieht der Wechsel zwischen DocFilter- und NullFilter-Objekt?

Möglichkeit 1: Ich ändere den Code. An der fraglichen Stelle wird ein DocFilter-Objekt erzeugt. Im Code für die Teststellung aktiviere ich eine Zeile, die das Filter-Objekt durch ein NullFilter-Objekt ersetzt.
Das hat zwei Nachteile: Erstens muss ich geänderten Code einsetzen – in Notes ist das einigermassen kompliziert. Zweitens bin ich nie sicher, ob gerade der “offizielle” Code aktiv ist oder der Code für die Teststellung.

Möglichkeit 2: Es gibt eine Konfiguration und darin einen Schalter namens debug. Der Code an der fraglichen Stelle entscheidet anhand von debug, welches Objekt erzeugt wird.
Das ist besser, weil ich nun in der Konfiguration nachschauen kann, statt im Code ‘rumzuwühlen. Aber das macht den Code an dieser Stelle – und an allen anderen, die ein ähnliches Problem haben – sehr häßlich.

Meine Antwort ist die: Die fragliche Stelle im Code entscheidet nicht, welches Objekt erzeugt wird. Statt dessen wird das Objekt in einem FilterProvider erzeugt. Ein FilterProvider liest die Konfiguration zur Laufzeit ein und gibt das jeweils passende Objekt zurück. Andere Stellen im Code werden andere Provider-Klassen brauchen.

Ich arbeite lieber mit einem Faulen als mit einem Dummen zusammen. Einfach ist besser.

Veröffentlicht unter Allgemein | Kommentare deaktiviert für #ifdebug objektorientiert

Prozess und Objektorientierung

Auftrag ist, einen bestehenden Prozess zu ersetzen, weil dieser Prozess eine aktive grafische Benutzeroberfläche erzwingt. Der Ersatz muss komplett im Backend laufen können. Ausserdem sagt mein Chef, dass es weitere bestehende Prozesse gibt, die ähnlich sind und die später auch abgelöst werden sollen.

Erster Schritt ist, den bestehenden Prozess zu verstehen, eine Lotus-Script-Funktion mit fast 300 Zeilen. Schnell ist klar, dass es wesentlich darum geht, über eine Auswahl von Notes-Dokumenten zu iterieren. Die Iteration enthält acht Schritte: Die ersten vier prüfen unterschiedliche Vorbedingungen, die letzten vier werden nur ausgeführt, wenn alle Vorbedingungen erfüllt sind.

Zweiter Schritt ist, einen Plan für die Modellierung des neuen Prozesses zu erstellen. Was getan werden muss ist klar, siehe Schritt Eins. Aber wie soll es geschehen? Ich entscheide mich für Objektorientierung mit Java und gegen prozedurale Programmierung in Lotus Script.

Und nun die Gretchenfrage, die eigentliche Modellierung: Welche Objekte kommen vor und wie arbeiten sie zusammen? Ich könnte vom Notes-Dokument ausgehen, dessen Java-Interface in der API verfügbar ist. Oder stelle ich den Prozess in den Vordergrund? Ich habe mich für den Prozess entschieden. Der Prozess verwandelt Schritt für Schritt ein Notes-Dokument. Die Programmierung der Notes-Dokument-Klasse lasse ich unverändert.
Der Unterschied ist nicht gross. Der Startpunkt des Ablaufs liegt bei meinem Modell im Prozess-Objekt, nicht im Datenobjekt. Das entspricht zwar nicht der “reinen Lehre” der Objektorientierten Modellierung, hat aber Vorteile:
1) Wer den alten Prozess kennt, der findet sich in der neuen Programmierung schnell zurecht.
2) Die Rede- und Denkweisen im Unternehmen orientieren sich am Prozess, nicht an den Datenobjekten. So ist die Verständigung einfacher.
3) Andere neue Prozesse können Teile dieses neuen Prozesses nutzen, und ich muss dazu nicht umdenken.

Apropos “reine Lehre”: Es gibt Leute, die meinen, dass Substantive in einem Modell zu Klassen werden und Verben zu Methoden. Dieser Ansatz ist nur in Grenzen hilfreich, denn “document.createPDF” und “PDFcreator.execute” können gleichbedeutend sein.

Der neu programmierte Prozess folgt dem alt-bekannten Muster Eingabe-Verarbeitung-Ausgabe. Das Prozess-Objekt liest aus einer Datenquelle. Die Verarbeitung ist mit Hilfe des Wrapper-Patterns abgebildet, so dass beliebige Schritte nacheinander durchgeführt werden können. Und auch die Ausgabe ist mit Hilfe des Wrapper-Patterns abgebildet, so dass unterschiedliche Ausgaben in unterschiedliche Datensenken geschrieben werden können.

Der neue Code ist gekapselt und lose gekoppelt. Er tut, was der alte auch tat. Ist aber leichter zu verstehen, die Teile sind wiederverwendbar, und er kommt ohne GUI aus.
Mission erfüllt.

Veröffentlicht unter Allgemein | Kommentare deaktiviert für Prozess und Objektorientierung

Taxi!

Wiederkehrende Abläufe können a) mit einem Namen belegt und b) in Details aufgeteilt werden. Beispiel

Das ist die Grundidee prozeduraler Programmierung. Problem: Es gibt “Eulen” und “Lerchen” und “Eulenlerchen” und “Lercheneulen” und und und. Die Prozedur verbingeDenTag ist nicht für alle Typen angemessen. Deshalb trumpft Objektorientierte Programmierung: Frühaufsteher sind Menschen und Spätzubettgeher sind Menschen und und und. Ihre Gemeinsamkeiten werden in der Klasse Mensch untergebracht. Ihre Besonderheiten in den erbenden Spezialklassen Frühaufsteher, Spätzubettgeher usw.
Mit der Objektorientierten Programmierung einher geht die Aufgabe, ein System zu analysieren, um es abbilden zu können. Analyse ist untrennbar verbunden mit dem Wissen um das zu analysierende Thema. Aber auch das umfassenste Wissen garantiert nicht, dass die Analyse treffend ist.

Tür auf …

Beispiel aus dem “echten Leben” sei das Thema “Tür”. Jeder von uns kennt Türen. Eine Tür kann geöffnet werden. Eine Klasse Tür wird also eine Methode öffnen bekommen. Oder? Eine Tür kann sich nicht selbst öffnen, das widerspricht den Gesetzen der Physik. Ausser Tür brauchen wir wohl auch eine Klasse TürÖffner? Ja. Aber nur dann, wenn der Türöffner eine Rolle spielt – sonst können wir den wegabstrahieren.

Tür zu …

Eine Klassenstruktur wird schnell kompliziert. Wohl dem, der es einfach hat. Für alle anderen gibt es Design Patterns. Das sind Muster, die erklären, wie Klassen zusammenarbeiten können, ohne dass der Programmierer schlaflose Nächte hat. Die immer wiederkehrenden Themen “lose Kopplung”, “innerer Zusammenhalt” usw.

Dritter sein.

Eine Grundidee von Objektorientierter Programmierung ist, dass Daten und ihre Verarbeitungsmethoden zusammengefasst sind. Aber das ist manchmal genauso unflexibel und unpassend wie das prozedurale Beispiel s.o.! Das Design Pattern “Delegation” hilft, Methoden austauschbar zu machen. Das Objekt weiss nicht, wie es etwas tun soll, aber es bekommt ein anderes Objekt, das den Job erledigen kann.

Stell’ Dir vor, Du hast kein KFZ. Du bekommst ein Taxi, um von A nach B zu kommen. Und Du bekommst einen 40-Tonner für den Umzug. Der eigene Wagen ist nicht so flexibel.

Von dieser Idee ausgehend fällt es mir leicht einzusehen, warum Service-Orientierte Architekturen und Komponenten-Frameworks eine a) brauchbare und b) flexible Sache sind. Die Plugin-Architektur hat diese Welten geöffnet. Ich bastel gerade an einer OSGi-Anwendung, die ich hier hoffentlich bald vorstellen kann.

Veröffentlicht unter Allgemein | Kommentare deaktiviert für Taxi!

Resume Next – in java

Summary

Lotus Script has a nice feature for exception handling called “resume next”. Java is missing this feature. This article shows an OOP way to implement it when looping an array.

The Task

Imagine you have a class UrlsContentCollector. You provide an URL[] and the collector gives you all the content of the given urls in one big chunk. What is your idea about handling exceptions here? Consider this: One of your applications named “Nippi” using the UrlsContentCollector is picky about the content. This application will produce bogus results, if there is any error in fetching the content e.g. one of the given urls is unreachable. There is another application called “Bob”. “Bob” is a little indifferent. One url unreachable? What the heck! Write a log entry and go on.

On the one hand you need to throw exceptions because of “Nippi”. But this will disturb “Bob”. “Bob” can decide to ignore the exceptions but it cannot get back to the point where the exceptions was raised to continue processing the list of urls.

Do you think about implementing UrlsContentCollector twice? A “noisy” implementation and a “quiet” one? Using reflections and if-blocks in order to decide what to do? I think there is a better way. Or two.

The Clients Decide

“Nippi” and “Bob” both use UrlsContentCollector, let’s call them clients. My idea is this: The UrlsContentCollector does not throw an exception but it notifies the client of the exception. In response the client tells the UrlsContentCollector wether to stop processing or not.

This is easy! Notification is done via a pattern called “observer“. Its interface needs a method with an exception as parameter and a boolean in its answer. “Nippi” and “Bob” use the ExceptionObserver. Being notified they react differently. UrlsContentCollector has a chance to resume if the client wants it to.

Your Exception

“Nippi” and “Bob” do not care about which item caused the problem. “Bob”‘s attitude is “Stop bothering me with details – just go on”. If “Nippi” and “Bob” take a little bit more of a care, then there is an other possibility. Let’s imagine that UrlsContentCollector takes an array of URLs and a starting position i to process the array from i to the end. Further imagine your own exception class ListprocessingInterruptedException. UrlsContentCollector throws a ListprocessingInterruptedException containing the current position processed. The client catching the exception knows where to start over and UrlsContentCollector gives the opportunity to do so.

Conclusion

ExceptionObserver is easy to implement and easy to use. There is no duplicated code necessary here. The classes are loosly coupled. Three reasons why this is a good idea. Maybe this idea is against the odds. This is not the usual way to handle exceptions in java. But as a proverb puts it: “You have to swim against the tide if you want to get to the spring.”

Creating my own exception has an advantage over using the observer pattern. I.e. exception handling is not mixed with other kinds of behaviour. Notably it is not easily confused. As a proverb puts it: “If you are in Rome do as the Romans”. It’s easy to implement, it is DRY, it is loosly coupled.

You can get some bare bones uncommented source code.

Howto decide? Convention rulz cleverness.

Veröffentlicht unter Allgemein | Verschlagwortet mit , , | Kommentare deaktiviert für Resume Next – in java

Maskenmorphose

Masken gehören zu den wesentlichen Objekten in Lotus Notes. Jedem Datensatz, auch “Dokument” genannt, ist genau eine Maske zugeordnet. Die Maske bestimmt das Layout des Dokuments und sie bestimmt, welche Feld-Werte des Dokuments angezeigt werden. Eine Maske kann Teilmasken einbinden und Berechnungen ausführen.

In unserem Unternehmen gibt es zwei Notes-Datenbanken, die ich hier einfach “System 1″ und “System 2″ nenne. System 2, das ich betreue, enthält Kopien von Dokumenten aus System 1 und auch eine Kopie der zugehörenden Maske W, siehe Abbildung 1. Dokumente in System 1 werden nur wenige Tage alt. System 2 hat nur einen klitzekleinen Teil dieser Dokumente, aber in System 2 bleiben sie länger erhalten, manchmal Monate lang.

Abbildung 1

Abbildung 1

Weil sich Anforderungen ändern, ändert sich Software – und in Notes entsprechend auch die Masken. Die Maske W ändert sich – leicht. Ich mache das durch einen leicht veränderten Namen kenntlich: Maske W’, siehe Abbildung 2.

Abbildung 2

Abbildung 2

In System 2 brauche ich sowohl Maske W als auch Maske W’, denn einige Dokumente in System 2 wurden in System 1 mit Maske W erzeugt, andere Dokumente, nämlich neuere, wurden mit Maske W’ erzeugt.

System 1 liegt ausserhalb meines Einflußbereichs, hier hat sich der Inhalt der Maske W leicht verändert, aber ihr  Name ist derselbe geblieben. Zum Glück kann ich aufgrund des Vorhandenseins eines Feldes entscheiden, ob ein Dokument in System 2 zur Maske W oder zur Maske W’ gehört. Wie kommt nun die passende Anzeige zum Dokument?

In System 2 erzeuge ich Teilmasken aus Maske W und Maske W’. Die Maske W in System 2 wird zu einer “Weiche”, denn sie bindet entweder die Teilmaske W oder Teilmaske W’ ein, je nach Existenz oder Nicht-Existenz eines Feldes im jeweiligen Dokument, vgl. Abbildung 3.

Abbildung 3

Abbildung 3

In Abbildung 1 ist Maske W von System 2 eine exakte Kopie der Maske W von System 1. In Abbildung 3 ist sie etwas ganz anderes. In System 1 ist dieses Umschalten nicht nötig. Die Auswirkung für Benutzer von System 2 ist, dass jedes Dokument mit der passenden Maske angezeigt wird. Ganz anders und doch gleich.

Veröffentlicht unter Allgemein | Kommentare deaktiviert für Maskenmorphose

Maschinenversteher

“Aus einem schlechten Schlosser kann man immer noch zwei gute Elektriker machen.” (mein Vater, Schlosser)

“Aus einem schlechten Elektriker kann man immer noch zwei gute Schlosser machen.” (mein Onkel, Elektriker)

Heute in der Teeküche greinte mein Kollege, weil seine Senseo-Kaffeemaschine “immer schnell blinkt”. Das bedeute, so sagte er, dass Wasser fehle, obwohl doch offensichtlich sei, dass der Tank voll ist.

Ich nahm mich der Sache an. Der transparente Tank zeigt zweierlei: Den Wasser-Pegel und ein schwarzes Dingelchen, das sich innen nahe am Rand befindet. Das Dingelchen ist beweglich. Es bewegt sich ein bisschen auf und ab, wenn man den Tank schüttelt. Fast so wie der Wasser-Pegel. Scheinbar klemmt es.

Annahmen: Das Dingelchen ist der Geber für den Wasser-Füllstand. In der Maschine, für uns unsichtbar, muss es einen Nehmer geben. Vermutlich magnetisch. Kalkablagerungen behindern die Beweglichkeit des Gebers.

Versuch: Whiteboard-Magnet geholt. Am Gehäuse entlang bewegt … irgendwo da muss der Nehmer sein. Bingo! Das Lämpchen beruhigt sich.

Ad-hoc-Abhilfe: Tank füllen, einsetzen und die ganze Apparatur mit dem Whiteboard-Magneten so manipulieren, dass das Lämpchen ruhig blinkt. Langfristig sollte der Tank entkalkt werden, damit sich das Dingelchen wieder frei bewegen kann.

Ist es wesentlich für eine Kaffeemaschine, dass sie elektrisch betrieben wird? Nein. Perkolatoren und Stabfilterkannen brauchen heisses Wasser. Wie das Wasser erhitzt wird, ist nicht wesentlich. Die elektrische Kaffeemaschine macht Kaffeebrühen von Elektrizität abhängig. In der Programmierung nennt man das “starke Kopplung”. Perkolatoren und Stabfilterkannen sind an Elektrizität nur “lose gekoppelt”.

Ich kann meine Edelstahl-Stabfilterkanne mit Senseo-Pads “betreiben”: Pads aufreissen, Kaffeepulver in die Kanne. Fertig. Teuer, aber möglich. Versuch mal, die Senseo-Maschine mit Jacobs Krönung zu “betreiben” … geht nicht. Die Senseo-Maschine ist stark an die Pads gekoppelt, meine Stabfilterkanne schwach.

Schön, dass wir die Teeküche haben. Sie erinnert mich daran, dass ich lieber lose Kopplung habe – sowohl analog als auch digital.

Veröffentlicht unter Allgemein | Kommentare deaktiviert für Maschinenversteher

(amusieren: Der glückliche Sisyphos

“der ganze Rest” im Untertitel meines Blogs ist bisher zu kurz gekommen, denn die meisten Beiträge werfen Schlaglichter auf technische Details. Dabei bin ich jeden Tag Teil der sozialen Komponente der Software-Entwicklung, bin sowohl Zuschauer als auch Akteur.

Ein Muster, das immer wieder aufzutauchen scheint, ist dies: Der Programmierer/ das Team rollt einen Stein bergauf. Kurz vor dem Ziel rollt der Stein wieder bergab. Konkret gesprochen: Kurz bevor das Projekt beendet ist, wird die Vollendung unmöglich. Die ganze Vorstellung erinnert an absurdes Theater. Bemerkenswert, dass es auch Projekte gibt, die gelingen ;)

In der Sisyphos-Situation denke ich immer an meinen Lieblings-Autor, A1ber7 (amu5

Jedes Gran dieses Steins, jeder Splitter dieses durchnächtigten Berges bedeutet allein für ihn eine ganze Welt. Der Kampf gegen Gipfel vermag ein Menschenherz auszufüllen. Wir müssen uns Sisyphos als einen glücklichen Menschen vorstellen.(1)

Schlichte und gewaltige Worte. Sie zeigen, dass Camus zurecht Philosoph genannt wird. Denn sie haben den Test der Zeit bestanden: 70 Jahre alt und treffend wir am ersten Tag.

Wenn ein Projekt erfolgreich abgeschlossen werden kann, dann ist die Ursache nicht zwingend in der eingesetzen Technik zu suchen. Ebensowenig bei einem gescheiterten Projekt. Man kann noch soviel Tom DeMarco(2)(3) und Fred Brooks(4) lesen – das wird nichts nutzen, wenn man nicht in der Lage ist, Absurditäten zu erkennen und zu ertragen. Egal ob Manager oder Programmierer oder ein bisschen von beidem: ohne Philosophie fehlt ‘was.

 

 (1) Camus, Albert: Der Mythos von Sisyphos. Ein Versuch über das Absurde. Hamburg 1959. S. 101
(2) DeMarco, Tom: Der Termin. Ein Roman über Projektmanagement. München 1998
(3) ders.: Wien wartet auf Dich! Der Faktor Mensch im DV-Management. München, Wien 1999
(4) Brooks, Frederick: Vom Mythos des Mann-Monats. Essays über Software-Engineering. Bonn 2003
Veröffentlicht unter Allgemein | Kommentare deaktiviert für (amusieren: Der glückliche Sisyphos

Notes: Alle Teil-Formulare kennen; Interface

In der Programmier-Umgebung von Lotus Notes, “Designer” genannt, kann man Daten-Eingabemasken, sogenannte “Formulare”, erstellen. Ausserdem kann man im Designer Teil-Formulare erstellen. Ein Formular kann beliebig viele Teil-Formulare enthalten.

Teil-Formulare clever nutzen

Die Möglichkeit, Teil-Formulare zu erstellen und einzubinden, hat zwei Vorteile. Einen offensichtlichen und einen weniger offensichtlichen.

Der offensichtliche Vorteil ist die Möglichkeit, wiederkehrende Abschnitte zu kapseln. Wenn ich erkenne, dass ein gewisser Bereich in mehreren Formularen vorkommt, dann verschiebe ich diesen Bereich in ein Teil-Formular und entferne ihn aus den entsprechenden Formularen. An der Leerstelle setze ich jeweils das Teil-Formular ein. Das spart Schreibarbeit und folgt dem guten Muster “Don’t Repeat Yourself”. Wenn ich das Teil-Formular ändere, dann wirkt sich das auf alle Formulare aus, die das Teil-Formular verwenden.

Weniger offensichtlich ist dies: Ein Teil-Formular kann als Interface dienen. Seine Feldwerte werden dazu durch einen Event-Handler im Formular gesetzt, beispielsweise durch das Exiting-Event eines zugehörenden Feldes oder das QuerySave-Event des Formulars. Dadurch, dass ein Formular ein Teil-Formular einbindet, codifiziert das Formular, dass es das Interface des Teil-Formluars implementiert – um java-ähnlich zu sprechen.

Teil-Formulare auflisten

Die Notes-Pogrammierung, die ich von meinen Vorgängern geerbt habe, ist voll von Teilmasken und schlecht dokumentiert. Wie erkenne ich, welche Teil-Formulare in einem Formular eingebunden sind? Anders formuliert: Wie erkenne ich, welche Interfaces ein Formluar implementiert? Mit den Bordmitteln des Designer kommt man leider nicht weiter. Das Notes-eigene XML und eine Transformation beenden die Not.

Zum Glück hat jedes (Teil-)Formular eine XML-Repräsentation in einem Dialekt namens dxl. Und der Designer kann eine XML-Transformation auf auswählbare Elemente anwenden. Fehlt nur die passende Transformation. Hier ist sie:

Grafische Tools, wie der Designer eins ist, beschleunigen die Schaffung der Benutzeroberfläche enorm. Aber der gute alte Quelltext wird weiterhin seine Daseinberechtigung haben. Beruhigend.

Veröffentlicht unter Allgemein | Verschlagwortet mit , , | Kommentare deaktiviert für Notes: Alle Teil-Formulare kennen; Interface