Design Patterns – Abstract Factory

Abstrakte Fabrik – das hört sich am kompliziertesten an, also weiter damit. Die abstrakte Fabrik ist ein Erzeugungsmuster und dient dazu, sich von der Erzeugung ganzer Produktfamilien unabhängig zu machen. Ein prominentes Beispiel sind Fabriken zur Erzeugung von Betriebssystemabhängigen Oberflächenelementen. Es könnte eine Fabrik MSFactory und eine Fabrik MacFactory geben, die beide verschiedene Familien von Oberflächenelementen zu Verfügung stellen. Da auch die Produkte dieselbe Schnittstelle besitzen (z.B. Fenster verschieden, oder Größe ändern), kann die Fabrik gewechselt werden, um die Software auf verschiedenen System laufen zu lassen.

Ich habe mir ein anderes Beispiel einfallen lassen. Ich denke da an ein Ayurveda-Kurhotel, in dem Gäste in drei Gruppen gemäß ihrem Dosha eingeteilt werden und eine Diät machen. Das Bedienungspersonal soll sich nicht um die Erzeugung der Mahlzeiten Gedanken machen müssen, sondern nur wissen, um welche Tageszeit es sich handelt und welches das Dosha des Gastes ist. Deshalb gibt es für die Doshas Kapha, Vata und Pitta jeweils eine eigene Factory, die Frühstück, Mittagessen und Abendessen erstellt.

