Abenteuer Clojure

Im Laufe der Zeit habe ich schon einige Programmiersprachen kennengelernt. Meiner ersten Schritte habe ich mit Basic auf einem Commode C64 gemacht, dann in dBase die Daten meiner Diplomarbeit ausgewertet und damit das imperative und prozedurale Programmieren gelernt. Dann habe ich das objektorientierte Programmieren mit Powerbuilder, Delphi und Java entdeckt und es im Laufe der Zeit immer wieder neu gelernt. Die wirkliche Idee habe ich vielleicht erst über die Beschäftigung mit Smalltalk verstanden (das Schöne an Smalltalk zeigt z.B. der Artikel Reading Smalltalk).

Das alles war spannend, jedoch war der Schritt vom prozeduralen zum objektorientierten Programmieren nicht besonders groß, da auch die genannten Sprachen imperative Sprachen sind. Er ist nicht vergleichbar mit dem Schritt vom objektorientiert-imperativen zum funktionalen Programmieren mit einer Sprache aus der Lisp Familie. Dank der regen Clojure Community gibt es gute Webseiten, auf denen man diese Sprache erlernen kann. Das Aufregendste daran für mich ist es, ohne Variablen zu programmieren. Das stellt mein gewohntes Denken vor wirklich neue Herausforderungen. Man kann über Algorithmen nicht in der gewohnten Weise denken. Werte sind im Prinzip erst einmal unveränderlich. Das ist ein Abenteuer. Es fühlt sich an, als ob man  das Laufen neu lernte, oder als ob ein Klarinettist auf einmal Geige spielen lernte.

Veröffentlicht unter Programmierung | Kommentare deaktiviert

Verwirrende Meldung

Oracle beantwortet die Abfrage

select (count(*) > 0) from dual

mit der Fehlermeldung

ORA-00907: Rechte Klammer fehlt

Interessanterweise in PL/SQL wird eine äquivalente Anweisung sogar fehlerfrei compiliert, führt aber zu einem Laufzeitfehler mit der gleichen Meldung.
Was auf den ersten Blick verwirrt, ist im nachhinein einfach. Der Ausdruck ist ein Boolean und dieser Datentyp gehört leider nicht zu den SQL Datentypen, sondern nur zu den PL/SQL Datentypen von Oracle.

Eine sprechendere Fehlermeldung hätte Oracle schon spendieren können.

Veröffentlicht unter Allgemein | Verschlagwortet mit | Kommentare deaktiviert

Einschränkungen für DimensionUsage

Wiederverwendung von Dimension ist schön, hat jedoch auch Grenzen. Schema Dimensionen, die über das DimensionUsage Element eingebunden werden, haben bei Mondrian folgende Einschränkung: Diese Dimensionen können nicht für degenerierte Dimensionen (degenerate dimension) verwendet werden. Erklärung findet sich im Pentaho Forum:

We obviously want the shared dimensions to have the same set of members, regardless of which cube they are used in, and your ‘table-less’ shared dimensions wouldn’t behave like that.

Das bedeutet, dass es genau dann zu einem Fehler mit Shared degenerate dimensions kommt, wenn diese Dimensionen in unterschiedlichen Cubes verwendet werden, welche auf unterschiedlichen Fakt Tabellen basiert. In diesem Falle bekommt man folgendenen Fehler:

Mondrian Error:In usage of hierarchy '[hierarchyName]' 
in cube 'NameOfCube', you must specify a foreign key,
because the hierarchy table is different from the fact table.
Veröffentlicht unter Business Intelligence | Verschlagwortet mit | Kommentare deaktiviert

Kanban und Storm

Heute war ein Hadoop Get Together der Scalable Information Retrieval group von Xing. Es gab interessante Vorträge, die sich jedoch nicht primär mit Hadoop auseinander setzten.

Der erste Vortrag von Markus Andrezak handelte über ein Prozessmodell in der Softwareentwicklung. Wie kann man Kanban in der Softwareentwicklung anwenden? Ausgangspunkt seiner Argumentation war das Ziel, dass die Firma möglich schnell Werte realisieren möchte und vom Markt auch schnell ein Feedback benötigt, die bestätigt, dass die Entwicklungen angenommen werden oder nicht. Dazu muss einerseits ein Modell bestehen, dass durch Datenanalyse verifiziert werden kann. Um ein schnelles Feedback zu bekommen, müssen Entwicklungen schneller deployed werden – das heisst tägliche Releases.

Interessant für mich waren verschiedene Aussagen. Das Problem, so meint er, sei das Projektmanagement, welches aus dem Management greifbarer Güter nicht auf Kreativprojekte – bei denen es viel auch um Lernen geht, nicht übertragen lasse. So konnte er durch das Reduzieren der gleichzeitig bearbeiteten Features die Durchlaufzeit erhöhen. Das führte dazu, dass auch die Varianz der Dauer der Implementation von Features deutlich reduziert werden konnte. Die Kosten für Transaktionen (Auslieferungen) sind deutlich geringer, das Risiko ist geringer. Auslieferung von Bugfixes ist kein Sonderfall, kleine Änderungen ausliefern ist der Standardfall.

