Archiv

Archive for September 2011

Kurz-Tipp: IIS Express in Visual Studio verwenden

30. September 2011 5 Kommentare

Wer mit Visual Studio eine Webanwendung entwickelt wird häufig den eingebauten Webserver Cassini nutzen. Dieser funktioniert für die meisten Anwendungen ohne Probleme. Will man aber schon zur Entwicklungszeit einige IIS-spezifische Funktionen verwenden, stösst man damit schnell an die Grenzen. IIS Express ist in solchen Fällen eine gute und einfach zu konfigurierende Alternative zum ausgewachsenen IIS.

 

IIS Express installieren

Der einfachste Weg zur Installation von IIS Express führt über den Web Platform Installer. Mit diesem Tool kann man über eine einfache Maske diverse Web-Pakete (von PHP bis WordPress) mit einem Klick installieren. Als Alternative kann man den direkten Link aufrufen der einem gleich den IIS Express auswählt.

 

In Visual Studio nutzen

Um IIS Express zu nutzen muss man den Einstellungsdialog des gewünschten Webprojektes öffnen. Im Reiter Web kann man unter Servers den IIS Express auswählen. Die Projekt-URL kann einen beliebigen Zusatz haben oder nur aus localhost und einem Port bestehen.

Wichtig: Nach dem man die gewünschte URL eingegeben hat muss man das virtuelle Verzeichnis anlegen.

Startet man das Webprojekt nun mit F5 wird IIS Express verwendet. Will man doch wieder Cassini nutzen wählt man einfach auf der gleichen Maske den Development Server aus.

 

Fazit

IIS Express ist sehr schnell konfiguriert und man kann problemlos jederzeit wieder zurück zu Cassini. Wer mit Cassini Probleme hat (zum Beispiel wenn die Webanwendung immer wieder abstürzt) kann so in kurzer Zeit auf IIS Express wechseln und überprüfen ob das Problem vom Webserver abhängt oder doch selber verursacht wurde.

Schlagworte: , ,

Buch-Rezension zu „Jenkins – The Definitive Guide”

26. September 2011 Kommentare aus

Jenkins – The Definitive Guide” von John Ferguson Smart erschien im Juli 2011 bei O’Reilly. Jenkins ist ein in Java geschriebener Build-Server der von Nightly Builds bis zu Continuous Deployment alles abdecken kann.

[Hinweis: Ich habe dieses Buch über die .Net User Group Bern erhalten, die am User Group Programm von O’Reilly teilnimmt. Wie immer wenn ich über Bücher blogge schreibe ich was mir daran gefällt und was nicht. Dies mache ich unabhängig davon ob ich ein Rezensionsexemplar bekomme oder das Buch selber kaufe.]

 

 

Hudson oder Jenkins?

Ursprünglich war der Build-Server unter dem Namen Hudson bekannt. Nachdem die Spannungen zwischen Oracle (dem Inhaber der Namensrechte) und den Entwicklern immer grösser wurden gab es Anfang 2011 einen Fork. Die meisten Entwickler entschlossen sich das Projekt unter dem Namen Jenkins fortzuführen.

Die meisten Punkte die im Buch erklärt werden gelten sowohl für Jenkins wie auch für Hudson. Da Jenkins aber immer noch jede Woche eine neue Version heraus gibt und Hudson nur alle 1 bis 2 Monate, werden die Projekte langsam aber sicher auseinander laufen. Wer über eine Migration von Hudson nach Jenkins nachdenkt sollte diese möglichst zügig angehen. Wer neu startet und den Support von Oracle nicht benötigt kann gleich mit Jenkins anfangen.

 

Von Nightly Builds zu Continuous Delivery

Continuous Integration (CI) ist mittlerweile ein Begriff mit vielen Definitionen. Für die einen ist CI erreicht wenn man einen Nightly Build hat, für die anderen erst wenn damit auch bei jedem Check-in alle Tests ausgeführt werden. Smart zeigt zu Beginn des Buches dass dies kein Wiederspruch ist. Vielmehr sind es einzelne Phasen in der Verwendung von CI. Er gliedert diese so:

  1. Kein Build Server – Entwickler bauen alles auf ihren eigenen Geräten
  2. Nightly Builds – 1x pro Nacht wird alles auf einem zentralen Server gebaut
  3. Nightly Builds und erste automatisierte Tests nach jedem commit
  4. Erste Schritte mit Code Metriken (wie Testabdeckung und Qualitätskontrolle)
  5. Test-Driven Development und automatisches deployment auf Testsystem
  6. Automatisierte Akzeptanztests und Möglichkeit fürs deployment auf Produktion
  7. Continuous Deployment – wenn alle Tests bestanden sind wird automatisch auf die Produktion deployt

