Archive for January, 2006

Über die Wichtigkeit von Theoretischer Informatik

Tuesday, January 3rd, 2006

Joel, drüben bei Joel On Software hat einen interessanten Artikel darüber geschrieben, warum Java seiner Meinung nach keine gute Lehrsprache ist: The Perils Of Java Schools. Sein Kernargument ist, dass Java es den Studenten zu einfach macht und die meisten interessanten Konzepte gar nicht möglich sind.

Fast unmittelbar danach las ich auf Justins Weblog eine andere Position, der ich mich hier ein wenig wiedersprechen möchte.

Justin behauptet in seinem Beitrag folgendes:

  • Alle interessanten Algorithmen und Technken zur Analyse von ihnen sind von Knuth, Cormen usw. schon hinreichend genau und ausführlich beschrieben worden.
  • Programmiert man in dynamischen Sprachen, dann sind diese Algorithmen und Techniken unwichtig. Übrigens: Python, Ruby usw. sind keine VHL-Sprachen. VHL-Sprachen sind Sprachen wie Prolog. In diesem definiert man ein Problem und die Anfoderungen an einer Lösung und ein System löst das Problem dann.
  • Effiziente Algorithmen bei gutem Software Engineering nicht nötig.

Wir wissen sehr wenig

Einer der Dinge, die mir in meiner momentan laufenden Informatik III Vorlesung klar geworden sind ist, dass die Informatiker nur sehr wenig über ihre eigenen Systeme wissen. Zwar können Informatiker Grenzen für das aufstellen, was sie erfassen und begreifen können (etwa: Das Halteproblem für deterministische Turingmaschinen ist unentscheidbar), aber viele Dinge sind einfach noch nicht bekannt.

Ein Beispiel für recht einfach beschreibbare aber sehr schwierige Probleme ist etwa die Frage nach einer unteren Grenze für das sortieren von dynamischen Datenstrukturen (sprich: nicht diskret und beschränkt). Man vermutet, dass es n · log n ist, aber es gibt noch keinen Beweis dafür.

Ein anderes Beispiel für auch in der Praxis wichtige Fragen aus der theoretischen Informatik ist die nach der Gleichheit der Komplexitätsklassen P und NP. Es gibt weder einen Beweis noch einen Gegenbeweis. Wären die Probleme aus NP in polynomieller Zeit mit ,,umsetzbaren” Rechenmodellen (sprich: Äquivalent zur deterministischen Turingmaschine) lösbar, dann könnte man sehr viele Optimierungsprobleme (etwa: TRAVELLING SALESMAN) und andere wichtige Probleme (etwa: KNAP SACK) effizient lösen. Nach dem aktuellen Stand der Forschung ist dies nicht möglich.

Als Informatiker trifft man also schon am Anfang seines Studiums auf ungelöste, wichtige Probleme. Diese kann man meiner Meinung nach nur dann verstehen, wenn man sie gründlich untersucht, ähnliche Probleme betrachtet und begreift, wie man etwa die verschiedenen Probleme in NP aufeinander abbilden kann.

In der Praxis ist dies auch wichtig: Ist einem Manager (sprich: BWLer) meine Lösung zu langsam, dann ist der Beweis, dass das Problem NP-hart ist, zur Verteidigung meines Programmes ein besseres Argument als ein ,,das ging irgendwie nicht besser”.

Und dynamische Sprachen?

Auch wenn man in dynamischen Sprachen wie Python programmiert, in denen man Algorithmen und Programme oft sehr kompakt und elegant aufschreiben kann, ist Wissen über Komplexitätstheorie, das O-Kalkül und den ganzen Rest nicht ganz ohne Nutzen: NP-harte Probleme bleiben auch in Python NP-hart, O(n3) ist auch (oder vielleicht sogar: gerade?) in Python schlechter als O(n2).

Elementare Datenstrukturen wie binäre Bäume, verkette Listen und so weiter sind in dynamischen Sprachen und auch Sprachen wie Java, die dem Programmierer sehr viel Arbeit abnehmen, eher unwichtig. Da hat Justin schon recht. (Randnotiz: Auf der anderen Seite gibt es im Zope Application Server - in Python geschrieben - eine B-Baum Implementierung, die Ordner mit sehr vielen Untereinträgen erlaubt).

Aber ich möchte mich selbst nicht nur auf Skriptsprachen oder Java bzw. C# beschränken: Sicher, vieles lässt sich in ihnen sehr fix - und durch Speicherschutz auch sicher - implementieren implementieren. Viele interessante Probleme und Aufgabengebiete lassen sich mit ,,low level” Sprachen wie C jedoch besser bearbeiten. Etwa dort, wo Geschwindigkeit an erster Stelle steht: Betriebssysteme, niedrigere Schichten in der Netzwerkkommunikation, die Implementierung von Datenbanken usw. Oder dort, wo große Datenmengen in Echtzeit bearbeitet werden sollen, etwa bei der Audio- und Videobearbeitung im Rechner.

Software Engineering > Algotech

In der Frage ,,Ist es nicht eher so, dass effiziente Algorithmen den Vergleich gegen gutes Software Engineering klar verlieren?” vergleicht Justin Äpfel nicht mit Birnen, sondern eher mit Wasser. Jeder, der gutes Software Engineering machen will, der muss meiner Meinung nach auch ein Mindestwissen in Algorithmentechnik und theoretischer Informatik aufweisen.