Der zweite Vortrag von Martin Scholl beschäftigte sich mit dem Framework Storm. Leider ist die Einleitung (mit einer netten musikalischen Analogie) recht lang geworden. Darum hat dem Vortragenden die Zeit für verschiedene technische Details und Beispiele nicht mehr gereicht. Storm ist eine Plattform für Echtzeit Analyse von Daten. Das System verarbeitet permanent einen Strom von Ereignissen und kann auf diese reagieren. Die Knoten können auf verschiedene Rechner verteilt werden. Das System stellt sicher, dass jedes Event mindestens einmal verarbeitet wird. Versprochen wurde außerdem, dass sich das System viel leichter aufsetzen lassen soll als Hadoop. Muß man mal ausprobieren.

Veröffentlicht unter Allgemein | Kommentare deaktiviert

svn Import in Place

Assuming you already have a repository, and you want to add a new folder structure to it, just follow these steps:
  1. Use the repository browser to create a new project folder directly in the repository. If you are using one of the standard layouts you will probably want to create this as a sub-folder of trunk rather than in the repository root. The repository browser shows the repository structure just like Windows explorer, so you can see how things are organised.
  2. Checkout the new folder over the top of the folder you want to import. You will get a warning that the local folder is not empty. Now you have a versioned top level folder with unversioned content.
  3. Use TortoiseSVN → Add… on this versioned folder to add some or all of the content. You can add and remove files, set svn:ignore properties on folders and make any other changes you need to.
  4. Commit the top level folder, and you have a new versioned tree, and a local working copy, created from your existing folder.

 

Veröffentlicht unter Allgemein | Kommentare deaktiviert

Synchronisieren von Verzeichnissen

Beim Synchronisieren von Verzeichnissen ist der Fall, neue oder geänderte Dateien zu kopieren mit verschiedenen Shellscripten schnell realisiert.  Das Löschen von Dateien, die in der Quelle gelöscht wurden, auch im Ziel zu löschen, ist mit Shellscripten mit meinen Kenntnissen nicht so einfach zu realisieren (Shell Scripte unter Windows mag ich gar nicht).

Mit Ant geht das hingegen recht einfach. Hier konfiguriert man einfach im Delete Task einen Fileset mit einem Present Selector. Bei letzterem ist es wichtig die Eigenschaft present=”srconly” zu setzen. That’s it.

<fileset dir="${target_dir}" includes="**/*">
 <present present="srconly" targetdir="${src_dir}"/>
 </fileset>
Veröffentlicht unter Allgemein | Kommentare deaktiviert

Mondrian Eigenart

Wenn im JasperServer ein Analysis View das erste Mal aufgerufen wird, dann wird dass ganze Schema validiert. Wenn ein Cube im Schema nicht validiert werden kann, dann wird die Abfrage mit einem Fehler abgebrochen. Ein Fehler kann es sein, wenn eine Dimension keine AllMemberElement besitzt und die zugrunde liegende Tabelle leer ist.

Sollte mich das zwingen, für jeden Cube ein eigenes Schema zu definieren? Das erhöht doch nur unnötig die Menge der Objekte, die zu verwalten sind.

Bug oder Feature?

Veröffentlicht unter Business Intelligence, Programmierung | Verschlagwortet mit , | 1 Kommentar

Parallele Verarbeitung

Um die Multi-Core-Prozessoren richtig zu nutzen, bietet sich parallele Verarbeitung an. Hauptanforderung an das zu lösende Problem ist, dass sich dieses in separate Einheiten aufteilen läßt, welche sich unabhängig voneinander verarbeiten lassen.

Die Fibonacci Folge ist das extreme Gegenbeispiel, jede Zahl der Folge berechnet sich aus den Vorgängern, diese Berechnung läßt sich nicht parallelisieren. Daneben gibt es Grauzonen. Ich habe eine Menge von Objekten, die sich identifizieren lassen und in der ersten Annäherung könnte man sich entsprechend dem PCP Muster einen Producer und mehrere Consumer vorstellen. Der Producer ermittelt die zu verarbeitenden Objekte und stellt sie in eine Queue. Diese Queue wird nun durch verschiedene Consumer abgearbeitet. Soweit so einfach.

Wenn nun aber die Verarbeitung der Consumer die Objektmenge verändert? Mehr als ein konkurrierender Consumer kann ja die gleichen Objekte ermitteln, die der zu verarbeitenden Objektmenge zuzufügen sind. Die Menge der Objekte ist relativ groß und ist nicht disjunkt von der Ursprungsmenge. In diesem Fall muss die Verarbeitung so gestaltet werden, dass die Ursprungsmenge abgearbeitet wird. Alle (parallelen) Consumer müssen fertig sein, bevor die Menge der neuen Objekte verarbeitet.