Man muss weder alle Phasen durchlaufen noch diese Reihenfolge einhalten. Hat man das fürs Projekt notwendige umgesetzt kann man jederzeit aufhören – ein automatisches Deployment ist keine Pflicht.

 

Erste Schritte, Installation und Konfiguration

Das Buch führt einem durch alle Schritte die nötig sind um Jenkins zu installieren und in Betrieb zu nehmen. Neben den verschiedenen und plattformspezifischen Installationsmöglichkeiten wird erklärt wie man Jenkins dazu bekommt mit den gängigsten Versionsverwaltungssystemen (wie Subversion, Mercurial, Git und CVS) zu kommunizieren und E-Mails zu verschicken. Letzteres ist besonders dann wichtig, wenn der Build fehlschlägt – sonst bleibt dies bis zum Release unbemerkt…

 

Build Jobs und automatisches Testen einrichten

Das Kapitel zum aufsetzen der Build Jobs lässt keine Fragen offen. Hat man die Arbeitsschritte mit einem Build-Tool wie Ant oder Maven bereits automatisiert kann man die entsprechenden Projektvorlagen nutzen und braucht nur die jeweiligen Kommandos einzutragen. Es wird aber auch erklärt wie man all die Schritte selber konfigurieren kann, was gerade für Projekte in .Net oder Ruby sehr hilfreich ist.

Die Jobs können zu bestimmten Zeiten, manuell oder nach jeder Änderung in der Versionsverwaltung starten – für alles gibt es wiederum eine detaillierte Anleitung um Jenkins entsprechend einzurichten.

Bei den automatischen Tests will man in der Regel eine Antwort auf 2 Fragen:

  1. Sind alle Tests erfolgreich?
  2. Wie viel Code wird von meinen Tests abgedeckt?

Jenkins führt die Tests aus und gibt die Resultate an Plugins weiter die sich um die Analyse und die grafische Aufbereitung der Resultate kümmern. Auch deren Konfiguration und Einbindung in die Jobs wird wiederum ausführlich erklärt.

 

Jenkins absichern und verteilte Builds

Nach den grundlegenden Themen die jeder Jenkins Benutzer benötigt geht das Buch auch auf weiterführende Themen ein. Hat man nur eine kleine Gruppe die mit Jenkins arbeitet wird man oft nicht gross über Zugangsbeschränkungen nachdenken. Wird dies ein Thema bietet Jenkins dazu verschiedenste Möglichkeiten an, sogar eine Anbindung an Active Directory ist machbar und wird von Smart beschrieben.

Ob man verteilte Builds nutzen will hängt ebenfalls vom Anwendungszweck ab. Dabei ist nicht alleine die nötige Geschwindigkeit eines Servers ausschlaggebend. Der Bedarf nach unterschiedlichen Konfigurationen kann ebenfalls dafür sprechen. Im Buch wird als Beispiel die Durchführung von Integrationstests mit verschiedenen Datenbanken auf verschiedenen Applikationsservern durchgespielt.

 

Build-Tool zur Vereinfachung

Über das ganze Buch hinweg sieht man immer wieder wie kompakt die Konfiguration von Jenkins ist wenn man auf ein Build-Tool wie Maven zurückgreifen kann. Die zusätzliche Konfiguration in Maven ist sehr oft kleiner als was man bei Jenkins einstellen muss um das gleiche Resultat zu erzielen.
Da jeder Entwickler mit dem Build-Tool die gleichen Befehle lokal ausführen kann gibt es nach dem commit auch keine Überraschungen.

Daher sollte man vor man Aufbau eines Build-Servers fragen ob man nicht zuerst die Konfiguration für ein Build-Tool erstellen will. Dieser zusätzliche Aufwand kann sich schnell auszahlen.

 

Braucht es für Jenkins wirklich ein Buch?

Das GUI von Jenkins ist sehr übersichtlich und mit der Online-Hilfe kommt man sehr weit. Wenn man ein Java-Projekt hat das bereits Ant oder Maven nutzt kann man sehr schnell und einfach zu ersten Erfolgen kommen – auch ohne Buch.