Hier der Code (C#):

using System;

namespace AbstractFactoryPatternExample
{
    public interface IAyurvedaMealFactory
    {
        IBreakfast 	CreateBreakfast();
	ILunch	CreateLunch();
	ISupper	CreateSupper();
    }

	public interface IBreakfast{}
	public interface ILunch{}
	public interface ISupper{}

	public class KaphaBreakfast : IBreakfast{}
	public class PittaBreakfast : IBreakfast{}
	public class VataBreakfast : IBreakfast{}

	public class KaphaLunch : ILunch{}
	public class PittaLunch : ILunch{}
	public class VataLunch : ILunch{}

	public class KaphaSupper : ISupper{}
	public class PittaSupper : ISupper{}
	public class VataSupper : ISupper{}

	class KaphaMealFactory : IAyurvedaMealFactory
	{
		public IBreakfast CreateBreakfast()
		{
			return new KaphaBreakfast();
		}
		public ILunch CreateLunch()
		{
			return new KaphaLunch();
		}
		public ISupper CreateSupper()
		{
			return new KaphaSupper();
		}
	}

	class PittaMealFactory : IAyurvedaMealFactory
	{
		public IBreakfast CreateBreakfast()
		{
			return new PittaBreakfast();
		}
		public ILunch CreateLunch()
		{
			return new PittaLunch();
		}
		public ISupper CreateSupper()
		{
			return new PittaSupper();
		}
	}

	class VataMealFactory : IAyurvedaMealFactory
	{
		public IBreakfast CreateBreakfast()
		{
			return new VataBreakfast();
		}
		public ILunch CreateLunch()
		{
			return new VataLunch();
		}
		public ISupper CreateSupper()
		{
			return new VataSupper();
		}
	}

	class MainClass
	{
		public static void Main (string[] args)
		{
			Console.WriteLine ("It's morning time and there is a kapha tourist");
			Console.WriteLine ("Creating kapha breakfast ...");
			IAyurvedaMealFactory kaphaFactory = new KaphaMealFactory();
			IBreakfast breakfast = kaphaFactory.CreateBreakfast();
			Console.WriteLine(breakfast.ToString());

			Console.WriteLine ("\nIt's noon and there is a pitta tourist");
			Console.WriteLine ("Creating pitta lunch ...");
			IAyurvedaMealFactory pittaFactory = new PittaMealFactory();
			ILunch lunch = pittaFactory.CreateLunch();
			Console.WriteLine(lunch.ToString());

		}
	}
}

Das Interface des Produkts könnte man natürlich benutzen, um Rezepte oder Verzehrempfehlungen zu speichern. Nachteil des Musters: Man muss für jedes Produkt alle Fabriken erweitern. Jede neue Fabrik muss alle Produkte herstellen.

Design Patterns – Strategy

Eine Frage hat mich neulich verblüfft: Welche Design Patterns benutzt du denn so? Obwohl ich umbewusst bestimmt etwas von Design verstehe, kann ich es nicht in Worte fassen. Und dazu dienen ja auch Design Patterns, nämlich um über ein gemeinsames Vokabular bezüglich des Softwaredesigns zu verfügen. Also jetzt werden die Patterns systematisch gepaukt. In meiner unterhaltsamen Ausgabe der Design Patterns, nämlich ‘Head first Design Patterns’ geht es zuerst um das Strategie-Muster. Es ist wohl deswegen so grundlegend, weil es gleich 3 Designprinzipien realisiert.

Hier ein Codebeispiel in C#:

using System;

namespace StrategyPatternExample
{
    public interface IHeatingDemandCalculator
    {
        void Calculate();
    }

    public class SwitzerlandHeatingDemandCalculator : IHeatingDemandCalculator
    {
        public void Calculate()
        {
            Console.WriteLine("Calculating heating demand the switzerland way!");
        }
    }

    public class GermanyHeatingDemandCalculator : IHeatingDemandCalculator
    {
        public void Calculate()
        {
            Console.WriteLine("Calculating heating demand the german way!");
        }
    }

    public class House
    {
		public House()
		{
			_heatingDemandCalculator = new GermanyHeatingDemandCalculator();
		}

        IHeatingDemandCalculator _heatingDemandCalculator;

        public void HeatingDemandCalculator(IHeatingDemandCalculator calculator)
        {
            _heatingDemandCalculator = calculator;
        }

        public void CalculateHeatingDemand()
        {
            _heatingDemandCalculator.Calculate();
        }
    }

	class MainClass
	{
		public static void Main (string[] args)
		{
			House house = new House();
			house.CalculateHeatingDemand();
			house.HeatingDemandCalculator(new SwitzerlandHeatingDemandCalculator());
			house.CalculateHeatingDemand();
		}
	}
}

Für ein Haus soll ein Wärmebedarf berechnet werden.
Die einfachste Möglichkeit wäre, die Berechnung direkt in dieser Klasse in Code zu gießen. Momentan gibt es nur diese eine Klasse. Kommen später jedoch abgeleitete Klassen wie Bungalow oder Mehrfamilienhaus oder Hochhaus hinzu, erben sie alle die selbe Wärmebedarfsberechnung. Wieso nicht? Man kann jetzt vielleicht noch gar nicht sagen, ob diese Berechnung so wichtig ist, dass alle abgeleitete Klassen sie erben müssen. Jede Unterklasse möchte vielleicht die Berechnung anders implementieren. Kommen noch andere Berechnungen hinzu, werden die im selben Maße vererbt. Vielleicht gibt es auch Modellhäuser, die über gar keine Berechnung verfügen sollen, sondern nur der Visualisierung dienen. Dann stehen in der Basisklasse Fallunterscheidungen an, aber den Code möchte man nicht ändern.

Als nächste Möglichkeit, kann eine Berechnung in der abgeleiteten Klasse definiert werden. Dann ists aber mit der Wiederverwendbarkeit dahin. Denn Code wird für 97% der Unterklassen wiederholt.

Hat man einmal das Design Pattern gesehen, gibt es keine andere Lösung: Die Basisklasse bekommt einen Interfacepointer auf IHeatingDemandCalculator, welcher vererbt wird. Sowohl Basisklasse als auch abgeleitete Klassen können die konkrete Implementierung der Berechnung wechseln und gemäß dem Interface immer calculate aufrufen. Nun können für Bungalows, Mehrfamilienhäuse oder Hochhäuser der Wärmebedarf entweder nach deutschem oder schweitzerischen Recht berechnet werden.
Diese Flexibilität erhalten wir dadurch, dass wir 3 grundlegende Designprinzipien berücksichtigt haben:

  1. Identifizere sich ändernde Aspekte und trenne sie von gleich bleidenden Programmteilen
  2. Programmiere gegen ein Interface, nicht gegen die Implementierung
  3. Ziehe Komposition der Vererbung vor

SGF-Player in Silverlight (Teil 2) – 99,1% Plattformunabhängigkeit

Nachdem ich die Machbarkeit eines Webservice erkundet habe, mache ich mich nun an die Implementierung eines Teils der Oberfläche und der Portierung der Logik von meiner letzten Entwicklung eines SGF-Players mit Java.
Als Erstes verpacke ich meine Oberfläche in ein Grid-Layout. Eine Zelle beherbergt eine ViewBox-Element. Wie in SVG werden Inhalte dieser Box skaliert, je nachdem, wieviel Platz sie innerhalb des Gitters im Browserfester zu Verfügung bekommt. Trotzdem kann die Box ein Rectangle in einem Canvas beinhalten, welches 1000 x 1000 Pixel groß ist. Auch wenn die tatsächliche Größe des Rechtecks abweicht, kann ich im Code mit dieser Größe rechnen. Auf diese Weise kann ich ganz einfach meinen Java Code portieren, der ebenfalls mit dieser Größe arbeitet.
Obwohl XAML keinen Standard für Vektorgrafik bietet, kann ich die Konzepte meiner Grafikgenerierung, die ich mit der SVG basierten Java-Bibliothek Batik entwickelt habe, übernehmen. Das Muster des Go-Bretts kommt durch eine große Textur zustande, ein Foto meiner Schreibtischplatte. Das bringt mir 500 KB Übertragungsoverhead ein. Aber in Zeiten der schnellen Leitungen kann ich eine Optimierung verzögern.
Die Portierung der Logik verlief am poblemlosesten. Ich kopierte meinen Java Code mit sehr wenigen Änderungen nach C#. Ich musste etwa die Syntax für mehrdimensionale Arrays oder von Stringoperationen ändern. Ein vollständiges Austauschen der for- in die besser lesbaren und eleganteren foreach-Anweisungen konnte ich mir nicht verkneifen.
Unter Windows flutscht die Anwendung. Rückmeldungen eines Mac-nutzenden Kumpels sind ebenfalls sehr positiv. Die Steine werden fast genauso schnell gesetzt, wie ich klicken kann. Als böse Überraschung finde ich unter Linux Unebenheiten vor. Auf meinem Rechner stellt Moonlight die Steine nicht korrekt dar. Auf dem Rechner meine Frau tut Moonlight es, dafür fehlen bei beiden Rechnern die Schatten. Installiere ich Moonlight 3, wird zwar alles korrekt dargestellt, aber die CPU-Auslastung ist sehr hoch, auch wenn die Anwendung ruhen sollte. Die Frickelei, um herauszufinden, woran es hapert, spare ich mir im Urlaub. Im Forum von go-mono.com habe ich mein Problem geschildert, wieder ohne Antwort. Das erfüllt mich nicht mit Vertrauen und ich hadere einen Moment.
Warum andererseits trauern? Meine Zielgruppe sind Clientnutzer und die benutzen zu 99,1 % Windows oder Macintosh. Es gibt laut Net Market Share nur 0,9% Linuxinstallationen auf dem Desktop. Und hier geht es ja nicht um Jesus, der seine 99 Schafe zurücklässt, um ein verlorenes Schaf zu retten. Und vielleicht macht sich Moonlight ja noch. Und wer interessiert sich schon für Go?
Hier die Anwendung. Die inhaltliche Benutzbarkeit muss natürlich erst noch hergestellt werden.

SGF-Player in Silverlight (Teil 1) – Visual Studio statt MonoDevelop

Ich mag Silverlight. Es wurde tatsächlich von Microsoft mit dem Anspruch entwickelt, plattformunabhängig zu sein. Da Microsoft der .NET-Nachbildung Mono seit den Anfängen von Mono bisher keinerlei Beschränkungen auferlegt hat, ist auch später nicht mit Patentklagen zu rechnen.
Als Demoanwendung will ich wieder einen SGF-Player entwickeln, diesmal fürs Web. Da Unmassen von Go-Spielen nicht bei jedem Aufruf des Players auf den Client geladen werden können, komme ich um einen Webservice nicht herum. Denn Silverlight ist eine Clienttechnologie und kann keine direkte Datenbankverbindung aufbauen.
Ich würde gerne in Silverlight mit meinem privaten Lieblingsbetriebssystem, Linux, entwickeln. Daher probiere ich mit MonoDevelop, einen Webservice zu programmieren. Auf www.webservicex.net finde ich einen Service, der das Symbol eines Unternehmens entgegen nimmt und mir die Aktienwerte zurück gibt.
Informationen, wie ich einen Webservice mit unter Mono entwickele sind spärlich aber ich finde ein repräsentatives Beispiel von Mono selbst. Lege ich mit MonoDevelop ein Moonlight-Projekt an und füge ich eine Webreferenz auf die Adresse des Service hinzu, wird zwar die WSDL (Web Service Description Language)-Datei des Service gefunden und es werden Servicezugriffsklassen generiert. Aber, oh Schande: der generierte Code lässt sich nicht übersetzen. Der Namespace der Zugriffsschicht ist ein ‘.’ und der Code benutzt den Namespace System.Web.Service, welcher in Silverlight nicht existiert. Auf meine Schilderung meines Problems im Forum von www.go-mono.com bekomme ich keine Antwort.
Danke, das wars dann. Ich versuche mein Glück mit dem Visual Studio unter Windows. Es gibt Beispiele wie Sand am Meer und ich kann meinen Service problemlos entwickeln.
Folgenden Codeschnipsel habe ich geschrieben, nachdem ich eine Servicereferenz auf den Webservice gesetzt habe und die Zugriffsklassen fehlerfrei generiert wurden.

Hier der C#-Code:

namespace SilverlightApplication1
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            ServiceReference1.StockQuoteSoapClient proxy = new ServiceReference1.StockQuoteSoapClient();
            //Wire the proxy to a completed handler to allow the async operation to be handled
            proxy.GetQuoteCompleted +=
              new EventHandler<ServiceReference1.GetQuoteCompletedEventArgs>(
            proxy_GetCustomerCompleted);
            //Call the service asynchronously
            proxy.GetQuoteAsync("GOOG");
        }

        void proxy_GetCustomerCompleted(object sender, ServiceReference1.GetQuoteCompletedEventArgs e)
        {
            //Bind the returned data to the DataContext
            System.Windows.Browser.HtmlPage.Window.Alert(e.Result.ToString());
        }
    }
}