Hat man dieses, so kann man hier und dort blutige Nasen vermeiden. Vielleicht kann man hier doch besser einen Baum statt einen Graph verwenden und erspart sich damit ein NP-Problem. Dort kann das Wissen um die Existenz von Rot-Schwarz-Bäumen ein naives Herangehen an das ausbalanciert Halten von Suchbäumen (und damit Zeit für Implementierung und einen nicht optimierten Algorithmus) vermeiden. An anderer Stelle hilft das Wissen über Hash-Tabellen vielleicht doch: O(1) ist sehr viel besser als O(n) bei unsortierten oder O(log n) bei sortierten Reihungen.

Dass man in seinem Diplomstudium Informatik so viele Algorithmen, Datenstrukturen und Methoden lernt ist also weniger Schikane als viel mehr ein Heranführen an das, was die Informatik antreibt: Das Streben nach der besten Lösung für ein Problem. Nur derjenige, der die Strukturen und Ideen hinter Problemen, Lösungen und Algorithmen versteht, kann auch effiziente Programme schreiben.

Was ist schlecht an Java?

Java hat eine - meiner Meinung nach - umständliche und nicht konsistente Syntax und ist sehr einschränkend. Auf der anderen Seite diese Sprache jedoch auch für durchschnittliche Programmierer entworfen worden und enthält viele ,,verschluckbaren Kleinteile” wie die Möglichkeit zu Speicherzugriffsfehler nicht.

Damit ist sie zu einer der Sprachen geworden, die in ,,der Industrie” bevorzugt werden (neben dem sehr änlichen C#). Warum sollte man sie nicht auch in der Lehre einsetzen? Natürlich sind die fehlenden, verschluckbaren Kleinteile, ein gutes Argument und ich will gar nicht sagen, dass Java auf gar keinen Fall in der Lehre eingesetzt werden sollte. Ich will viel mehr zum Nachdenken anregen:

  • Ist es unmöglich in Java Fehler zu machen? Nein, man macht auch in Java viele Fehler. Typfehler findet oft der Compiler. Aber alle? Wofür gibt es dann die ClassCastException? Und bei semantischen Fehlern (diejenigen, die mir selbst in C am häufigsten passieren) kann mir kein Compiler helfen.
  • Ist es sinnvoll, in der Lehre Datenstrukturen in Java implementieren zu lassen? Ich würde sagen: Nein. Verkette Listen sind in Java recht witzlos und in der Praxis werden sie wohl immer noch am häufigsten in Sprachen wie C verwendet. Und dort muss man sich dann auch um Zeiger und Speicherverwaltung kümmern. Sind Informatikstudenten dümmer als Fachinformatiker, die ggf. C(++) lernen? Ist das Konzept von Zeigern zu schwer für einen Diplominformatiker? Wenn ja, dann werden wir auch wohl die Fragen aus der Berechenbarkeitstheorie nie lösen.
  • Ist Hello World in Java trivial? Selbst für das einfachste, was irgendwie funktionieren könnte, braucht man in Java eine Klasse. Unser Informatik 1 Professor sagte immer “ignorieren sie das, das ist syntaktischer Zucker”. In Mathematikvorlesungen wurde jedoch etwa nie zu einem Symbol an der Tafel etwas ähnliches gesagt. Will man dann in Java prozedural programmieren, so braucht man immer static TypName Variablen. Was heißt static? Dies wurde in unserer Informatik 1 Vorlesung nie wirklich erklärt. Wenn prozedurale Programmierung in Java zu schwierig ist, um sie Informatikstudenten (die zukünftige ,,Elite” in der IT-Branche) erklären zu können: Warum benutzt man dann nicht eine imperative Sprache, in der Hello World trivial ist?

Der Weisheit letzter Schluss?

Ich habe diesen Beitrag nach besten Wissen und Gewissen geschrieben, bin aber für Belehrungen und Korrekturen offen. Schreibt sie einfach in die Kommentare.

Danke, Microsoft!

Sunday, January 1st, 2006

Danke, Microsoft: Für ein Ausgaben eures tollen Betriebssystems Windows XP Home Edition, die sich nur mit einem Übermaß an Aufwand installieren lassen. Corpus Delicti: Ein Fujitsu Siemens Scaleo L, etwa 2 Jahre alt.

Auf dem Rechner lief erst Windows XP Home (vorinstalliert), dann anstandslos ein Debian Linux 3.1. Als ich jedoch versuchte, wieder Windows XP Home zu installieren, beschenkte mich das Installationsprogramm reich mit der Fehlermeldung, das irgendwas mit der Festplatte nicht in Ordnung sei, er aber nicht so wirklich wisse, das das ist. Das ganze natürlich erst nachdem ich 10 Minuten auf das Formatieren der Festplatte gewartet hatte und dabei kein Fehler angezeigt wurde. Windows XP Professional wollte sich auch nicht installieren lassen.

Was bleibt einem dann noch übrig? Richtig! Knoppix herunterladen, auf CD bannen, die Festplatte partitionieren. Danach wollte der XP Home Installer immer noch nicht. Der XP Pro installer funktionierte jedoch und ich ließ in die Partition formatieren. Dann fix den Installationsvorgang durch einen Druck auf die Reset-Taste abgebrochen und nun ließ sich auch der XP Home Installer zu einer Installation bewegen.

Die Moral von der Geschicht: Die Wege von Windows sind unergründlich und ich lobe mir Unix. Diese Systeme sind von Grund auf offener - selbst das kommerzielle Os X - und man kann schneller Fehlerursachen bestimmen und Workarounds finden.