Ich nutze Jenkins/Hudson seit mehreren Jahren sowohl für kleine Java-Projekte wie auch für ein grosses Kundenprojekt in .Net. Das Buch lieferte mir etliche Anregungen um die alltäglichen Arbeiten einfacher zu erledigen. Ein klein wenig mehr Aufwand und die Konfiguration ist deutlich flexibler als das was ich in den Jahren des Anwendens selber heraus getüftelt hatte. Für komplexe Aufgaben (wie die verteilten Builds oder eine AD-Anbindung) konnte ich etliche Anregungen holen.

Das Buch ist meiner Meinung nach sehr gut um sich schnell in Jenkins einzuarbeiten. Man kann vom grossen Wissen des Autors profitieren und hat ein kompaktes Nachschlagewerk zu allen Belangen von Jenkins.

 

Was fehlt

Ich hätte gerne noch mehr Informationen zur Konfiguration für Nicht-Java Projekte gehabt. Das Buch hilft einem bei den ersten Schritten, doch weiterführende Teile fehlen danach leider. Nicht jeder will (oder kann) Maven und Ant nutzen. Mehr Informationen und Beispiele zu anderen Build-Tools hätte ich ebenfalls sehr begrüsst.

Leider sind die Konfigurationsbeispiele nicht einzeln herunterladbar. Auf der Webseite des Autors gibt es dafür das ganze Buch als PDF (Open Book mit Creative Commons Lizenz). Über diesen Umweg kommt man dann doch noch an die Beispiele.

 

Fazit

Das Buch bietet sowohl für Neulinge wie auch für fortgeschrittene Nutzer von Jenkins viele Tipps und Praxiswissen um einen Build-Server aufzubauen und ins Entwicklungsprojekt zu integrieren. Wer sich mit Jenkins beschäftigen will sollte unbedingt einen Blick ins Buch werfen.

 

Zum Buch

Jenkins – The Definitive Guide” von John Ferguson Smart, 2011 O’Reilly, ISBN 978-1-449-30535-2, 406 Seiten, Englisch

Karte von OpenStreetMap auf eigenem (Garmin) Navi nutzen

24. September 2011 3 Kommentare

Die Karte von OpenStreetMap kann man auch auf dem eigenen Navigationsgerät nutzen. Je nach Hersteller ist dies mit mehr oder weniger Arbeit verbunden. Bei Garmin genügt es eine Datei ins richtige Verzeichnis zu legen – sobald man sich für eine Karte entschieden hat.

 

Karte finden

Der wohl zeitaufwendigste Arbeitsschritt ist die Suche nach der passenden Karte. Dabei kommt es vor allem darauf an was man mit der Karte machen will. Nutzt man diese nur im Auto braucht es eine gute Darstellung von befahrbaren Strassen. Als Wanderer will man lieber wissen mit welchem Pfad man am schnellsten zum Ziel kommt. Höhenlinien sind für die einen sehr wichtig und für andere im flacheren Gelände nur störend.

Im Wiki von OpenStreetMap gibt es eine Übersichtsseite mit Links zu allerlei Karten. Diese sind nach Gebiet sortiert und meist mit einem Hinweis zum angedachten Benutzerkreis ausgestattet. (Ich selber nutze im Moment die Karte „Schweiz“ von Kowoma.)

 

Installieren…

Garmin liefert mit seinen Navigationsgeräten das Tool MapSource mit. Neben vielen praktischen Funktionen kann man damit auch Karten installieren. Um dieses Tool zu nutzen muss die Karte als MapSource installer Datei (.exe) vorliegen. Hat man so eine Datei genügt ein Doppelklick darauf und man wird durch einen Assistenten geführt der die Karte installiert.

 

… oder nur kopieren

Wenn man aber direkt eine gmapsupp.img Datei bekommen kann sollte man diese nutzen. Es genügt nach dem Download und entzippen (sofern nötig) die Datei auf dem GPS-Gerät ins Verzeichnis /Garmin zu kopieren.

Für ältere Geräte wichtig: Die Datei beim Kopieren nicht umbenennen. Der Dateiname muss stimmen, sonst wird die Karte nicht gefunden. Man kann so nur 1 Karte verwenden, doch genügt dies für die meisten Anwendungsfälle.

 