Die Antwort des Webdienstes auf “GOOG” ist nachfolgend in XML abgebildet.
webServiceAntwort

Eine Silverlight-Anwendung wird publiziert, indem einfach die HTML- und die dazu gehörige XAP-Datei auf den Server kopiert werden. Das Schöne: Die Anwendung ist tatsächlich plattformunabhängig. Unter Linux funktioniert die Anwendung genauso wie unter Windows. Unter Linux zwar mit einer Meldung, dass es sich um eine Silverlight 3-Anwendung handelt, Moonlight jedoch erst Silverlight 2 abdeckt. Es sei also mit Imkompatibilitäten zu rechnen. Das stört mich allerdings weniger, da die nächste Moonlight Version Silverlight 3 abdecken und im 1. Quartal 2011 heraus kommen soll.
In einer Antwort in einem Forum auf www.go-mono.com habe ich gelesen, dass sich das Mono-Team bisher hauptsächlich auf die Lauffähigkeit von Mono-Anwendungen konzentriert hat statt auf das Bereitstellen einer funktionstüchtigen IDE. Die Erfahrung habe ich hiermit auch gemacht.

Mittelstrenges XML-Schema

Ein zu scharf wachendes Schema, welches XML-Dateien validiert, verdirbt die Freude an der Entwicklung von XML-Strukturen. Das Schema soll so großzügig wie möglich sein, d.h. so viele Knoten und Attribute wie möglich akzeptieren. Andererseits soll das Schema gewährleisten, dass alle zum Betrieb der Anwendung nötigen Daten vorhanden und korrekt sind. Letzteres ist einfach zu erreichen, da XML-Schema von Natur aus restriktiv ist.
Um ein vorhandenes Schema aufzuweichen, dass es auch so großzügig wie möglich ist, habe ich folgende Lösungen gefunden:

1. xs:key statt xs:ID
xs:key stellt die Eindeutigkeit eines Attributes innerhalb eines mit XPath festgelegten Geltungsbereichs des Dokuments sicher. Es können z.B. die Eindeutigkeit von Hotelzimmernummern und von Gästenummern garantiert werden, auch wenn beide Nummernbereiche überlappen. xs:ID ist aber innerhalb des Dokuments global. Außerdem kann ein xs:key-Attribut beliebige Zeichen beinhalten.

