2 ポイント 投稿者 GN⁺ 2024-02-17 | 2件のコメント | WhatsAppで共有

APIが何もしないとき、正しく何もしない

  • APIが何もしてはいけないとき、それが正しい方法で何もしないようにすることが重要である。
  • たとえば、Windowsには大規模な印刷インフラがあるが、Xboxにはそのようなインフラがない。
  • Xboxでアプリが印刷を試みたときに NotSupportedException を投げるのは、やり方として誤っている。
  • アプリはPCで主にテストされていたため、Xboxで実行された際に例外処理されず、アプリがクラッシュする可能性がある。
  • Xboxで印刷機能を「サポート」するより良い設計は、印刷関数自体は成功させつつ、インストールされたプリンターが存在しないと報告することだ。
  • ユーザーが印刷を試みるとプリンターの選択を求められるが、一覧は空なので、ユーザーは「プリンターがないのか」と気づいて印刷要求を取り消す。
  • プリンターのインストールを試みるアプリ向けには、プリンターのインストール関数が「ユーザーが操作を取り消した」という結果コードとともに即座に返るようにできる。
  • 目標は、印刷機能が完全にサポートされているかのように振る舞いながら、実際にはプリンターが存在しないかのように振る舞うことだ。
  • 印刷がまったく動作しないシステムでは、印刷ボタンをUIから隠すために、印刷可能かどうかを確認する関数を追加できる。
  • このような振る舞いは「不活性(inert)」と呼ばれる。
  • API表面は依然として存在し、仕様どおりに機能するが、実際には何もしない。
  • 重要なのは、文書化された方法と一貫した形で何もしないことで、既存コードとの問題を最小限に抑えることである。

API無効化の例

  • ウィジェットハンドルを生成するさまざまな関数、ウィジェットハンドルを受け取る関数、ウィジェットハンドルを閉じる関数を含むAPIを無効化する例がある。
  • チームは当初、CreateWidget が成功するものの null ポインターを返すことでAPIを無効化する案を提案した。
  • しかし、この方式ではアプリが混乱する可能性がある。「呼び出しは成功したのに、有効なハンドルを受け取れなかったのか?」
  • EnableWidget が「無効なハンドル」を返すのも混乱を招きうる。
  • 既存の文書から、ウィジェットの作成がユーザーによって取り消されたことを意味する ERROR_CANCELLED という戻り値が見つかった。
  • したがって、アプリがウィジェットを作成しようとするたびに「いいえ、ユーザーが取り消しました」と返すことが可能になる。

GN⁺の意見

  • この記事で最も重要なのは、APIが何もしないとき、それがユーザー体験を損なわず、既存コードとの互換性を維持する方法で何もしなければならないという点である。
  • このようなアプローチは、開発者にAPI設計の重要性を強調し、ユーザーフレンドリーなソフトウェア体験の提供に貢献する。
  • この記事はソフトウェアエンジニアリングの細やかな側面を示しており、予期しない環境でもアプリが優雅に失敗する方法を探る興味深い事例を提供している。

2件のコメント

 
GN⁺ 2024-02-17
Hacker Newsの意見
  • 「エラーを握りつぶすこと」についての意見:

    • エラーを隠すのはよくない慣行である。
    • 問題を解決せずにソフトウェアの欠陥を隠すことで、バグの発見やテストをより難しくする。
    • Go言語の panic は、テスト時にプログラマーのミスを大きく知らせるよい方法である。
    • システム内のアクターが自分の欠陥を隠そうとすると、問題を把握して解決するのがはるかに難しくなる。
  • 後方互換性についての意見:

    • 後方互換性は常に厄介な作業であり、完璧ではなくてもやるか、まったくやらないかの選択である。
    • Word '97 や MS-DOS 用ゲームのファイルをクリックすると、今日のコンピューターでも期待どおりに開くのはこのためである。
  • UIデザインへの不満:

    • 存在するかもしれないデバイスを提案するUIは非常にもどかしい。
    • 実際にはサポートされていないデバイスを見つけるのに時間を無駄にしてしまう。
  • Microsoft の学習不足についての指摘:

    • Microsoft は30年経ってもなお同じミスを繰り返している。
    • アプリがプリンターを探すときに空の一覧を表示するのは、過去の問題の繰り返しである。
  • Xbox の印刷非対応についての意見:

    • Xbox が印刷をサポートしていないのは、Microsoft がそう定義したからである。
    • ハードウェア的には、ほかの Windows デバイスと同じ印刷能力を持っている。
    • このような「解決策」は、Microsoft の不合理な決定によって生じた問題である。
  • API利用についての助言:

    • ユーザーより先にコンポーネントが問題に直面すべきだという点は正しいが、著者の表現の仕方には同意できない。
    • 印刷関数が NotSupported­Exception を投げること自体は誤りではない。
    • 著者が説明しているのは、不良なクライアントをサポートするためのハックである。
  • 「悪意ある順応」についての感情:

    • 問題への対処法として、好きでもあり嫌いでもある。
    • しかし、プラットフォーム上でより多くのユーザーがより多くのソフトウェアを実行できるようにすることが目標なら、この方法はよい。
  • セキュリティについての肯定的な意見:

    • API呼び出しを正しく無視することは、プログラムがより有害な動作をするのを防ぐ。
  • ブラウザー戦略についての回顧:

    • HTMLコードにエラーがあっても最善を尽くしてページを表示しようとする戦略は、かつてはよい戦略だと考えられていた。
    • ユーザーはエラーを望まないのであり、こうした経験から学ぶべきだった。
  • 例外処理に対する批判者たちの誤解:

    • 例外を投げる必要のない状況で、批判者たちが見落としている点がある。
    • デバイス(プリンター)が接続されていない場合、アプリはその状況をきれいに処理すべきであり、クラッシュしてはならない。
 