Karte aktivieren

Je nach Gerät muss man nun unter den Einstellungen erst noch die neue Karte aktivieren. Um Probleme zu vermeiden deaktiviere ich jeweils die anderen Karten. (Falls diese das gleiche Gebiet zeigen.)

Wechselt man nun in die Kartenansicht sieht man die neue Karte.

 

Fazit

Das Kartenupdate funktioniert mittlerweile sehr einfach. Als Anwender kann man unter einem grossen Angebot wählen und findet meist etwas Passendes.

Schlagworte:

Buch-Rezension zu “Sieben Wochen, sieben Sprachen”

21. September 2011 2 Kommentare

Sieben Wochen, sieben Sprachen – Verstehen Sie die modernen Sprachkonzepte“ von Bruce A. Tate erschien in der deutschen Ausgabe im Juni 2011. Wer sich bisher nur mit objektorientierter Programmierung beschäftigt hat bekommt mit diesem Buch eine Übersicht über andere moderne Konzepte. Wie man schnell merkt bedingt ein modernes Konzept nicht zwingend eine neue Sprache.

[Hinweis: Ich habe dieses Buch über die .Net User Group Bern erhalten, die am User Group Programm von O’Reilly teilnimmt. Wie immer wenn ich über Bücher blogge schreibe ich was mir daran gefällt und was nicht. Dies mache ich unabhängig davon ob ich ein Rezensionsexemplar bekomme oder das Buch selber kaufe.]

 

Aufbau des Buches

Jede Sprache wird in 3 Lektionen (jeweils ein Tag) erklärt. Am ersten Tag geht es um die grundlegenden Dinge und es gibt ein Interview mit einem Poweruser oder dem Erfinder der Sprache selbst. Dabei werden die Besonderheiten der Sprache hervorgeheben und gezeigt wofür sie eingesetzt werden kann.

Am Ende jedes Tages gibt es einige „Hausaufgaben“ zum Selbststudium. Die Lösungen wurden leider entgegen dem Hinweis im Buch nicht veröffentlicht. Googelt man ein wenig stösst man schnell einmal aufs Blog von Ben Nadel der die einzelnen Lösungen schön kommentiert veröffentlicht hat.

Am zweiten und dritten Tag wird tiefer in die Eigenheiten der Sprache vorgedrungen. Als Abschluss gibt es eine Zusammenfassung der Sprache und die Vor- und Nachteile werden hervorgehoben.

Am Ende des Buches werden nochmals die wichtigsten Eigenheiten jeder Sprache zusammengefasst und eine Entscheidungshilfe angeboten.

 

Die 7 Sprachen

Ruby
Die Reise beginnt mit Ruby, einer objektorientierten Programmiersprache. Die meisten Leser des Buches werden wohl mit dem Konzept der Objektorientierung vertraut sein und so auf dem bestehenden Wissen aufbauen können. Da Ruby eine Scriptsprache ist gibt es für Java- oder C# Programmierer auch hier schon etliche neue Konzepte zu lernen. Duck-Typing eines davon, bei dem es darum geht, das alles was wie eine Ente läuft und wie eine Ente schnattert auch eine Ente ist. Ein Typ hängt nicht mehr so sehr davon ab von welchem Objekt er abgeleitet wurde als vielmehr was für Funktionalitäten er bereitstellt.

Io
Io ist eine Prototypensprache (wie JavaScript). Dies bedeutet dass jedes Objekt ein Klon eines anderen Objekts ist. Io ist sehr minimalistisch und kann dank seinem sehr kleinen Speicherverbrauch in eingebetteten Systemen verwendet werden. Nachrichten und Slots sind 2 Konzepte die man für Io verstehen muss und einem auch in den weiteren Kapiteln begegnen.

Prolog
Prolog ist eine deklarative Sprache bei der man Fakten und Regeln definiert und die Lösung des Problems dem Computer überlässt. Als Beispiel kann man ein Sudoku nur durch die Definition der Regeln lösen lassen. Prolog ist als Vertreter der Logikprogrammierung nicht mit den anderen Sprachen im Buch vergleichbar. Hier geht es um eine ganz andere Art Probleme anzugehen. Ich fand diesen Ausflug sehr gelungen und es gibt einem etliche neue Ideen bevor es mit den funktionalen Programmiersprachen losgeht.