2. xs:choice statt xs:sequence
Will man beliebige Kindknoten neben definierten Kindknoten zulassen, könnte man in xs:sequence bestimmte Kindknoten definieren und dann mit xs:any beliebige Knoten zuassen. xs:sequence drängt aber eine Reihenfolge auf. Steht ein Element an erster Stelle, erwartet das Schema auch diesen Typ an erster Stelle.
Definiert man das Inhaltsmodell eines Elements mit xs:choice, muss man alle möglichen Knoten kennen, um eine Auswahl von Kindknoten anzubieten. Andererseits ist dann die Reihenfolge der Kindknoten beliebig. Die Festlegung des XML-Autors auf eine bestimmte Reihenfolge ist aber strenger als die Einschränkung, mögliche Elemente erst dem Schema bekannt zu machen.

3. xs:anyAttribute
Die Reihenfolge von Attributen ist bei XML-Schema beliebig. Will man jedoch, dass ein Schema zusätzlich zu den im Schema definierten Attributen beliebige Attribute akzeptieren soll, erlaubt man diese mit xs:anyAttribute.

MVC – Managed M, Unmanaged VC

Ein neues Projekt beginnt, also habe ich eine neue Chance, endlich sauber nach MVC zu programmieren. Zusätzlich wollen wir das Modell managed in C# programmieren. Das Modell betrachten wir hiermit als das wertvollste Stück und erhalten die Möglichkeit es in neuen Programmgenerationen wieder verwenden zu können. Also die Abspaltung des Modells ist gut, die weitere Sonderstellung als verwaltete Komponente in einem unverwalteten System könnte weitere Vorteile bringen. Letzteres steht aber noch unter Beobachtung. Schließlich erfordert es weiteren Aufwand. Fast hätte ich es vergessen: Das Modell kann testgetrieben entwickelt werden. Das bringt Agilität in die Entwicklung einer komplexen Logik und macht diese einfach nachvollziehbar.

Idealerweise alles managed

Nach der reinen Lehre wird das MVC Entwurfsmuster sauber eingesetzt, indem das Modell das Observable-Interface und verschiedene Views das Observer-Interface implementieren. Der Controller greift einseitig verändernd auf das Modell zu. Wird das Modell geändert, werden alls horchenden Views, nachdem sie sich beim Modell registriert haben, benachrichtigt. Danach holen sie sich die nötigen Informationen vom Modell ab. Durch das Observer-Interface kennt das Modell von den Views nur die eine Methode notify

Eine Modellklasse Bauteil könnte etwa so aussehen:


public class Bauteil
{
	public String Beschreibung { get; set; }
	public event EventHandler BauteilChanged;
	private double _Betriebsspannung = 0;
	public double Betriebsspannung
	{
		get
		{
			return _Betriebsspannung;
		}

		set
		{
			_Betriebsspannung = value;
			EventHandler handler = BauteilChanged;
			if (handler != null)
			{
				handler(this, EventArgs.Empty);
			}
		}
	}
}

Ich meine, Degaten und Events überträfen Interfaces in ihrer Eleganz. Deswegen entwerfe ich hier das Observer/Observable-Muster Modellseitig mit einem Event public event EventHandler BauteilChanged; und viewseitig kann in folgendem Observer die Methode void HandleEvent(Object^ sender, EventArgs^ args) als Delegat gekapselt und dem Event des Bauteils hinzugefügt werden:

ref class Observer
{
	public:
		Observer()
			:eventcount (0)
			, lastSender (NULL)
		{}

	void HandleEvent(Object^ sender, EventArgs^ args)
	{
		eventcount++;
		lastSender = sender;
	}

	int eventcount;
	Object^ lastSender;
};

Folgender Unittest beweist mir, dass das Zusammenspiel funktioniert:

[TestMethod]
void MultipleObjectsSendsUpdate()
{
	Bauteil^ bauteil = gcnew Bauteil();
	Observer^ observer = gcnew Observer();

	EventHandler^ handler;
	handler = gcnew EventHandler(observer, &Observer::HandleEvent);

	bauteil->BauteilChanged += handler;
	bauteil->Betriebsspannung = 50;

	Assert::AreEqual(true, observer->eventcount == 1);
	Assert::AreEqual(true, observer->lastSender == bauteil);

	Bauteil^ bauteil2 = gcnew Bauteil();
	bauteil2->BauteilChanged += handler;
	bauteil2->Betriebsspannung = 100;

	Assert::AreEqual(true, observer->eventcount == 2);
	Assert::AreEqual(true, observer->lastSender == bauteil2);
};

Eingeschränkte Komplexität

Über die managed/unmanaged-Grenze können die Informationen nicht so ungehindert wie oben beschrieben fließen. Würde man alles beherrschen wollen, müsste man das Design so fassen, dass Controller wie Views entweder managed oder unmanaged sein können. Auch müsste man die Zugriffe auf das verwaltete Modell von einem unverwalteten Controller kapseln und die Nachrichten von dem verwalteten Modell zu den unverwalteten Views ebenso. Hier kommt man nicht umhin, die Komplexität zu beschränken. Wir haben uns für unser Design entschieden, dass das Modell nur verwaltet ist und Controller wie Views nur unverwaltet sein können. Daraus resultiert, dass die Vermittlungsschicht, der ModelAgent, hauptsächlich das Design umsetzt. Der ModelAgent hat ein unverwaltetes Interface und eine verwaltete Implementierung, die auf das Modell zugreift. Er nimmt Anfragen des Controllers entgegen, registriert Views und entscheidet, ob diese benachrichtigt werden sollen.

XML-Validator über die managed/unmanaged-Grenze