Da die Mengen nicht disjunkt sind, ist die Herausforderung, die ursprünglich verarbeitete Menge von der neuen Menge abzuziehen, um die Menge der noch zu bearbeitenden Objekte zu erhalten.

Wir haben eine Datenbanktabelle und die Consumer schreiben die Identifikatoren der neuen Objekte in eine Tabelle. Der Consumer arbeitet diese dann nachträglich ebenfalls ab. Dann ergibt sich die Notwendigkeit, die Menge der neuen Objekte mit der Menge der schon verarbeiteten Objekte zu vergleichen und die Differenz zu ermitteln.

Nachteil: Das Speichern erfordert relativ langsame I/O Operationen. Um die relativ langsamen I/O Operationen zu vermeiden, kann das Sammeln der neuen Objekte in den Hauptspeicher verlegt werden. Bei einer relativ großen Menge an Objekten aber kann der Bedarf an Hauptspeicher bei diesem Vorgehen recht hoch sein. Hier heisst es also abwägen.

 

Veröffentlicht unter Programmierung | Verschlagwortet mit , | Kommentare deaktiviert

AllMember Element in Mondrian

In Definitionen von Mondrian Cubes ist es hin und wieder angebracht, für eine Dimension auszuschliessen, dass über alle Elemente aggregiert wird. So macht es in der Regel keinen Sinn, die Summe der Umsätze aus verschiedenen Währungen zu bilden. Dieses Ziel kann einige Fallstricke bereithalten.

Richtig ist, dass die JPivot Oberfläche bei der Navigation in der Dimension eine Auswahl erfordert. In gespeicherten Abfragen jedoch, die noch kein ausgewähltes Element enthalten, wird dann implizit durch Mondrian das erste Element ausgewählt und in der Abfrage verwendet. Das ist auch noch in Ordnung. Das beschriebene Verhalten führt zu sehr merkwürdigen Ergebnissen, wenn sich die Elementmenge verändert und dann zufällig ein anderes Element das erste ist.

Hier wäre es wohl schöner gewesen, diese implizite Auswahl beim Speichern der Abfrage explizit zu speichern.

Einen anderen Weg nennt die Mondrian Dokumentation. Man kann auch einen Default Member direkt im Schema angeben. Dies kann, lt. Mondrian, auch zu verwirrenden Ergebnissen führen. Außerdem ist dies nur dann angebracht, wenn man in einer Umgebung entwickelt, bei der die Elememte der Dimensionen bekannt sind.

Falls man das AllMemberElement in der Dimension anbieten möchte, dann muß auch das Attribut allMemberName gesetzt sein. Dann ist darauf zu achten, dass dieser Name sich vom Namen des Levels der Hierarchie unterscheidet. Falls beide den gleichen Bezeichner besitzen kommt es zu folgendem, etwas verwirrenden Fehler:

com.jaspersoft.jasperserver.api.JSException: com.tonbeller.jpivot.olap.model.OlapException: Mondrian Error:No function matches signature '{<Level>}'

Update:

Weitere Fallstricke gibt es im Zusammenhang mit leeren Cubes.

 

Veröffentlicht unter Business Intelligence | Verschlagwortet mit | Kommentare deaktiviert

Bedingungen in Scriptella

Vor geraumer Zeit schrieb ich über meine ersten guten Erfahrungen mit Scriptella geschrieben. Da war ich von der Einfachheit und der Möglichkeit, HTML zu generieren, begeistert.

In letzter Zeit habe ich immer wieder nach einer Möglichkeit gesucht, eine bedingte Verarbeitung zu realisieren. Das query und script Tag besitzen ein if Attribut. Das kann man benutzen, um einfache Bedingungen zu hinterlegen. Hier sind die Variablen aus Properties oder vordefinierte Variablen (rownum) verwendbar. Wegen der fehlenden Debug Möglichkeit scheint es mir bisher noch nicht praktikabel, Java Anweisungen zu benutzen.

Unschön erscheint mir, dass im Gegensatz zur sonstigen Syntax, bei der $ für zur ersetztende Ausdrücke verwendet wird, dies in den Ausdrücken für das if Attribut scheinbar nicht gilt (siehe verschiedene Bespiele der Dokumentation). Auch kommen andere Operatoren wie wie “gt” zur Anwendung, während == das nach Java aussieht. Eine merkwürdige Mischung.

Bei der Definition der Properties muss man aufpassen mit Leerzeichen, denn z.B. die Zeichenkette “1 ” aus der Properties Datei kann nicht in eine Zahl gewandelt werden und führt zur Exception.

Die implizite Variable rownum beginnt bei 1 und kann gut verwendet werden, um weitere bedingte Abfragen oder Anweisungen zu erstellen.

Wenn man die ersten Hürden gemeistert hat, kann man damit jedoch schnell zum gewünschten Ziel kommen.

Veröffentlicht unter Programmierung | Verschlagwortet mit , | Kommentare deaktiviert