Scala
Scala ist eine Hybridsprache die versucht objektorientierte und funktionale Konzepte zu vereinen. Bei der Objektorientierung gibt es eine enge Integration mit Java. Scala läuft in der Java Virtual Machine (JVM), ist beim Syntax nahe an Java und kann auch Java-Bibliotheken nutzen. Man kann mit Scala langsam in die funktionale Programmierung einsteigen und dabei immer noch auf die Objektorientierung zurückgreifen.

Erlang
Erlang („Ericsson Language“) ist eine Sprache zur Parallelprogrammierung. Erlang ist die Sprache hinter CouchDB und sonst vor allem in Telekom-Anwendungen weit verbreitet. Dies vor allem wegen der hohen Zuverlässigkeit und der Möglichkeit einzelne Module im Betrieb auszutauschen.
Tate zeigt in diesem Kapitel schön auf wie einzelne Konzepte von Prolog in Erlang geflossen sind. Man wird noch des Öfteren sehen wie Sprachen die gleichen Konzepte nutzen oder sich gegenseitig beeinflussen.

Clojure
Clojure ist ein Lisp-Dialekt der auf der JVM läuft. Die vielen Klammern sind Lisp-Typisch und verwirren wohl die meisten Leute erst einmal. Das Verschachteln und binden macht die ganze Sache nicht einfacher und ist sehr gewöhnungsbedürftig. Mit Transactional Memory nutzt das sonst auf Funktionen ohne Nebenwirkungen konzentrierte Clojure eine interessante Möglichkeit um Daten dennoch verändern zu können. Wie bei einer Datenbank gibt es Transaktionen die die Integrität der Daten schützen.

Haskell
Als Abschluss kommt Haskell als reine funktionale Sprache. Haskell zwingt einem sich voll auf das Konzept der funktionalen Programmierung einzulassen und lässt einem keine Hintertür zur Umgehung offen. Man trifft viele Konzepte der vorgehenden funktionalen Sprachen wieder an, aber halt ohne deren Kompromisse.

 

Gutes Konzept

Es ist ein sehr ambitioniertes Ziel 7 Programmiersprachen in einem Buch unterzubringen. Tate gelingt es sehr gut die wichtigsten Punkte einer Sprache aufzuzeigen. Mit seiner Auswahl kann man oft auf den im vorgehenden Kapitel erstmals vorgestellten Konzepten aufbauen und sieht was damit alles möglich wird.

Man darf allerdings nicht erwarten das man nach dem Durcharbeiten die einzelnen Sprachen auch Beherrscht. Tate vermittelt die Grundlagen und lässt einem in den Hausaufgaben die wichtigsten Anlaufstellen für die jeweilige Sprache suchen. Dieses Wissen ist ein guter Ausgangspunkt um sich intensiver mit der Sprache zu befassen.

 

Gelungene Übersetzung

Die Übersetzung aus dem englischen ist meistens sehr gut. Ich konnte dem Text problemlos folgen ohne mir zu überlegen was das wohl in Englisch bedeuten könnte. Formulierungen wie „Syntaktischer Zucker“ sind zwar Gewöhnungsbedürftig, aber es ist klar um was es geht und einen besseren Begriff würde mir auch nicht einfallen.

Hin und wieder hat man die Übersetzung aber auch ein wenig Übertrieben. Wenn in einem Beispiel ein Wert der Variabel „Eins“ zugewiesen und zwei Zeilen später auf „One“ zugegriffen wird fördert dies nicht gerade das Verständnis. In die gleiche Richtung geht es wenn im Beispiel „Pirates of the Caribbean“ steht und der beschreibende Text von „Fluch der Karibik“ spricht. So etwas hätte die Qualitätskontrolle gerne herausfiltern dürfen.

 

Einige mühsame Fehler

Beim Kapitel zu Scala erschien es mir mehrmals als ob sich einige Formatierungsanweisungen in den Text geschlichen hätten. Diese stören den Lesefluss und macht es nicht einfacher ein neues Konzept zu verstehen.

Durchs ganze Buch hindurch wird bei Rekursion immer wieder die Fibonacci-Folge verwendet. Es wäre schön wenn man bemerkt hätte das für Fib(0) = 0 gilt. Dann würden auch die Beispiele bei Haskell die gleichen Resultate liefern wie die anderen Fibonacci-Implementierungen.

 

Zu sehr auf Java fixiert