Wir stützen uns mehr und mehr auf XML-Dokumente. Das hält die Typenvielfalt im Code geringer und die Datenvielfalt kann dort explodieren, wo sie hingehört. Und es ermöglicht dem Fachpersonal auch ohne C++ oder ähnlich komplizierte Sprachen zu ‘programmieren’. XML-Dokumente und XSD sind menschenlesbar und spiegeln genau die Struktur und den Stand der Daten wider. Daten können auch ebenso direkt wie einfach geändert werden, ohne qualifizierte Programmierer zu bemühen. Routinearbeit wie das Eingeben von Daten kann ausgelagert werden und der Programmierer kann sich wieder dem Wesentlichen wie dem Design der Anwendung widmen.
Ein XML-Schema in Form einer oder mehrerer XSD-Dateien hilft, die Struktur der XML-Daten zu spezifizieren und deren Gültigkeit zu überprüfen. Natürlich kann die Gültigkeit auch programmatisch verifiziert werden. Und warum ungültige Datein einlesen? Wenn man denn ein Schema besitzt, sollte man tunlichst die Daten dagegen validieren. Die Anwendung wird dadurch stabiler und die Fachkraft der Domäne kann informative Rückmeldungen seitens der Software bekommen.
Nun habe ich einige Zeit geforscht, wie man XML gegen ein XSD in C++ mit der msxml6.dll überprüft. Da gibt es auch einige Beispiele aber keins hat auf Anhieb funktioniert. Der Beispielcode, darunter Beispiele von Microsoft, mutet archaisch an und viele Datentypen, welche aus der C-Urzeit kommen, sind mir nicht bekannt. Zu kompliziert für meinen Geschmack und ich überlege mir, wieso eigentlich nicht Richtung .NET gehen? Auf meiner Suche nach C#-Code werde ich sofort fündig und als ich das abgetippte Progrämmchen ausprobiere, tut es genau das Erwartete. Also lege ich eine neue DLL für .NET-Auslagerungen an. Denn C# kann ich nicht in ein C++-Projekt hineinmischen. Ich kann C# auch nicht direkt in unmanaged C++ aufrufen. Dafür brauche ich eine Zwischenschicht in C++/CLI. Ich kann eine einzelne Datei in einem C++-Projekt managed kompilieren. Code darin kann von unmanaged heraus aufgerufen werden und seinerseits C#-Objekte instanziieren und benutzen. Ich denke an die Zukunft, in der ich vermehrt C#-Code mit der alten Welt verbinden möchte und überlege mir, ob es nicht besser ist, mein Ziel direkt in C++/CLI zu erreichen. Im Nachhinein widerum denke ich eher, dass C++/CLI doch als Vermittlungsschicht geeignet ist und dass man neue Zeilen bevorzugt in C# schreiben sollte. Aber sei es drum, ich werde dem Thema auf den Fersen bleiben und liste nachfolgend erst einmal den C++/CLI-Code auf.

namespace XMLUtilities
{
ref class Validator
{
public:
	String^ ErrorDescription;
	Validator(Stream^ xmlstream, XmlReader^ xsddocument)
	{
		XmlReaderSettings^ settings = gcnew XmlReaderSettings();
		settings->ValidationType = ValidationType::Schema;

		XmlSchemaSet^ schemas = gcnew XmlSchemaSet();
		settings->Schemas = schemas;

		try
		{
			schemas->Add("", xsddocument);
		}

		catch (Exception^ err)
		{
			ErrorDescription = err->ToString();
		}
		settings->ValidationEventHandler += gcnew ValidationEventHandler(this, &Validator::HandleError);
		XmlReader^ validator = XmlReader::Create(xmlstream, settings);

		try
		{
			while (validator->Read()) { }
		}
		catch (Exception^ err)
		{
			ErrorDescription = err->ToString();
		}
		finally
		{
			validator->Close();
		}

	}
private:
	void HandleError(Object^ sender, ValidationEventArgs^ args)
	{
		ErrorDescription = args->Message;
	}

};

_declspec(dllexport) CString ValidateXMLString(CString xmlstr, CString xsdstr  )
{
	array<Byte>^ byteArray = Encoding::UTF8->GetBytes(CStringToString(xmlstr));
	MemoryStream^ xmlstream = gcnew MemoryStream(byteArray);

	XmlReader^ xsddocument = XmlReader::Create(gcnew StringReader(CStringToString(xsdstr)));

	Validator v (xmlstream, xsddocument);
	return StringToCString(v.ErrorDescription);
}

_declspec(dllexport) CString ValidateXMLFile(CString xmlfile, CString xsdfile)
{
	FileStream^ xmlstream = gcnew FileStream(CStringToString(xmlfile),  FileMode::Open, FileAccess::Read);
	FileStream^ xsdstream = gcnew FileStream(CStringToString(xsdfile),  FileMode::Open, FileAccess::Read);

	XmlReader^ xsddocument = XmlReader::Create(xsdstream);

	Validator v (xmlstream, xsddocument);
	xmlstream->Close();
	xsdstream->Close();
	return StringToCString(v.ErrorDescription);
}
}

Da ich meinen Code sehe, erkenne ich, dass ich den Validator nicht als ref class schreiben müsste. Eine ref class kann ich von C# aus benutzen. Diesen Typ definiert man für Verbindungen aus der abstrakteren .NET-Welt hin zu der schnellen nativen C++-Welt. Ich will aber hier in die andere Richtung gehen. Natürlich habe ich meinen Code testgetrieben entwickelt. Gerade, wenn man mit vielen neuen Dingen einer Programmwelt ausgesetzt ist, bieten sich Tests an, um programmatisch Herr der Lage zu werden. Für die Tests möchte ich dem Validator manuell geschriebene Daten geben, der Produktivcode möchte konkrete Dateien validiert bekommen. Ich abstrahiere also meinen Validator, dass er keine Dateien kennt und für beide Fälle jeweils mit den gleichen Argumenten initialisiert wird. Dann schreibe ich für Tests und Produktivcode zwei Funktionen, die aus Strings bzw. Dateien jeweils die gleichen Übergabewerte für den Validator erzeugen (_declspec(dllexport) deshalb, weil ich die Funktionen aus der DLL exportiere).