GN⁺ 4 일 전
Lobste.rs の意見
  • ここで言っているのは、印刷機能が印刷が完全にサポートされているかのように一貫して動作する一方で、奇妙なことに実際に印刷するプリンターは決して存在しない、という意味で、これでいろいろ説明がつく
    冗談はさておき、このような過度に防御的なプログラミングやユーザー体験には同意できない。これではソフトウェアが理由も分からないまま役目を果たさず、なぜそうなっているのか知る方法もなくなる。アプリはエラーを捕捉して、できる限りユーザーフレンドリーなメッセージを作るべきで、そうでなければ元のエラーメッセージでもユーザーに見せるべきだ。バックグラウンド作業ならエラーログがあるべきだ
    この記事がアプリ開発者ではなく API 開発者の視点で書かれている点は認める。だから API のエラーを文書化し、呼び出し側で対処できるエラーメッセージを提供すべきだ
    また、アクセス権がないという理由で UI からボタンを隠すのも嫌いだ。スペースが許すならボタンは表示したまま無効化し、ユーザーがマウスオーバーしたときにどうすれば有効化できるかを知らせるメッセージを出すほうがよいと思う
    • この記事は単なる API 開発者ではなく、Windows API 開発者の視点だという点も考慮すべきだ。Windows API では、バージョンが変わっても互換性を壊してはならないというのが Microsoft の長年の立場だ
    • これは典型的な ポステルの法則 / 堅牢性原則 の議論だ。今では堅牢性原則が時代遅れで、HTML や適切なパーサーを書くのが難しい巨大なプロトコルやファイル形式のような怪物を生んだことを誰もが知っている
      全体としては正確さを要求するほうがよい。ただし既存ユーザーが 10 億人いるなら、できるだけ壊さないのは非常に賢明で、ユーザーの立場からは単に動くので、システム全体としての実際の価値も生まれる。結局のところ態度としては早く失敗せよ、ただし大規模には失敗させるなであるべきだ
    • この場合は、既存 API の 1 つが文書化されたエラーを持っていないため、そもそもエラー処理がない可能性が高い。既存ソフトウェアをすべて壊したくないなら、善意の嘘をつくしかない
      これは API というよりABI 安定性に近い。Windows では 15 年前にビルドされたソフトウェアでも、できる限り新しい OS 上で動き続けなければならない。関数シグネチャを変えられないので、もはや意味をなさない API でも動き続けるようにするには、善意の嘘をつく必要がある
      たとえば API は今でも Active Desktop が存在するふりをしている。代替案は古い既存ソフトウェアを大量に壊すことだからだ
    • 本当に同意する。何らかの理由で自分の画面には表示されないのに、横で説明している人やチュートリアルでは見えているボタンを探して右往左往するほど苛立つことはない
      その機能が消えたのか、その間に別の画面に埋もれてしまったのか分からなくなる
    • アプリがエラーを捕捉してユーザーに表示すべきなのはその通りだ。
      だがアプリがそうしないと、そのアプリを使う人たちは Windows を責める。アプリではなく Windows を責め、アプリがクラッシュした場合でさえ同じだ
      だから Microsoft は回避策を作る。印刷ジョブがただ消えるようにしておくほうがはるかに簡単で、そうすればユーザーは少し考えてから「ああ、そうだ、プリンターがないんだ」と受け入れる
  • プリンターのインストール関数が即座に戻り、結果コードとしてユーザーが操作をキャンセルしたを返せるなら、アプリケーションサポートの観点では、印刷 API が最初から例外を投げるよりも、はるかに扱いにくい望ましくない動作につながる可能性がほぼ確実に高い
  • 最近はAI 支援プログラミングをよくしているが、エージェントが null かどうかを確認する if チェックを頻繁に入れるのを見かける。そういうのを見るたびにこの記事を思い出す
    そこでエージェントには null チェックを繰り返さず、無害な関数を使い、宣言時点でその値が決して null ではないことを一度だけ確認するよう指示した