Für meinen Geschmack legt Tate zu viel Wert auf die Kompatibilität zur JVM. Ich verstehe sehr wohl dass man so viele der bekannten Bibliotheken weiter nutzen kann. Bei einigen Situationen ist es mir aber schleierhaft, wie man bei einer solchen Ausgangslage auf die JVM will. Als Beispiel bei der Schlussbesprechung von Erlang:

Die JVM hat so ihre Altlasten, wie etwa das Prozess- und Threading-Modell, das für Erlangs Bedürfnisse völlig ungeeignet ist. Doch die JVM zu nutzen, hat auch seine Vorteile, etwa die Fülle an Java Bibliotheken und Hundertausende potentieller Server, die man nutzen könnte.

Wenn eine Sprache dermassen Wert auf Parallelisierung legt wie Erlang ist ein ungeeignetes Threading-Modell ein Killerkriterium. Punkt. Da gibt’s von mir aus nichts was das noch retten kann.

Auch wenn ich mit einigen Einschätzungen über die Stärken und Schwächen von Tate nicht immer einverstanden bin, so macht er doch eine gute Arbeit um einem die einzelnen Sprachen vorzustellen.

 

Fazit

Wer das Buch nur durchliest verpasst viel. Um wirklich davon zu profitieren sollte man sich die Zeit nehmen und auch die Beispiele und Aufgaben durcharbeiten. Die 7 Sprachen bieten viele Herausforderungen und Möglichkeiten um sich mit ungewohnten Konzepten zu beschäftigen.

Will man sich mit einer Sprache tiefer beschäftigen wird einem dieses Buch alleine nicht genügen. Man weiss nach dem Lesen aber wie man an weitere Informationen kommt und hat so einen guten Ausgangspunkt.

 

Zum Buch

Sieben Wochen, sieben Sprachen – Verstehen Sie die modernen Sprachkonzepte“ von Bruce A. Tate, 2011 O’Reilly, ISBN 978-3-897-21322-7, 360 Seiten, Deutsch

Schlagworte: , ,

Prolog: Kleine Unterschiede, grosse Wirkung

7. September 2011 1 Kommentar

Beim Durcharbeiten der “Hausaufgaben” von „Sieben Wochen, sieben Sprachen“ hatte ich beim Kapitel zu Prolog einige Schwierigkeiten zu lösen. Da ich mich sonst nicht mit Prolog beschäftige dauerte es recht lange bis ich meinen Fehler finden konnte. Auch wenn ich diesen Blog-Eintrag primär als Gedankenstütze für mich selber schreibe, so würde es mich freuen wenn andere Prolog-Neulinge auch davon profitieren könnten.

 

Die Aufgabe


An sich war die Hausaufgabe recht einfach: Die vorgegebene Lösung für ein 4×4 Sudoku muss so erweitert werden damit man ein reguläres 9×9 Sudoku lösen kann. Neben dem grösseren gültigen Zahlenbereich mussten vor allem mehr Spalten, mehr Zeilen und mehr Blöcke eingefügt werden.

Mein (fehlerhaftes) Resultat sah so aus:

valid([]).
valid([Head|Tail]) :-
        fd_all_different(Head),
        valid(Tail).