Gerne hätte ich aus dem Validator heraus die verschiedenen Exceptions geworfen, doch in C++ Coding Standards lese ich, dass man so etwas nicht über Modulgrenzen hinaus tun sollte (Keine Steine in des Nachbarn Garten werfen). Nachfolgend werden die Unittests aufgelistet:

[TestInitialize()]
void MyTestInitialize()
{
	XSDString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
		"<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" >" 

		"<xsd:simpleType name=\"Status\">"
		"<xsd:restriction base=\"xsd:string\">"
		"<xsd:enumeration value=\"Angestellter\"/>"
		"<xsd:enumeration value=\"Freiberufler\"/>"
		"<xsd:enumeration value=\"Rentner\"/>"
		"</xsd:restriction>"
		"</xsd:simpleType>"

		"<xsd:element name=\"Person\" >"
		"<xsd:complexType>"
		"<xsd:attribute name=\"Status\" type=\"Status\"></xsd:attribute>"
		"</xsd:complexType>"
		"</xsd:element>"

		"<xsd:element name =\"Root\">"
			"<xsd:complexType>"
				"<xsd:sequence>"
					"<xsd:element ref =\"Person\" minOccurs=\"1\" maxOccurs=\"unbounded\"/>"
				"</xsd:sequence>"
			"</xsd:complexType>"

		"</xsd:element>"

		"</xsd:schema>";

	XMLString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
		"<Root >"
		"<Person Status=\"Angestellter\" >"
		"</Person>"
		"</Root>";

};

[TestMethod]
void CPPXMLStringValidatorWorks()
{
	CString error = XMLUtilities::ValidateXMLString(XMLString, XSDString);
	Assert::AreEqual (error.IsEmpty(), true);
};

[TestMethod]
void ValidatorXMLSchemaException()
{
	XSDString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
		"<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" >"
		"<xsd:element name =\"Kontakt\" minOccurs=\"1\" maxOccurs=\"Sonnenschein\">"
		"<xsd:complexType>"
		"<xsd:sequence/>"
		"</xsd:complexType>"
		"</xsd:element>";

	CString error = XMLUtilities::ValidateXMLString("", XSDString);
	Assert::AreEqual (!error.IsEmpty(), true);

};

[TestMethod]
void CPPValidatorXMLException()
{

	XMLString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
		"<Root >"
		"<Datenblaetter >"
		"<Datenblatt Description=\"Steckdosen\" ID=\"St1\" LongDescription=\"Steckdosen lang\">"

		/*"</Datenblatt>"*/
		"</Datenblaetter>"
		"</Root>";

	CString error = XMLUtilities::ValidateXMLString("", XSDString);
	Assert::AreEqual (!error.IsEmpty(), true);

};

Installiert is’

Kubuntu hat im Endeffekt nicht meinen Gefallen gefunden. Selbst Linus Torvalds, der sich negativ gegenüber Gnome geäußert hat und Verfechter von KDE gewesen ist, hat jetzt nach Gnome umgeschwenkt. KDE ist mit neuen, unausgereiften Funktionen überfrachtet, die nicht zusammenpassen und es funktioniert nicht fehlerfrei. Dass ich die Bildschirmeinstellungen von Hand in eine Datei schreiben musste, damit sie gemerkt werden und aushilfsweise Nautilus als Dateimanager benutzen musste, um Daten-CDs zu mounten sind nur einige von unzähligen Fehlerchen. Genervt hat mich z.B. auch, dass die Netzwerkverbindung nach dem Hochfahren ein bisschen zu spät hergestellt wurde, so dass der Firefox mit lauter Tabs startete, deren Inhalt nicht aus dem Netz bezogen werden konnte. Das mag nur subjektiv empfunden sein, aber so kommt Eins zum Anderen. Den Grafikkartentreiber musste ich gänzlich deinstallieren, damit Filme, die ich manchmal sehe, schlierenfrei laufen. Nach Deinstallation musste ich mit den Default-Möglichkeiten zum Betreiben von 2 Monitoren vorlieb nehmen, welche ebenfalls keine Perfektion bieten. Viel Gefrickel also.
Mh, warum hatte ich mir danach noch OpenSuse installiert? Ich dachte mir, hier funktioniert KDE besser. Denn man sagt ihr ja nach, bessere KDE-Unterstützung als Kubuntu zu bieten. Dem war aber nicht so. Ich entdeckte haargenau dieselben Fehler. Entnervt gab ich auf, als ich mit Dolphin wegen eines Bugs nicht auf meine lokalen Windows-Partitionen zugreifen konnte. Es liegt also an KDE.
Als nächstes habe ich mir Linux Mint Isodora installiert und: OH WUNDER!!! Das ist ein sehr schönes, funktionierendes System! Das Problem mit dem proprietären Grafikkartentreiber, welches ich neulich bei der Installation von Ubuntu hatte, ist verschwunden. Da Linux Mint auf Ubuntu basiert, nehme ich an, dass der Bug jetzt behoben wurde.
Was ich zusätzlich tun musste, um mir das System einzurichten, kann man nicht als Gefrickel bezeichnen. Da der Firefox bei den Schriften aus der Rolle fällt, habe ich mit sudo rm /etc/fonts/conf.d/10-hinting-slight.conf
und
sudo ln -s /etc/fonts/conf.avail/10-hinting-full.conf /etc/fonts/conf.d/
das volle Hinting noch übertragen müssen.
Das Meißte, was man nach einer frischen Installation braucht, kann man eh ab aktuellem Ubuntu leicht mit dem Paket ubuntu-restricted-extras nach installieren.
Da ich mir neulich einen SGF-Player in Java entwickelt habe, welcher SVG-Dateien live manipuliert, musste ich erreichen, dass dies unter Ubuntu korrekt dargestellt wird. Denn die Kugeln waren plötzlich eckig. Ich war ratlos, wo doch Gnome Vorreiter in der SVG-Nutzung ist. Doch zum Glück hatte ich noch ein anderes Problem. Ebenfalls unter Java läuft mein KGS-Client, mit dem ich übers Netz Go spiele und ich hörte das Knacken nicht, welches beim Spielen eines Steins produziert werden soll. Der Sound hilft aber schwer, mich aufs Spiel zu konzentrieren. Nachdem ich sehr viel probiert habe, wechselte ich die Javapakete von openjdk nach sun-java. Und siehe da, alles funktionierte sauber. Außer dass die Maserung des Go-Bretts bei meinem Player verschwindet, wenn ich das Fenster maximiere. Naja, ich denke mir, bei meinen exotischen Wünschen kann ich keine Perfektion erwarten. Bei Windows allerdings schon. In punkto Ästhetik ist Windows einfach weiter. Auf jeden Fall ist openjdk die offene Variante von Java, es sind aber erst 94% implementiert. Sound und SVG gehören wohl zu den nicht implementierten 6%.
Heute beschäftigte ich mich noch mit dem Netzwerk. Gerne möchte ich öfter etwas übers Netz auf den Rechner meiner Frau kopieren. Sowohl über die Protokolle smb und sftp als auch über die Befehle scp und rcp kam ich nicht über eine Rate von 100 kB/s. Installation des WLAN-Kartentreibers brachte dann jedoch den ersehnten Durchsatz von ca. 2 MB/s.

