Wenn eine API nichts tut, richtig nichts tun
- Wenn eine API nichts tun soll, ist es wichtig, dass sie auf die richtige Weise nichts tut.
- Windows verfügt zum Beispiel über eine umfangreiche Druckinfrastruktur, Xbox jedoch nicht.
- Wenn eine App auf Xbox versucht zu drucken und dabei eine
NotSupportedException auslöst, ist das der falsche Weg.
- Da die App hauptsächlich auf dem PC getestet wurde, wird die Ausnahme beim Ausführen auf Xbox möglicherweise nicht behandelt und die App stürzt ab.
- Ein besseres Design, um Drucken auf Xbox zu "unterstützen", besteht darin, dass die Druckfunktion erfolgreich ist, aber meldet, dass keine Drucker installiert sind.
- Wenn der Benutzer zu drucken versucht, wird zwar zur Druckerauswahl aufgefordert, aber die Liste ist leer, sodass der Benutzer erkennt: "Es gibt keinen Drucker" und den Druckauftrag abbricht.
- Für Apps, die versuchen, einen Drucker zu installieren, kann die Funktion zur Druckerinstallation sofort mit dem Ergebniscode "Der Benutzer hat den Vorgang abgebrochen" zurückkehren.
- Das Ziel ist, sich so zu verhalten, als würde die Druckfunktion vollständig unterstützt, tatsächlich aber so, als gäbe es einfach keinen Drucker.
- Auf Systemen, auf denen Drucken überhaupt nicht funktioniert, kann man zusätzlich eine Funktion bereitstellen, die prüft, ob gedruckt werden kann, damit der Druck-Button in der UI ausgeblendet wird.
- Dieses Verhalten wird als "inert" bezeichnet.
- Die API-Oberfläche existiert weiterhin und funktioniert gemäß Spezifikation, tut in Wirklichkeit aber nichts.
- Entscheidend ist, auf die dokumentierte und konsistente Weise nichts zu tun, um Probleme mit bestehendem Code zu minimieren.
Beispiele zum Deaktivieren einer API
- Es gibt ein Beispiel zum Deaktivieren einer API, die verschiedene Funktionen zum Erzeugen von Widget-Handles, Funktionen mit Widget-Handles als Parameter und Funktionen zum Schließen von Widget-Handles umfasst.
- Das Team schlug zunächst vor, die API zu deaktivieren, indem
CreateWidget zwar erfolgreich ist, aber einen Nullpointer zurückgibt.
- Dieser Ansatz kann Apps jedoch verwirren: "Der Aufruf war erfolgreich, aber ich habe kein gültiges Handle bekommen?"
- Auch wenn
EnableWidget "ungültiges Handle" zurückgibt, kann das Verwirrung stiften.
- In der vorhandenen Dokumentation wurde schließlich ein Rückgabewert namens
ERROR_CANCELLED gefunden, der bedeutet, dass die Widget-Erstellung vom Benutzer abgebrochen wurde.
- Daher kann man jedes Mal, wenn eine App versucht, ein Widget zu erzeugen, sagen: "Nein, der Benutzer hat abgebrochen."
Meinung von GN⁺
- Das Wichtigste an diesem Beitrag ist, dass eine API, wenn sie nichts tut, dies auf eine Weise tun sollte, die weder die Benutzererfahrung beeinträchtigt noch die Kompatibilität mit bestehendem Code gefährdet.
- Dieser Ansatz unterstreicht für Entwickler die Bedeutung von API-Design und trägt dazu bei, eine benutzerfreundliche Software-Erfahrung bereitzustellen.
- Der Beitrag zeigt eine sorgfältige Seite des Software Engineerings und liefert ein interessantes Beispiel dafür, wie Apps auch in unerwarteten Umgebungen elegant scheitern können.
2 Kommentare
Hacker-News-Kommentar
Meinung zum „Verschlucken von Fehlern“:
panicvon Go ist eine gute Möglichkeit, Programmierfehler beim Testen unübersehbar sichtbar zu machen.Meinung zur Abwärtskompatibilität:
Beschwerde über UI-Design:
Hinweis auf Microsofts mangelnde Lernfähigkeit:
Meinung zur fehlenden Druckunterstützung der Xbox:
Ratschlag zur Nutzung von APIs:
NotSupportedExceptionauslöst.Gefühl der „böswilligen Regelbefolgung“:
Positive Meinung zur Sicherheit:
Rückblick auf die Browser-Strategie:
Missverständnis der Kritiker bei der Ausnahmebehandlung:
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