sudoku(Puzzle, Solution) :-
        Solution = Puzzle,


        Puzzle = [S11, S12, S13, S14, S15, S16, S17, S18, S19,
                  S21, S22, S23, S24, S25, S26, S27, S28, S29,
                  S31, S32, S33, S34, S35, S36, S37, S38, S39,
                  S41, S42, S43, S44, S45, S46, S47, S48, S49,
                  S51, S52, S53, S54, S55, S56, S57, S58, S59,
                  S61, S62, S63, S64, S65, S66, S67, S68, S69,
                  S71, S72, S73, S74, S75, S76, S77, S78, S79,
                  S81, S82, S83, S84, S85, S86, S87, S88, S89,
                  S91, S92, S93, S94, S95, S96, S97, S98, S99],

        fd_domain(Solution, 1, 9),

        Row1 = [S11, S12, S13, S14, S15, S16, S17, S18, S19],
        Row2 = [S21, S22, S23, S24, S25, S26, S27, S28, S29].
        Row3 = [S31, S32, S33, S34, S35, S36, S37, S38, S39],
        Row4 = [S41, S42, S43, S44, S45, S46, S47, S48, S49],
        Row5 = [S51, S52, S53, S54, S55, S56, S57, S58, S59],
        Row6 = [S61, S62, S63, S64, S65, S66, S67, S68, S69],
        Row7 = [S71, S72, S73, S74, S75, S76, S77, S78, S79],
        Row8 = [S81, S82, S83, S84, S85, S86, S87, S88, S89],
        Row9 = [S91, S92, S93, S94, S95, S96, S97, S98, S99],

        Col1 = [S11, S21, S31, S41, S51, S61, S71, S81, S91],
        Col2 = [S12, S22, S32, S42, S52, S62, S72, S82, S92],
        Col3 = [S13, S23, S33, S43, S53, S63, S73, S83, S93],
        Col4 = [S14, S24, S34, S44, S54, S64, S74, S84, S94],
        Col5 = [S15, S25, S35, S45, S55, S65, S75, S85, S95],
        Col6 = [S16, S26, S36, S46, S56, S66, S76, S86, S96],
        Col7 = [S17, S27, S37, S47, S57, S67, S77, S87, S97],
        Col8 = [S18, S28, S38, S48, S58, S68, S78, S88, S98],
        Col9 = [S19, S29, S39, S49, S59, S69, S79, S89, S99],

        Square1 = [S11, S21, S31, S12, S22, S32, S13, S23, S33],
        Square2 = [S41, S51, S61, S42, S52, S62, S43, S53, S63],
        Square3 = [S71, S81, S91, S72, S82, S92, S73, S83, S93],
        Square4 = [S14, S24, S34, S15, S25, S35, S16, S26, S36],
        Square5 = [S44, S54, S64, S45, S55, S65, S46, S56, S66],
        Square6 = [S74, S84, S94, S75, S85, S95, S76, S86, S96],
        Square7 = [S17, S27, S37, S18, S28, S38, S19, S29, S39],
        Square8 = [S47, S57, S67, S48, S58, S68, S49, S59, S69],
        Square9 = [S77, S87, S97, S78, S88, S98, S79, S89, S99],

        valid([Row1, Row2, Row3, Row4, Row5, Row6, Row7, Row8, Row9,
                Col1, Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9,
                Square1, Square2, Square3, Square4, Square5, Square6, 
                Square7, Square8, Square9]),

        write( '\n' ), write( Row1 ),
        write( '\n' ), write( Row2 ),
        write( '\n' ), write( Row3 ),
        write( '\n' ), write( Row4 ),
        write( '\n' ), write( Row5 ),
        write( '\n' ), write( Row6 ),
        write( '\n' ), write( Row7 ),
        write( '\n' ), write( Row8 ),
        write( '\n' ), write( Row9 ).

 

Kompilierfehler


Als Arbeitsumgebung nutze ich meinen Linux-PC mit Ubuntu 11.4 und GNU Prolog 1.3.0. Nach dem Start von gprolog gab es beim Laden der Datei diese Fehlermeldung:

jgr@R:~/BLOG/$ gprolog
GNU Prolog 1.3.0
By Daniel Diaz
Copyright (C) 1999-2007 Daniel Diaz
| ?- ['sudoku.pl'].
compiling /home/jgr/BLOG/sudoku.pl for byte code...
/home/jgr/BLOG/sudoku.pl:6-23: warning: singleton variables [S31,S32,S33,S34,S35,S36,S37,S38,S39,S41,S42,S43,S44,S45,S46,S47,S48, S49,S51,S52,S53,S54,S55,S56,S57,S58,S59,S61,S62,S63,S64,S65,S66,S67, S68,S69,S71,S72,S73,S74,S75,S76,S77,S78,S79,S81,S82,S83,S84,S85,S86, S87,S88,S89,S91,S92,S93,S94,S95,S96,S97,S98,S99,Row1,Row2] for sudoku/2
/home/jgr/BLOG/sudoku.pl:24-64: warning: suspicious predicate (',')/2
/home/jgr/BLOG/sudoku.pl compiled, 64 lines read - 22767 bytes written, 187 ms

yes
| ?- 

Wer wie ich vor allem in C# entwickelt wird beim ersten Zusammentreffen mit so einer Fehlermeldung wenig anfangen können. Es stehen aber alle nötigen Informationen drin – nur muss man diese erst einmal „entschlüsseln“.

 

