Wenn man schon nichts tun wird, dann sollte man es wenigstens richtig tun
(devblogs.microsoft.com)- Selbst wenn eine tatsächliche Funktion wegen einer bestimmten Plattform oder eines eingestellten Zustands nicht bereitgestellt werden kann, muss ein „Nichtstun“-Verhalten innerhalb des dokumentierten API-Vertrags entworfen werden, damit bestehende Apps nicht kaputtgehen
- In einer Umgebung ohne Druckinfrastruktur wie Xbox ist für nach PC-Maßstäben geschriebene Apps eine erfolgreiche Antwort mit 0 Druckern sicherer als eine
NotSupportedException - Dieser Ansatz ist eine inert API: API-Oberfläche und Spezifikation bleiben erhalten, aber tatsächlich wird keine nützliche Arbeit ausgeführt
- Wenn in einer eingestellten Widget-API
CreateWidgeterfolgreich ist, abernullptrzurückgibt, geraten Aufrufer in einen widersprüchlichen Zustand; der dokumentierte Fehlerpfad mitERROR_CANCELLEDist konsistenter - Eine korrekt gestaltete inert API lässt nur die Funktionalität verschwinden und reduziert über bereits im bestehenden Code berücksichtigte Fehlerpfade Ausnahmen, ungültige Handles und Abstürze
Auch ohne Funktion bleibt der API-Vertrag bestehen
- Es gibt Fälle, in denen eine API nichts tun soll, aber auch dieses Nichtstun muss zum bestehenden Code und zum dokumentierten Verhalten passen
- Falsch entworfenes Nichtstun kann Ausnahmen, widersprüchliche Rückgabewerte und ungültige Zustände erzeugen und so zu App-Abstürzen oder unnötigen Benutzerfehlern führen
So werden Druck-APIs auf Xbox inert gemacht
- Windows verfügt über eine umfangreiche Druckinfrastruktur, Xbox jedoch nicht
- Wenn eine App auf Xbox zu drucken versucht und die Druckfunktion dabei eine
NotSupportedExceptionauslöst, kann das größere Probleme verursachen- Apps, die auf Xbox installiert sind, wurden wahrscheinlich vor allem auf PCs getestet
- Auf dem PC ist Drucken immer möglich, daher kann eine unbehandelte Ausnahme zum Absturz der App führen
- Selbst wenn die Ausnahme abgefangen wird, könnte der Benutzer eine Fehlermeldung wie „Geben Sie dem Support den Incident-Code an“ sehen
- Ein besseres Design ist, dass die Druckfunktion erfolgreich ist, aber meldet, dass keine installierten Drucker vorhanden sind
- Die App zeigt dann eine UI zur Druckerauswahl und eine leere Liste an
- Der Benutzer sieht, dass keine Drucker vorhanden sind, und kann den Druckvorgang abbrechen
- Für Apps, die bei der Druckerinstallation helfen wollen, kann die Installationsfunktion sofort zurückkehren und einen Ergebniscode liefern, der bedeutet, dass der Benutzer den Vorgang abgebrochen hat
Bedingungen für eine inert API
- Ein solches „Nichts tun“-Verhalten wird als inert bezeichnet
- Eine inert API behält die API-Oberfläche bei und verhält sich gemäß der Spezifikation, führt aber tatsächlich keine nützliche Arbeit aus
- Entscheidend ist, auf eine Weise nichts zu tun, die mit der Dokumentation konsistent ist und bestehendem Code mit der geringsten Wahrscheinlichkeit Probleme bereitet
- Für die Druck-API könnte man zusätzlich eine Funktion einführen, die prüft, ob Drucken überhaupt möglich ist
- Apps könnten diese Funktion nutzen, um den Button „Drucken“ auf Systemen auszublenden, die Drucken überhaupt nicht unterstützen
- Apps, die einfach davon ausgehen, dass Drucken möglich ist, verhalten sich dann so, als liefen sie auf einem System „ohne Drucker und ohne wirksamen Installationsversuch“
Welches Design man bei einer auslaufenden Widget-API vermeiden sollte
- Die auslaufende API enthält eine Funktion zum Erzeugen eines Widget-Handles, eine Funktion, die ein Widget-Handle entgegennimmt, und eine Funktion zum Schließen eines Widget-Handles
- Der ursprüngliche Vorschlag war, dass
CreateWidgetS_OKzurückgibt und dabei*widget = nullptrsetzt- Der Aufruf war erfolgreich, aber es wurde kein gültiges Handle geliefert
- In tatsächlichem Testcode gab es Fälle, in denen der Erfolg nicht am Rückgabewert, sondern daran erkannt wurde, ob das Handle
nullwar
- Auch ein Design, bei dem
EnableWidget„ungültiges Handle“ zurückgibt, verwirrt Aufrufer- Die App übergibt das nach erfolgreichem
CreateWidgeterhaltene Handle anEnableWidget - Die API antwortet, dass dieses Handle ungültig sei
- Der Aufrufer erlebt damit einen widersprüchlichen Zustand: „Ich habe ein Widget angefordert und erhalten, aber wenn ich es jetzt erneut verwende, heißt es plötzlich, es sei gar kein Widget“
- Die App übergibt das nach erfolgreichem
Überarbeitung mit einem dokumentierten Fehlerpfad
- In der bestehenden Dokumentation gibt es bereits den Rückgabewert
ERROR_CANCELLED, der bedeutet, dass der Benutzer die Widget-Erstellung abgebrochen hat - Da Apps ohnehin damit umgehen müssen, dass ein Widget wegen externer Bedingungen möglicherweise nicht erstellt werden kann, kann man die Widget-Erstellung so gestalten, dass sie immer mit Benutzerabbruch fehlschlägt
- Der Ablauf des überarbeiteten Designs ist einfach
CreateWidgetbelässt*widget = nullptrund gibtHRESULT_FROM_WIN32(ERROR_CANCELLED)zurück- Da die Widget-Erstellung immer fehlschlägt, gibt es kein gültiges Widget-Handle
GetWidgetAliases,EnableWidget,ClosegebenE_HANDLEzurück, also dass das Handle ungültig ist
- Bei diesem Ansatz muss auch kein Dummy-Alias erzeugt werden
- Da es kein gültiges Widget gibt, kann die App auch in keinem normalen Fall erfolgreich einen Alias anfordern
Maßstäbe beim Übertragen von Desktop-APIs in andere Umgebungen
- Auf dem Desktop war die Druck-API immer vorhanden, und die Funktion zum „Abrufen der Druckerliste“ ist so dokumentiert, dass sie keine Ausnahme auslöst
- Wenn diese API auf Xbox gebracht wird und bestehende Desktop-Apps weiterlaufen sollen, ist ein inert Verhalten korrekt, das ehrlich zurückgibt: „Auf Xbox gibt es keine Drucker“
- Auf die Frage „Wie viele Drucker gibt es?“ mit einer Ausnahme zu reagieren, passt nicht zum dokumentierten API-Vertrag
- Dasselbe Prinzip gilt auch beim Einstellen bestehender APIs
- Auch wenn keine nützliche Arbeit mehr ausgeführt wird, muss das API-Verhalten mit dem Vertrag konsistent bleiben
- Wichtig ist, Rückgabewerte und Zustände zu verwenden, die bestehender Code bereits verarbeiten kann
2 Kommentare
Lobste.rs-Kommentare
Spaß beiseite: Ich stimme dieser übermäßig defensiven Programmierung und User Experience nicht zu. So erfüllt die Software stillschweigend ihre Aufgabe nicht, ohne dass man den Grund kennt, und es gibt keine Möglichkeit herauszufinden, warum. Die App sollte Fehler abfangen und, wenn möglich, eine benutzerfreundliche Meldung erzeugen, oder andernfalls zumindest die ursprüngliche Fehlermeldung dem Nutzer anzeigen. Bei Hintergrundaufgaben sollte es ein Fehlerprotokoll geben
Ich räume ein, dass dieser Text aus der Perspektive eines API-Entwicklers und nicht eines App-Entwicklers geschrieben wurde. Daher sollte man API-Fehler dokumentieren und Fehlermeldungen bereitstellen, anhand derer die aufrufende Seite Maßnahmen ergreifen kann
Ich mag es auch nicht, wenn in der UI Buttons versteckt werden, nur weil Zugriffsrechte fehlen. Wenn der Platz es zulässt, ist es besser, den Button anzuzeigen, aber zu deaktivieren, und beim Darüberfahren mit der Maus eine Meldung einzublenden, wie man ihn aktivieren kann
Insgesamt ist es besser, auf Korrektheit zu bestehen. Wenn man allerdings eine bestehende Nutzerbasis von 1 Milliarde Menschen hat, ist es sehr klug, möglichst nichts kaputtzumachen, und aus Nutzersicht entsteht dadurch auch ein realer Wert auf Systemebene, weil es einfach funktioniert. Letztlich sollte die Haltung sein: früh scheitern, aber nicht dafür sorgen, dass massenhaft Dinge scheitern
Das hat weniger mit der API als mit ABI-Stabilität zu tun. Unter Windows sollte möglichst auch Software, die vor 15 Jahren gebaut wurde, auf neuen Betriebssystemen weiterlaufen. Man kann die Funktionssignatur nicht ändern, also muss man wohlwollend lügen, damit auch APIs, die eigentlich keine Bedeutung mehr haben, weiter funktionieren
Zum Beispiel tut die API noch immer so, als gäbe es Active Desktop. Die Alternative wäre, in großem Umfang alte Bestandssoftware zu beschädigen
Dann weiß man nicht, ob die Funktion verschwunden ist oder inzwischen unter einem anderen Bildschirm vergraben wurde
Aber wenn die App das nicht tut, geben die Menschen, die diese App benutzen, Windows die Schuld. Sie geben Windows die Schuld und nicht der App, und das gilt sogar dann, wenn die App abstürzt
Deshalb baut Microsoft Umgehungslösungen. Es ist viel einfacher, den Druckauftrag einfach verschwinden zu lassen, und dann denkt der Nutzer kurz nach und akzeptiert: „Ach ja, ich habe ja keinen Drucker.“
if-Prüfungen auf null einbauen. Jedes Mal muss ich an diesen Artikel denkenDeshalb habe ich dem Agenten gesagt, er solle solche null-Prüfungen nicht wiederholen, sondern harmlose Funktionen verwenden und beim Deklarieren einmal sicherstellen, dass der Wert niemals null ist
Hacker-News-Meinungen
Ich habe es als Fehler verschlucken kennengelernt und halte es für eine schlechte Praxis.
Es löst nicht nur das eigentliche Problem nicht, dass auf der Xbox nicht gedruckt werden kann, sondern verbirgt auch, wie kaputt die Software ist, und macht das Finden von Bugs und das Testen deutlich schwieriger.
Gos
panicist gut, weil es nicht dafür gedacht ist, zur Laufzeit missbraucht oder abgefangen zu werden, sondern beim Testen laut Alarm schlägt, dass der Programmierer etwas falsch gemacht hat.Wenn Akteure in einem System ihre eigenen Defekte oder Fehler aktiv verbergen, wird es exponentiell schwieriger, die Ursache zu finden und zu beheben.
In den B2B-, Microservice- und API-zentrierten Systemen, mit denen ich zu tun habe, ist es richtig, Anfragen außerhalb der Spezifikation schnell fehlschlagen zu lassen.
Windows hat sich jedoch für Kompatibilität enorm verbogen, und es gab Fälle, in denen berühmte kaputte Software wie SimCity sogar mit Memory-Patches am Leben gehalten wurde: https://arstechnica.com/gadgets/2022/10/windows-95-went-the-...
In einer Desktop-Umgebung, in der Nutzer den Systemcode nicht reparieren können, ist in vielen Fällen die Endnutzererfahrung wichtiger als Korrektheit.
Warum es zu einem BSOD kam, ist nicht wichtig; Microsoft hat gelernt, dass schlechte Software oder Hardware dem Ruf von Microsoft schadet.
Persönlich bevorzuge ich Designs, die bei ungültigen Eingaben oder Bedingungen schnell fehlschlagen oder abbrechen, aber in diesem Umfeld verstehe ich auch den Wert dieses Ansatzes.
Entscheidend ist der Kontext, nicht die dogmatische Anwendung der einen oder anderen Seite.
Zum Beispiel sollte man Chens Ansatz nicht auf das Design von Kernreaktoren oder High-Frequency-Trading übertragen; für eine Game-Engine kann er ausgezeichnet sein.
Die Frage, ob man eine Runtime-Komponente „harmlos inaktiv“ lässt, ist eine Designentscheidung, die der Frage vorausgeht, ob die Implementierung ein
panicauslöst oder nicht.In diesem Fall ist es Microsofts Sache, die Bedeutung von „auf der Xbox drucken“ festzulegen.
Man kann es als Fehler definieren oder theoretisch als eine Funktion, die später unterstützt werden könnte, für die es derzeit aber keine praktische Ausführungsmöglichkeit gibt.
Wenn man einen USB-Drucker anschließt und ein „Spiel“, etwa ein Gameboy-Spiel mit Erweiterungsport, das den GB Printer unterstützte, weiß, wie gedruckt wird, könnte man theoretisch auch auf der Xbox drucken.
Dass ein Xbox-Spiel versucht zu drucken, ist nicht zwangsläufig ein inhärenter Fehler; es als Fehler zu definieren, ist ebenfalls nur eine Entscheidung mit Trade-offs, etwa bei der Portabilität von Anwendungen.
Man könnte wie auf der Xbox einen Auswahldialog ohne auswählbaren Drucker anzeigen, die API lügen lassen, dass gedruckt wurde, oder echtes Drucken unterstützen.
Erst nachdem man die Bedeutung von „auf der Xbox drucken“ als Fehler definiert hat, wird es zu einem Implementierungs- oder Debugging-Problem, ob dieser Fehler nicht geworfen, sondern verschluckt wird.
Es gibt zwei mögliche Behandlungen: einen Fehler ausgeben, weil die Maschine niemals einen Drucker hat, oder eine leere Druckerliste zurückgeben, weil die Maschine niemals einen Drucker hat.
Beides ist plausibel, aber nur eines davon macht den Userspace nicht kaputt.
„Laut Alarm zu schlagen“ ist für Tester oder Entwickler gut, für Endnutzer aber weniger.
Aus Sicht des Endnutzers ist es besser, den Fehler zu verschlucken, als die App abstürzen zu lassen.
Man kann nicht erkennen, was fehlgeschlagen ist: die Software auf meinem Computer, die Hardware, das Ethernet-Kabel oder WLAN, der Switch, der Router, das Kabelmodem, das Internetkabel bis zu meinem Haus, der ISP oder das entfernte System, zu dem ich eine Verbindung herstellen will – daran hat sich überhaupt nichts verbessert.
Negative Reaktionen sind zu erwarten, aber genau diese schmutzige Arbeit ist der Grund, warum ein Word-’97-Dokument oder ein vor 30 Jahren für MS-DOS kompiliertes Spiel beim Anklicken so geöffnet wird, wie man es erwartet.
Abwärtskompatibilität ist immer messy, und entweder man macht sie unvollkommen oder gar nicht.
Am Ende nutzt man GOG, und GOG virtualisiert letztlich ebenfalls die Umgebung.
Zum Beispiel glaube ich nicht, dass jemand das originale Sim City erfolgreich unter Windows 11 installieren wird.
Die Formatierung hing von den installierten Druckertreibern ab.
Eine LaTeX-Datei von vor 35 Jahren funktioniert dagegen heute noch gut.
Word konnte nicht garantieren, dass sich die Formatierung nicht ändert, selbst wenn man die Datei auf demselben Computer und mit derselben Version erneut öffnet; deshalb habe ich TeX gelernt.
Bei Spielen hat Microsoft außerdem mit der Einstellung von GFWL zahlreiche Spiele kaputtgemacht.
Das originale Dark Souls war bis zur erneuten Veröffentlichung auf Steam nicht spielbar, sodass man eine Raubkopie verwenden musste.
Es erscheint ein Dialog „nicht unterstützt“, und man kann dosbox herunterladen, aber das ist nicht „genau wie erwartet“.
Fast jedes Mal habe ich aufgegeben oder sie bei GOG erneut gekauft; im Grunde habe ich also für die Arbeit bezahlt, Kompatibilitätsprobleme aufzuräumen.
Nichts ist so frustrierend wie eine Geräte-UI, die andeutet, dass Geräte tatsächlich existieren könnten, dann aber sagt, dass derzeit keine vorhanden sind.
Am Ende muss man erst Zeit investieren, um herauszufinden, dass diese Geräte gar nicht unterstützt werden und dieser Bildschirm nur ein Mockup war, das jemand gebaut hat.
Wenn eine App nicht auf den Fall vorbereitet ist, dass Drucken nicht unterstützt wird, und die Ausgabe eine Exception wirft, stürzt die App vermutlich einfach ab.
Eine App, die den Fall fehlender Druckunterstützung berücksichtigt, sollte zuerst über eine explizite API prüfen, ob Drucken unterstützt wird, und die Druck-UI nicht anzeigen, wenn es nicht unterstützt wird.
Der Artikel handelt nicht von solchen Apps, sondern davon, wie man mit Apps umgeht, die vorher nicht prüfen.
Der Bug liegt in der App, aber eine gute Plattform sollte versuchen, auch schlechte Apps möglichst weiter funktionieren zu lassen, statt sie einfach abstürzen zu lassen.
Microsofts Rolle besteht darin, zu verhindern, dass eine App abstürzt, nur weil der Softwareanbieter Drucker nicht bedacht hat.
Dass eine App, wenn sie drucken will, den Benutzer zur Druckerauswahl auffordert und dann eine leere Liste zeigt — offenbar hat Microsoft in 30 Jahren nichts gelernt: https://www.reddit.com/r/hacking/comments/djvzd/windows_nt_l...
Die im Artikel vorgeschlagene konkrete Richtung, nämlich dass die Komponente leiden sollte, bevor der Benutzer leidet, ist richtig, aber das Framing ist extrem störend.
Aussagen wie „Manchmal muss man eine API so machen, dass sie nichts tut“ oder „Es ist falsch, wenn eine Druckfunktion
NotSupportedExceptionwirft“ sind absolut kein allgemeiner Rat.Das ist ein Hack, um schlechte Clients zu unterstützen; manchmal ist er nötig, aber normal oder verallgemeinerbar ist dieser Rat nicht.
In solchen Formulierungen sieht man Spuren davon, dass der Schmerz eines Microsoft-Entwicklers verinnerlicht wurde.
Wenn sich der Client nicht geändert hat, die API ihn aber kaputtmacht, dann ist nicht der Client schlecht, sondern die API.
Für jede weit verbreitete Plattform, die Abwärtskompatibilität ernst nimmt, ist das völlig normal und verallgemeinerbar.
Windows ist das Paradebeispiel, aber dasselbe passiert auch beim Linux-Kernel-ABI, bei glibc, der Webplattform, Java usw.
Man kann die Zeit nicht zurückdrehen und die Clients neu kompilieren oder neu schreiben.
Wenn ein Client bereits auf
NotSupportedExceptionprüft, muss man sie zurückgeben; wenn nicht, braucht man einen anderen Ansatz.Das hier ist Windows.
Anwendungen, auf die Benutzer angewiesen sind, dürfen nicht kaputtgemacht werden.
Wenn es „schlechte“ oder fehlerhaft funktionierende Client-Apps gibt, muss man alle nötigen Workarounds, Shims und Kompatibilitäts-Hacks einsetzen, damit sie wie erwartet funktionieren.
Selbst wenn man speziellen Speicherverwaltungscode einbauen muss, damit SimCity läuft.
Dein Kunde ist auf diesen Client angewiesen, und wenn er wegen deiner Änderung nicht mehr läuft, wird er dir die Schuld geben.
Hier hängen sich alle an „nichts tun“ und „Fehlerbehandlung“ auf, aber der Artikel scheint nicht gut genug erklärt zu haben, dass es nicht darum geht, jedes Problem zu schlucken und kumbaya zu singen.
Der eigentliche Kontext ist Emulation und Kompatibilität für Software, die sich nicht mehr ändern wird, und das unterscheidet sich sehr stark von den meisten Situationen.
Microsoft selbst verwischt diese Grenze oft, was es noch verwirrender macht, aber hier geht es nicht um gewöhnliche Fehlerbehandlung.
Emulation bedeutet im Kern, zu lügen.
An eine Xbox kann man tatsächlich keinen Drucker anschließen, unter Linux läuft ein Windows-Spiel, und ein falsches iPhone kann in Wahrheit ein ARM-Server bei AWS sein.
Wenn man lügt, muss man überzeugend lügen, damit bestehende Anwendungen weiter funktionieren.
Wenn Microsoft sagt, man könne bestehende Windows-Apps auf die Xbox portieren, und Windows-Apps das Versprechen hatten, drucken zu können, dann muss die Xbox so lügen, dass es möglich aussieht.
Wenn ein Programm dagegen ein Use-after-free hat und man still so tut, als gäbe es den Bug nicht, ist das keine korrekte Behandlung.
Denn niemand hat versprochen, dass selbst bestehende Use-after-free-Bugs auf der neuen Plattform buggenau kompatibel bleiben.
Das nimmst du nur an, weil diese Interpretation die Position stützt, die du vertreten willst.
Tatsächlich gilt der Inhalt des Artikels genauso, wenn ich morgen ein Programm für die Xbox schreibe und drucken will.
Es gibt keine Abgrenzung, dass dieses Verhalten nur für alte, nicht mehr gewartete Software gelten soll.
Ich mag diesen Ansatz und mag ihn zugleich nicht.
Instinktiv gefällt es mir nicht, Probleme durch böswillige Befolgung zu behandeln.
Andererseits stimme ich völlig zu, dass es eine gute Entscheidung ist, wenn das Ziel darin besteht, mehr Benutzern zu ermöglichen, mehr Software auf der Plattform auszuführen, selbst wenn Drucken kaputt ist.
Dieser Kommentarverlauf war seltsam.
Es gibt eindeutig Leute, die alles hassen, was Microsoft tut.
Der Kern des Blogs ist, den Weg, Apps (UWP) auf die XBOX zu bringen, möglichst reibungslos zu machen.
Ohne Neukompilierung, ohne hässliche
ifdefs, ohne Zusatzarbeit soll die App „einfach funktionieren“, und danach kann der Entwickler die App an die XBOX-Plattform anpassen.Entscheidend ist, dass der Entwickler die App ohne irgendeinen Aufwand auf die XBOX bringen konnte, und das ist sowohl für die Plattform als auch für die Entwickler gut.
Für den Benutzer ist eine leere Druckerliste ein klares Signal, dass Drucken nicht möglich ist.
Vor allem stürzt die App nicht ab und zeigt auch nicht den schlimmstmöglichen Fehler wie „Es ist ein Problem aufgetreten. Bitte versuchen Sie es später erneut“ an.
Diese Meldung ist keine bessere User Experience.
Der Entwickler kann die App neu kompilieren und eine aussagekräftigere Meldung einbauen, aber dann ist man wieder am Ausgangspunkt.
Zum Beispiel geht der Vorwurf, Fehler würden geschluckt, völlig am Kern vorbei.
Der zentrale Punkt, den die Kritiker dieses Textes übersehen, ist, dass es hier keine Ausnahmesituation gibt, in der eine Exception geworfen werden müsste.
An diesem Gerät ist kein Drucker angeschlossen, und da das in diesem Fall per Definition so ist, sollte die App damit sauber umgehen und nicht abstürzen.
Ein Notebook würde auch keine Exception werfen, nur weil es keinen Zugriff auf einen Drucker hat.
Wenn man in den Einstellungen einen Drucker hinzufügt und während der Installation zum Tab „Color Profiles“ wechselt, stürzt gnome-control-center bei passendem Timing ab.
Schaut man genauer hin, versucht es, die verfügbaren Drucker aufzulisten; es weiß zwar, dass ein Drucker vorhanden sein müsste, aber die Informationen existieren noch nicht, und deshalb stirbt es einfach.
Zum Glück reicht es, ein paar Sekunden zu warten, bis GNOME die Druckerinstallation abgeschlossen hat, und die Einstellungen erneut zu öffnen.
Trotzdem sollte eine zentrale App, die Endnutzern mit unterschiedlichstem Hintergrund dabei helfen soll, den Desktop richtig zu verwenden, in einer idealen Welt niemals abstürzen.
Über Randbedingungen nachzudenken ist schwierig, und sich vorzustellen, dass auch die Behandlung von Randbedingungen wiederum eigene Randbedingungen hat, ist noch schwieriger.
Ob richtig oder falsch: Zumindest denkt der Autor tiefer darüber nach als nur „schlechte App, sie sollte neu geschrieben werden, damit sie Wayland unterstützt“.
Eine Zeit lang galt es als hervorragende Strategie, dass Browser trotz Fehlern im HTML-Code ihr Bestes taten, um die Seite anzuzeigen.
Man versuchte, die Absicht des Autors so gut wie möglich zu erraten und weiterzumachen; Fehler seien schlecht, und Nutzer wollten keine Fehler sehen.
Ich dachte, wir hätten aus dieser Erfahrung gelernt, aber offenbar nicht.
Der Versuch, sie durch strikte Validierung mit XHTML zu ersetzen, scheiterte; stattdessen war HTML5 erfolgreich, indem es zurückging und explizit definierte, wie jede mögliche fehlerhafte Sequenz zu interpretieren ist, sodass Browser sich zumindest konsistent verhalten.
Hätten frühe Browser sofort einen Fehler angezeigt, sobald sie auf ein unbekanntes Tag stießen, wären neue Browserfunktionen schon bei ihrer Geburt erstickt.
HelloundWorld!eingibt, kann man dank der gewonnenen Weisheit nun sehen, ob ein Fehler erscheint.Wenn es aber weiterhin korrekt gerendert wird, heißt das entweder, dass wir noch viel zu lernen haben, oder dass es durchaus sinnvoll sein kann, bestimmte Arten von Fehlern elegant zu behandeln und bei Ausnahmesituationen abzustürzen.
Wenn man ins Jahr 1999 zurückreisen würde, würde einem vermutlich nicht allzu viel fehlen.