Informatik an der Uni Karlsruhe: Keine case/switch-Anweisungen?
Stirnrunzeln über die Karlsruher Lehre.
Ich weiß, daß eine ganze Menge Leute von der Uni Karlsruhe mein Blog mitlesen. Und ne Menge jüngerer Studenten haben mir auch schon persönlich berichtet, daß sie mit den abgehobenen und weltfremden, teils absurden und fehlerhaften Sichtweisen der dortigen Professoren sehr unzufrieden sind, die sich da ihre eigene kleine Weltsicht einreden. Und, wie mir mehrfach berichtet wurde, die Programmiersprache Java für das Maß aller Dinge halten. (Ich halte Java von der Sprachkonstruktion her für einen mißlungenen Entwurf von jemandem, der erstens kein Programmiersprachgefühl hatte, zweitens wohl nicht viel mehr als C und C++ kannte, und drittens nicht das Ziel hatte, eine ordentliche Sprache zu entwerfen, sondern unter Zeitdruck einen möglichst einfachen Compiler und ein einfaches Laufzeitsystem bauen mußte, und damit vieles auf den Programmierer verlagert, was eigentlich ein guter Compiler erledigen könnte, also eine Bastellösung. Java ist unübersichtlich, langatmig und geschwätzig, kontraintuitiv, und viele Probleme lassen sich damit nicht elegant und nur umständlich lösen.)
Neulich deutete einer an, daß man(che) in Karlsruhe der Auffassung sei(en), daß die case/switch-Konstruktion, die es in vielen Sprachen (und neuerdings endlich in primitiver Form auch in Java) gibt, sowas wie Teufelswerk sei.
Ich halte diese Sprachkonstruktion im Gegenteil für äußerst gut und wichtig, und in vielen Fällen für prädestiniert, um Sicherheitsprobleme und Programmierfehler zu vermeiden (insbesondere, wenn die Anweisung nicht nur einfache Konstantenvergleiche, sondern den Aufruf komplexer Operatoren ermöglicht.)
Zugegeben, letztlich ist diese Anweisung kein eigenes Sprachkonstrukt, sondern nur eine syntaktische Vereinfachung einer If-elsif-else-Kette (was man normalerweise als „syntactic sugar” bezeichnet, was bedeutet, daß ein Konstrukt die Sprache oder die unterstellte Maschine nicht wirklich erweitert, sondern einfach nur dem Menschen das Lesen und Schreiben erleichtert, was ja letztlich Sinn und Zweck einer höheren Programmiersprache ist). Manchmal sorgt aber der Syntactic Sugar gerade dafür, daß der Programmierer (oder Leser) die Struktur des Programmes viel leichter erkennt und viel leichter bemerkt, wenn er irgendwelche Fälle nicht abgefragt hat. In manchen Sprachen warnt einen sogar der Compiler, falls man eine Case-Anweisung über eine Aufzählung macht und nicht alle Fälle abgeklappert hat.
Gerade wegen dieser Äquivalenz zu einer If-elsif-else-Konstruktion stellt sich mir aber die Frage, was daran eigentlich schlecht sein könnte, denn die Notwendigkeit einer If-Konstruktion zu bestreiten wäre mutig (denn dann wäre die Turing-Fähigkeit fraglich).
Gerade in Fällen, in denen man etwa mehr als zwei Fälle von Rückgabewerten einer aufgerufenen Prozedur unterscheiden muß, sind solche Anweisungen wichtig und treffen eine Problemstellung, die sehr häufig auftritt. Beispiel: Suche nach einem Objekt in einer Datenbank. Fall 1: Nichts gefunden. Fall 2: Genau eins gefunden. Fall 3: Mehrere gefunden. Typischer Case-Fall. Oder auch beim Verarbeiten von irgendwelchen Werten und Parametern, vor allem, wenn sie von einem Angreifer stammen könnten, können solche Anweisungen, insbesondere wenn sie komplex und objektorientiert sein können, sehr nützlich sein.
Typische Fehler, die dann zu Sicherheitsproblemen führen, sind etwa solche Abfragen wie if (x<1000)..., was in die Hose gehen kann, wenn x=0 oder sogar x<0. So mancher verwechselt nämlich auch mal signed und unsigned und denkt nicht daran, daß ein Wert bei signed auch mal negativ werden könnte, oder ein großer positiver Wert mit gesetztem obersten Bit auch negativ interpretiert werden könnte. Eine Anweisung wie case x ; when 1..1000 ... ; else... kann solche Fehler vermeiden und das Programm lesbarer machen. Lesbarkeit kommt aber im Leben eines Elfenbeintheoretikers nicht oder nur als schlechte Eigenschaft vor.
Deshalb interessiert es mich, ob die das in Karlsruhe wirklich so lehren (denen traue ich dort in dieser Hinsicht alles zu), und wenn ja, wie sie das begründen.
Und falls ja: Ob sie das auch so prüfen. Denn wenn einer das so abprüft, daß man diese Anweisung nicht nutzen soll, dann wäre das unzulässig.
Wer kann mir dazu (oder zu anderen Fragwürdigkeiten) was erzählen?
13 Kommentare (RSS-Feed)
Ich denke, es bezieht sich eher darauf, dass man switch/case oft – nicht immer – durch eine elegantere Lösung ersetzen kann. Siehe
http://lambda-the-ultimate.org/node/1090#comment-11701
Enno
Na, das hört sich ja doch noch vernünftig an.
Die Fehleranfälligkeit der C++-Version ist wirklich Mist. Mir fällt jetzt gerade kein ernsthafter Fall ein, in dem ich dieses Durchrutschen schon mal sinnvoll hätte brauchen können.
Haskell/Gopher habe ich damals nicht gemacht, das war mir zu blöd. Da war ich auch nicht mehr Tutor sondern schon Mitarbeiter, als die damit angefangen haben.
Von Java halte ich allerdings auch nicht viel. Das habe ich damals mal ausprobiert, als das ganz neu erfunden worden war, und bin mir vorgekommen, als würde ich mit Lego-Bauklötzen spielen. Keine schöne Sprache.
Allerdings dann auch die einzige, die eine weitgehend einheitliche Umgebung bereitstellt. Als ich in den ersten Semestern war, hatten wir UCSD-Pascal, was ähnlich wie Java auch ein Zwischencodesystem war, bei dem nur der Interpreter an die jeweilige Maschine angepasst werden mußte. Das gabs daher auch einheitlich für Apple II, Amiga usw.
Ich hatte damals schon an der Schule Kontakt mit dem UCSD-P-Code-System und wir haben uns auch den Spaß gemacht an der Uni (KA) teilweise direkt in P-Code zu programmieren. War auch ganz lustig und interessanterweise lief das auch auf alle P-Code-System (sogar mit C64).
Uns wurde damals noch Modula als das nonplus-ultra der Programmiertechnik verkauft.
Naja, Java wird immerhin in der Industrie verwendet.
Modula habe ich in der freien Wildbahn nie beobachtet. Wobei es ja auch einen Primitiv-Compiler hatte.
Die entsprechenden Slides der Anfängervorlesung über Java im Infornatik Bachelor, falls jemand keinen Zugang ins Uninetz hat: http://yourfiles.to/?d=5D35093336
Ich bin aber kein großer Vorlesungsgänger, keine Ahnung was also rein verbal propagiert wird.
BTW, in Lisp wird dieser syntactic sugar als Macro implementiert, dh es ist eine Spracherweiterung die sich nicht von den Erweiterungen des Programmierers unterscheidet und die zur Compilezeit in einen equivalenten if-then-else-Baum umgeformt wird. Man hat also alle Vorteile ohne eine Ausnahme gemacht zu haben und ohne zusaetzliche Komplexitaet in der eigentlichen Sprache. Und weil man das fast ueberall machen kann, ist der eigentliche Sprachkern sehr klein und jede selbstgemachte Erweiterung gleichwertig mit der eigentlichen Sprache. Ist das nicht schoen? 🙂
Oh, nachdem ich mir das mit dem Java switch nochmal angesehen habe, scheint meine Erinnerung mir einen Streich gespielt zu haben: Ist auch schon ein Weilchen her, dass ich das letzte mal Java gemacht habe.
Java scheint diesen Quatsch mit dem “durchfallen” und dem benötigen von breaks ja doch auch zu haben. Mea Culpa an alle, die ich verwirrt haben sollte. Ich dachte eigentlich, das wäre weggefallen. Insofern bezog sich der Kommentar, an den ich mich errinnere vieleicht doch nicht auf Java (war in der Konzepte von Programmiersprachen-VL), sondern war auf C# bezogen.
Naja, in diesem Fall bin ich sogar geneigt demjenigen hier in Karlsruhe zuzustimmen, der dieses Konstrukt in dieser Form kritisiert hat, falls er es aus diesem Grund getan haben sollte.
Stimmt, ich habs auch noch mal im Buch nachgesehen, Java braucht auch ein Break.
Wie gesagt, ich habe mir Java vor ca. 13-14 Jahren bei dessen ersten Erscheinen mal angesehen und es seitdem wieder weggelegt, weil mir die Sprache nicht gefallen hat. Zu sehr an C angelehnt. Und C ist ja eher ein höherer Assembler als eine Hochsprache.
Das heißt aber nicht, daß man was gegen die Case-Anweisung haben könnte, sondern was gegen die Programmiersprachen C/C++/Java.
Insofern kann ich die Karlsruher Haltung nicht recht nachvollziehen, sich so auf eine Sprache festzulegen und dann daraus (evtl.) einzelne Konstrukte zu verteufeln.
Ich bin ein großer switch-Freund, auch wenn ich es nur selten benutze.
Bei 2-3 Fällen kommt man ja hübsch mit if/else if/else aus, aber was darüber ist, ist mit einem switch gut abgebildet.
Ich kenne zwei Kritikpunkte, 1. daß man break vergißt, und 2. daß man in OO-Sprachen ableiten kann, und so für jedes Objekt den richtigen Code aufrufen kann.
Teils wurde dem bei Java begegnet, in dem man den enum-Typen geschaffen hat, ein aufgeblasenes Monstrum welches ich ungern verwende, wie auch das Objekt, welches dank Ableitung eben in seinem Fall etwas spezielles macht, nicht immer praktisch ist.
Naja – und wer beharrlich break vergißt, der soll doch eine IDE benutzen, die ihn bei sowas warnt, oder Spargel ernten gehen. 🙂
In Scala, eine junge, funktional-oo-Sprache für die JVM, kann man gleich über beliebige Objekte switchen, nicht blos über integrale Typen:
scala> def msg (s: String) = s match {
| case "foo" => println ("Foo!")
| case "bar" => println ("Bar?")
| case _ => println ("wat'n? wat'n? wat'n?") }
In Java kann man beispielsweise keinen Eventhandler für Buttons so implementieren:
public void actionPerformed (ActionEvent ae)
{
int c = ae.getActionCommand ().toString ().hashcode ();
switch (c)
{
case "run".hashcode () : run () ; break;
case "help".hashcode () : help () ; break;
case "print".hashcode (): print () ; break;
case "exit".hashcode () : exit () ;
default: throw new SleepingProgrammerException ("handler vergessen!"); break;
}
}
obwohl das zu schön lesbarem Code führen würde.
Explizite breaks sind immer nützlich, wenn man Gruppen bilden kann:
case 'A':
case 'E':
case 'I':
case 'O':
case 'U': return ("Vokal");
—
Da es keine Vorschaufunktion und keine Kurzliste erlaubter Syntax gibt riskiere ich meine Tags in spitzen Klammern auf Gefahr des Blogbetreibers. 🙂
Hm. Codeblöcke funktionieren so zumindest nicht. Aber ich habe auch vergessen zu sagen, wieso der Javahandler nicht funktioniert: Weil die Sprungziele Konstanten sein müssen, die zur Compilezeit feststehen.
Dazu passend ein Ranking der Programmiersprachen:
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Gefunden bei fefe.
Sieht so aus, als ob ich das mit meinem Kommentar auf Danisch.de gestartet hab, siehe https://www.danisch.de/blog/2010/04/02/wieder-so-ein-linux-desktop-argernis/comment-page-1/#comment-2686
Ganz so schlimm ist es nicht, aber wie ich dort geschrieben hab, manche scheinen es ueberhaupt nicht zu moegen.
Als einer dieser Karlsruher Leser kann ich Dir nur sagen, dass bei uns Java case/Switch als gut und wichtig gelehrt wurde und dass C++ Äquivlanent als Teufelswerk (wegen dem oft vergessenen und nicht wirklich intuitivem break) gelehrt wurde. Der Fall, dass man in einer Fallunterscheidung in den nächsten Fall durchrutschen will, d. h. die Variante ohne break, ist ja eher der Sonderfall, als der Default.
Ansonsten ist bei den neuen Bachelor-Studenten Java wirklich das Maß der Dinge. Das bei den Diplomern noch gelehrte Haskell/Gopher wird wohl nicht mehr gemacht. Die Grundlagenprogrammierung wandelt sich gerade in Richtung Java und Konzepte des parallelen Programmierens.