sudoku.pl:6-23: warning: singleton variables [S31,S32,S33,...] for sudoku/2

 
Laut dieser Fehlermeldung verwendet die Regel sudoku (mit 2 Parametern) die Variablen S31, S32, usw. nur 1 einziges Mal. Schaue ich den Inhalt meiner sudoku-Regel an, sollten diese Variablen aber alle mehrmals verwendet werden.

Auch die Zeilennummern erscheinen auf den ersten Blick nutzlos. Weder in Zeile 6 noch in Zeile 23 sehe ich etwas was nach einem Fehler aussieht. Meldet Visual Studio „; expected Line 97 Column 76“ weis ich das ein „;“ in Zeile 97 fehlt. Prolog ist ein wenig anders.

Die Fehlermeldung kann man aber auch so übersetzen:
„In der Regel sudoku mit 2 Parametern, die zwischen Zeile 6 und 23 definiert ist, werden die Variablen S32, … nur 1 Mal verwendet.“

Für den Interpreter ist meine Regel zwischen den Zeilen 6 und 23 definiert. Für mich müsste diese aber bis zu Zeile 64 gehen – und hier liegt die Ursache der Fehlermeldung. Prolog nutzt einen Punkt um einzelne Fakten und Regeln zu trennen. Schaut man meinen Regelsatz noch einmal genau an findet man auf Zeile 22 am Ende der Definition von Row2 auch ein Punkt statt einem Komma.
Dieser „kleine“ Unterschied hat aber grosse Wirkung. Sind die Regelsätze unvollständig wird Prolog damit kein Sudoku lösen können. Macht man trotzdem weiter sind die Folgefehler kaum mehr zu durchschauen.

Nachdem ich den Punkt durch ein Komma ersetzt hatte liessen sich meine Regeln fehlerfrei laden:

| ?- ['sudoku.pl'].
compiling /home/jgr/BLOG/sudoku.pl for byte code...
/home/jgr/BLOG/sudoku.pl compiled, 64 lines read - 19963 bytes written, 13 ms

yes
| ?- 

Um ein Sudoku zu lösen genügt es nun die bekannten Zahlen sowie ein _ für alle offenen Felder einzugeben. Prolog löst das Rätsel im Handumdrehen – oder noch schneller:

| ?- sudoku([_, _, _, 2, 4, _, 8, _, _,
             _, _, 2, 3, _, _, _, 6, _,
             _, _, _, 7, _, _, 9, 3, _,
             _, _, _, _, 9, _, _, _, 1,
             _, 9, _, 1, 2, 4, _, _, 3,
             _, _, 1, _, _, _, _, _, _,
             3, _, _, _, _, 8, _, 1, _,
             _, 8, 6, 4, 1, _, _, 5, _, 
             _, 7, 4, _, _, 5, _, _, _], Solution).

[6,3,9,2,4,1,8,7,5]
[7,5,2,3,8,9,1,6,4]
[4,1,8,7,5,6,9,3,2]
[2,6,3,8,9,7,5,4,1]
[5,9,7,1,2,4,6,8,3]
[8,4,1,5,6,3,7,2,9]
[3,2,5,9,7,8,4,1,6]
[9,8,6,4,1,2,3,5,7]
[1,7,4,6,3,5,2,9,8]

 

Tipps für die Problemlösung


Zum Abschluss möchte ich 2 Punkte herauspicken die ich im Nachhinein als besonders wichtig erachte:

  1. Im Fehlerfall immer erst den 1. Fehler beheben. Viele Folgefehler werden damit auch gleich beseitigt.
  2. Für Sprachen wie Prolog muss der Texteditor oder die Konsole unbedingt eine Schrift verwenden die Punkte und Kommas deutlich differenziert. (Monospace ist dafür nicht geeignet)

 

Fazit


So richtig spannend wird es erst wenn man vor Probleme gestellt wird. Eine ganz einfache uns simple Aufgabe (eine Lösung von 4×4 auf 9×9 erweitern) verwandelte sich in eine veritable Herausforderung. Wenn man die Antwort kennt ist es banal. Muss man sich aber durch die Fehlermeldungen und unzählige falsche Ansätze kämpfen beginnt erst das eigentliche lernen.

Auch kleine Aufgaben können einem viel beibringen.

Schlagworte: ,
Folgen

Erhalte jeden neuen Beitrag in deinen Posteingang.

Schließe dich 297 Followern an