SGF Player mit Java und Batik – 2

Schönheit First

Mich interessiert zuerst, wie ich in SVG ein äußerlich passables Go-Brett mit Steinen hinbekomme. Im Netz finde ich ein mit Inkscape erzeugtes welches. Der SVG-Code ist gruselig: Die Koordinaten für die Gitterpunkte des Brettes haben etliche Nachkommastellen und die Datei enthält viel zu viele Knoten, welche ich nicht verstehe und nicht brauche. Unverständlicher, generierter Code, den ich nicht programmatisch manipulieren möchte, da ich an die Koordinaten und Knoten schlecht heran komme. Also schreibe ich mir meinen SVG-Code anhand von W3C-Spezifikation und Beispielen selber. Als erstes erzeuge ich mir mit dem SVG-Attribut ViewBox ein eigenes Koordinatensystem. Dieses Koordinatensystem lässt sich als Auflösung auffassen. Ich sage damit, wie groß meine Auflösung immer ist, egal, wieviel Platz ich tatsächlich zur Verfügung habe. Das macht mein SVG-Dokument skalierbar.
Für das Holzbrett zeichne ich nun ein Rechteck in hellbraun. Da ich unbedingt eine Art Holzmaserung sehen will und andernfalls nicht auf das Brett gucken kann, definiere ich mir für das Rechteck einen Filter, der aus den Effekten feTurbulence und feDiffuseLighting besteht.
Das Gitter zu zeichen ist trivial, doch das mache ich lieber in Java mit einer for-Schleife, da ich dann alle Abstände zentral ändern kann, statt 19 mal 19 Linien händisch zu programmieren. Um die Steine zu zeichnen definiere ich mir für schwarze und weiße Steine jeweils einen radialGradient-Knoten und einen Filter für den Schatten. Nachdem ich probeweise einige Steine gezeichnet habe, sehen diese zwar ganz reizend aus, aber wenn der Schatten zu groß ist, fällt er über den benachbarten Stein. Ich finde auf Anhieb keine Lösung, bin aber damit zufrieden, wenn der Schatten nur 1 Pixel breit ist und dieser bei einem Abstand eines Steines vom nächsten von ebenfalls 1 Pixel nur noch aufs Brett fällt.
Nun fange ich an, für ein Spiel Stein für Stein aufs Brett zu zeichnen, indem ich die ‘Logik’ ausblende. Die Logik besteht daraus, dass auch Steine vom Brett genommen werden müssen, wenn ein gesetzter Stein eine Gruppe gegnerischer Farbe berührt und dieser die letzte Freiheit nimmt. Ich möchte am liebsten pro Zug alles neu darstellen und alle Steinknoten dem SVG Dokument neu hinzufügen. Doch je mehr Steine ich hinzufüge, desto länger dauert es. Da die Verzögerung deutlich erkennbar ist, brauche ich eine Lösung. Im Netz kursiert der Vorschlag, vom SVG-Dokument ein Fragment abzuspalten und alles nötige zuerst dem Fragment anzuhängen, bevor das Fragment als Ganzes in das Dokument eingefügt wird. So müsse die Darstellung des Dokuments nur einmal gerechnet werden. Leider schafft auch dieser Vorschlag keine wesentliche Abhilfe. Deshalb gebe ich jedem Steinknoten eine eindeutige ID und füge nur einen neuen Knoten hinzu, wenn es ihn noch nicht gibt.

Logik

