Weniger Programmieren ist mehr

Wenn ein Problem mit Hilfe eines Computerprogramms bearbeitet werden soll, ist es oft hilfreich, darüber nachzudenken, welcher Ansatz so einfach ist, dass er gerade so funktioniert. Eingeweihte nennen dies The Simplest Thing that Could Possibly Work.

Diesem Paradigma folgende Lösungen können selbst dann gut funktionieren, wenn sie auf den ersten Blick absurd wirken: Die Frage Was ist der Vorname von Franz Beckenbauer? schützt gegen spam nämlich genau so gut wie ein komplexes Analyse-plugin. Auch die Methode der Riesenmaschine, neue Kommentare gegen eine kurze Liste unerwünschter Wortbestandteile (etwa !!, lugschei) zu prüfen, kommt ohne komplizierte Filtermodelle aus.

Wie es hingegen nicht geht, beschreibt Lea Verou anhand der Aufgabe, das Doppelkreuz am Anfang von URL-Fragmenten zu entfernen. In einem Buch fand sie dazu den JavaScript-Schnipsel location.hash.match(/#(\w+)/)[1]. Der enthält allerdings nicht nur einen unleserlichen regulären Ausdruck, sondern funktioniert auch nicht; so produziert die Verarbeitung des gültigen Werts #♥ einen Fehler. Verous in jedem Fall funktionierende Alternative lautet schlicht location.hash.substring(1).

Um Fehler dieser Art zu verstehen, sollte man wissen, dass viele Programmierer nicht programmieren können. Damit ist nicht gemeint, dass sie unfähig sind, lauffähigen Code zu produzieren – sie haben jedoch Schwierigkeiten, ein zutreffendes mentales Modell der Programmlogik zu entwickeln. Hinzu kommt mangelnde Lesekompetenz: So lehnen Programme etwa Email-Adressen mit Plus-Zeichen ab, weil die Entwickler nicht wissen, welche Zeichen erlaubt sind – und dennoch überzeugt sind, das Richtige zu tun.

Dass jemand einen Algorithmus oder eine Spezifikation missverstanden hat, ist jedoch für Außenstehende nicht auf den ersten Blick erkennbar, für einen selber sogar noch weniger. Unabhängig vom Ego gilt aber: Programme nach dem Simplest Thing-Prinzip zu schreiben reduziert das Risiko, etwas Unverständliches zu produzieren – selbst für jene, die sich für besonders clever halten. Als Fingerübung habe ich mir daher vorgenommen, so weit wie möglich auf reguläre Ausdrücke zu verzichten.

The Simplest Thing that Could Possibly Work muss übrigens nicht unbedingt aus eigenem Code bestehen: Spezialisierte Programmbibliotheken zu nutzen spart nicht nur Zeit, sondern reduziert ebenfalls die Fehlerrate. Faustregel: Wer komplexe Formate wie HTML parsen oder generieren möchte, sollte besser existierende Werkzeuge benutzen, als sich selbst Gedanken zu machen – sonst besteht das Risiko, eine beherrschte Technik in einem Bereich anzuwenden, für den sie vollkommen unpassend ist (Patch für Negativ-Beispiel).

Gleich doppelt beleuchtet diese Kategorie BozoCrack – ein Programm, das mit MD5 unkenntlich gemachte Passphrasen nicht selbst knackt, sondern Google bemüht (danke, plomlompom): Es benutzt nicht nur eine externe Resource, sondern zeigt auch, dass die MD5 nutzenden Entwickler nicht verstanden haben, wie Passwörter gespeichert werden sollten.

08. November 2011 von erlehmann
Kategorien: Software | Schlagwörter: , | 7 Kommentare

Kommentare (7)

  1. Manchmal sind reguläre Ausdrücke the simplest thing that could possibly work, etwa um aus ca. 3800 Kontakten in vCards alle Notizen die zu lang sind (sagen wir, mehr als 200 Zeichen) und deswegen schlechte Adressbuchsoftware verwirren, zu entfernen.

  2. Da liegt ein Missverständnis vor: Reguläre Ausdrücke können sicher oft genug schnell geschrieben sein. Auf die Programmiergeschwindigkeit beziehe ich mich allerdings an keiner Stelle.

    Sowohl du als auch ich müssen eine Weile überlegen, um ein mentales Modell der Funktionsweise von Regexes zu erstellen – das oft genug auf subtile Weise falsch ist. So ist mein URL-Regex sensitiv gegenüber der locale.

  3. Ich brauche wesentlich länger und mache wesentlich mehr Fehler bei mentalen Modellen von state machines als von einfachen bis moderat komplexen Regexen. Und “Zeilenanfang, NOTE + 200 Zeichen” passt nun mal sehr sehr gut in einen regulären Ausdruck. YMMV, ich will nur darauf hinaus, dass zu simple Regeln (keine reguären Ausdrücke) auch die simpelste Lösung verstellen.

    Und die simpelste Lösung, die grade noch so funktioniert ist halt auch nur eine Lösung, solange sie funktioniert. Franz Beckenbauer funktioniert u.a. deswegen so gut, weil es als Spamfilterlösung nicht weit genug verbreitet ist um es per Spambot zu lösen – für jede mittelgroße Plattform reicht das schlicht nicht, weil jede endliche Menge von Lösungen früher oder später in die plattformspezifischen Bots einprogrammiert wird; sollte sich das webweit durchsetzen würde die KI-Forschung auf einmal einen großen Schritt nach vorne machen (AFAIK hat das die Texterkennung aus dem gleichen Grund schon getan).

  4. Klar gibt es persönliche Vorlieben für Herangehensweisen an Informationsströme. Aber brauchst du wirklich länger, um eine Anweisung nach Schema if line.startswith('NOTE') and len(line) > 205 […] zu durchdringen, als einen verwandten regulären Ausdruck? Das glaube ich genau dann, wenn die die Laufzeit des entsprechenden Algorithmus eher erklären kannst als die einer Nicht-Regex-Variante. (Kann ja sein, ich kann mir das nur schwer vorstellen.)

    Was Franz Beckenbauer angeht: Klar ist oft genug eine Zukunft denkbar, in der die gleiche Lösung in der selben Domäne weitgehend wertlos ist. Aber Versagen ist bei Filtern dieser Art billig – einen Kommentar fälschlicherweise zuzulassen ist weder sicherheitskritisch noch besitzt es großes Stör-Potential. Beides ist bei Email-Validierung oder URL-Parsen anders: Da werden im Zweifelsfall nämlich nützliche Informationen verworfen.

    Wenn eine ähnlich simple Antispam-Lösung für die ehemals populäre Riesenmaschine ausreicht, brauche ich mir übrigens garantiert keine Gedanken über mittelgroße Plattformen zu machen.

  5. > Aber brauchst du wirklich länger …

    Ja, weil ich bzpw. an 3 verschiedene Dinge gleichzeitig denken muss um die 205 zu erklären. Weil die Python-Standardlibrary bzw. schon ihr String-Teil zu komplex ist um ihn auswendig zu können. Weil es zwei separat zu evaluierende Bedingungen an eine Zeile sind statt einer Beschreibung der Zeile.

    Auch: manchmal ist the simplest thing eben kein Python-Skript bzw. gar kein Programm, sondern ein sed-Einzeiler.

    Das Laufzeitverhalten hängt von der Implementation von .startswith und len() einerseits bzw. der Regex-Engine andererseits ab.

  6. Die Frage ist ja: Kannst du, matthiasr, aus dem Kopf heraus einen passenden regulären Ausdruck, der einen bestimmten Task erfüllt hinschreiben, ohne dafür irgendwo nachschauen zu müssen?
    Durch die Tatsache, dass eine Programmiersprache wie Python mehr (lies: “überflüssige”) Bestandteile (wie komplette Wörter statt nur Buchstaben für Funktionen, Keywords) hat ist sie eingängiger und für jemanden der ein wenig Englisch kann in Teilen sogar ohne Programmierkenntnisse lesbar. Mach das mal mit RegExes.
    Auch: Die Anforderungen im akademischen Umfeld sind teilweise sehr hypothetischer Natur (was gut ist, “Ein Hoch auf die Wissenschaft”), weshalb sie sich aber bestimmt oftmals von den Anforderungen in der Realität unterscheiden!
    Just my 2 Cents.

Schreibe einen Kommentar

Pflichtfelder sind mit * markiert


Before you post, please prove you are sentient.

Was ist der Vorname von Franz Beckenbauer?