Da die Darstellung der kleinen Anwendung nun flüssig läuft und schön aussieht, kann ich mich nun der Logik zuwenden. Ein Zug verändert den Zustand des Brettes. Ein Zustand ist vom vorherigen Zustand abhängig. Wie kann ich es erreichen, dass ich wahllos zu irgendeinem Brettzustand eines Spiels springen kann, z.B. Zug n? Ich muss für Zug n den Zustand aus den voran gegangenen n-1 Zuständen errechnen. Meine eigenen Gedanken zum Thema Freiheiten von Steinen berechnen und diese Steine nahtlos vom Brett entfernen, erscheinen mir sehr kompliziert und ich schaue mir den offenen Quellcode von qgo an. Dieser Code ist in C++ geschrieben und ich finde sofort, was ich brauche. In dem qgo-Modell existieren Gruppen von Steinen. Beim Setzen eines Steins wird geprüft, ob er einer Gruppe angehört. Dabei wird Stein für Stein geschaut, ob der neue Stein von der Position her ein nördlicher, südlicher, westlicher oder östlicher Nachbar sein könnte. Gehört er zwei Gruppen an, werden die zwei Gruppen zu einer Gruppe verbunden und der Stein hinzugefügt. Gehört er keiner Gruppe an, wird aus ihm eine neue gebildet. Weiter wird pro Zug der Stand der Freiheiten der Gruppen anhand des Brettzustands berechnet. Hat mindestens ein Stein einer Gruppe einen benachbarten Punkt, der weder von einem weißen noch einem schwarzen Stein besetzt ist, besitzt die Gruppe Freiheit. Hat die Gruppe keine mehr, wird sie gelöscht, nachdem Stein für Stein dieser Gruppe vom Brett genommen wird. Es wird also pro Zug allerhand berechnet, aber das geht immer noch schneller, als ich klicken kann.
Zum Schluß hätte ich gerne noch alle 40.000 Spiele, die ich in einer viele MB großen Datei beherberge, in einer übersichtlichen Tabelle. Dort möchte ich Spiele anhand von Spielernamen, Turnier und Datum filtern können. Dies habe ich mir schon einmal mit F# in .NET programmiert. Aber wie ich festellen muss, sind es in Java mehr Zeilen und geht nicht so leicht von der Hand. Die string.split() Funktion in Java ist nämlich viel zu langsam, da sie einen regulären Ausdruck als Argument erwartet. Zum parsen des Strings, der alle Spiele enthält, muss ich ihn char für char begutachten, mir Positionen von Spieltrennern merken und pro Spiel einen Substring aus dem Gesamtstring extrahieren. Auch das läuft nach einigen Optimierungen flüssig, so dass der Import nur ein paar Sekunden dauert.

So sieht der Player aus:
SGF_Player_Batik_Swing

Sogar mein 4-jähriger Sohn kann auf diese Weise Profi-Partien nachspielen! Züge können in der geschwindigkeitsverstellbaren Animation äußerst gut gefunden werden, statt in einem PDF-Dokument, welches 50 Züge als Zahlen beinhaltet, suchen zu müssen.

SGF Player mit Java und Batik – 1

Ich schaute mir ja so gerne Amatuerpartien von hochrangigen Go-Spielern auf dem KGS-Server an. Doch jetzt schaue ich mir, seit dem ich mir einen SGF Player entwickelt habe, lieber Profi-Partien an. Als ich mit einem Kollegen über mein Vorhaben sprach, war sein erster Rat: SVG. Dieses Format findet demnächst seinen Weg in den Internet Explorer 9 und in den Firefox ist es jetzt schon integriert. Erste Erkundungen waren beeindruckend. SVG öffnet einen Weg, Spiele in den Browser zu bringen, indem SVG-Inhalte, die sich im DOM befinden, über Javasript manipuliert werden können. Doch wie viele Enwtickler machte ich um Javascript bisher einen weiten Bogen. Lange gab es für die Entwicklung mit Javascript keine IDE, was sich jetzt eigentlich geändert haben dürfte. Aber eine neue Technologie, nämlich SVG, ist mir erst einmal genug. Ich will Schritt für Schritt vorgehen und nur eine neue Sache auf einmal lernen. Und schließlich muss es nicht direkt ins Web. Mein Blick fällt auf die Bibliothek Batik, welche die Manipulation von SVG mittels der mir vertrauten Sprache Java ermöglicht. Das Beispiel sieht denn auch sehr vielversprechend aus: Es ist sogar möglich, ein Applet zu entwickeln, welches sehr wohl übers Web ausgeführt werden kann.
Als nächstes entscheide ich mich für die NetBeans IDE und binde die Batik-Archive in mein Projekt ein. NetBeans behagt mir auf Anhieb. Die Bedienung ist sehr ähnlich zum Visual Studio. Im Gegensatz zur C++-Unterstützung von Visual Studio kann ich hier jedoch sehr bequem Klassen oder das Projekt umbennennen, Code refaktorisieren und fehlende Importe einfügen. Da ich jetzt doch wieder einen Haufen neuer Technologien auf einmal vorfinde, will ich zunächst die Batik Beispielanwendung in eine Swing-Anwendung überführen.
Das Ergebnis:

Batik-Beispiel in Java Swing - klein

Batik-Beispiel in Java Swing - klein


Batik-Beispiel in Java Swing - groß

Batik-Beispiel in Java Swing - groß

Das Ergebnis stellt mich sehr zufrieden und entspannt lehne ich mich zurück. Mit Java unter Linux bin ich zufrieden. Swing schnurrt schnell und Anwendung und IDE, die ebenfalls in Java programmiert ist, laufen flüssig. Das SVG-Dokument ist interaktiv über Java manipulierbar und die Manipulation verläuft ohne Flackern. Das Ergebnis ist frei skalierbar, ohne, dass ich hierfür Aufwand betreiben müsste. Die Technologien sind gefunden, um meinen ersten SGF-Player zu verwirklichen.