防御的なソフトウェアを作る
· Matt Senter

先日、私のノートパソコンはバッテリーが切れて落ちました。電源につないで再起動すると、Comoji が動かなくなっていました。絵文字のショートカットを打っても、何も起こりません。説明もなければ、何かが変わったという手がかりもありません。シャットダウン前は動いていて、今はどうやら動かないアプリがあるだけでした。
Comoji は、いつも使っているテキスト欄でそのまま絵文字の自動補完ができるようにする、私の小さな Mac アプリです。役目は単純で、ショートカットを認識し、合致する絵文字を提示し、あとは邪魔をしないことです。それが起こらなくなれば、触れるべきプロダクトはほとんど残っていません。
ただし、Comoji は実際には壊れていませんでした。私のコンピュータ上の別の何かが引っかかっていたセキュリティ境界を、Comoji は尊重していたのです。
なぜ正しいことをするのが、何もしていないように見えるのか?
macOS には Secure Input(セキュア入力)という機能があり、機密性の高いキーボード入力が他のプロセスに横取りされないよう保護します。これは Comoji のようなアプリにとって重要です。Comoji は自動補完を提示するために、あなたが何を打っているかを認識する必要があるからです。絵文字ユーティリティがパスワード入力を覗き見る筋合いはないので、Secure Input が有効な間、Comoji は意図的に身を引きます。
今回は、もうパスワードを入力していないにもかかわらず、Secure Input を保持しているプロセスとして Chrome が表示されていました。これで片付くだろうと思って Chrome を強制終了しました。ところが Secure Input は有効なままで、今度は Apple のログインプロセスに紐づいていました。再起動後に何がおかしくなったにせよ、ブラウザを閉じるだけでは解決に足りなかったのです。
これは Apple 自身が文書化している種類の問題です。不要になっても Secure Input を有効にしたままにするアプリケーションは、キーボードイベントに依存する他のアプリケーションに干渉することがあり、それは問題のアプリケーションがバックグラウンドに回った後でも続きます。セキュリティ機構は自分の仕事をし続けますが、マシン上の別の場所にあるソフトウェアがその結果を被るのです。
Comoji が置かれていたのは、まさにその状況でした。システムがキーボード入力の保護が必要だと言っている間、Comoji は正しく動作を拒んでいました。しかし、そのどれも私には見えませんでした。アプリを書いた本人である私ですら、最初は「動かなくなった」ことしか分からなかったのです。
絵文字のショートカットが突然何もしなくなった理由を理解するために、ユーザーがオペレーティングシステムの状態を調査しなければならないというのはおかしな話です。
なぜ「自分のバグではない」は完全な答えにならないのか?
問題の原因が自分のコードの外にあると分かった時点で調査をやめたくなる気持ちは理解できます。Chrome が Secure Input を保持していた。次に Apple のログインプロセスが関わっていた。Comoji は意図どおりに振る舞っていた。これで一件落着、ですよね?
そうでもありません。それは誰が問題を引き起こしたかを説明しますが、私のアプリを使おうとしている人の助けにはなりません。その人はプロセスの所有権を眺めているわけでも、どの会社にバグ報告を送るべきか決めているわけでもありません。Comoji を見て、なぜ動かないのだろうと首をかしげているのです。
根本にある入力の問題は Comoji の外にありました。説明が欠けていることは、私が直せるものでした。
防御的なソフトウェア開発が、不正な引数のチェックや例外の捕捉を超えていくのはここです。周囲の環境が正しく振る舞わなくなったとき、自分のアプリケーションがどう見えるかも考えなければなりません。ユーザーは意図的な一時停止とクラッシュを区別できるでしょうか? 何がアプリの動作を妨げているのか分かるでしょうか? 次に向かうべき有用な場所を用意してあるでしょうか?
プロダクトが壊れて見えるとき、技術的に正しいことは大した慰めになりません。
何を変えたのか? 謎の代わりに小さな鍵を
Secure Input が有効なときはいつでも、Comoji のメニューバーアイコンに小さな鍵のインジケーターを表示するようにしました。これで、自動補完が出てこないことに目に見える理由ができました。キーボード入力が保護されているため、Comoji は一時停止中なのです。アプリはもう、使えない機能をさも動くはずであるかのように黙って差し出すことはありません。
また、トレイメニューから Secure Input とは何かを説明するヘルプ記事にリンクを張り、Comoji がなぜそれを尊重するのかも説明しました。行き詰まった人は、正しい検索語を推測したり、このシステム機能の存在を知るために私に連絡したりしなくても、アプリ自体からその説明にたどり着けます。
重要なのは、私が解決しようとしなかったことです。答えは、絵文字の自動補完を動かすためだけにパスワード保護を回避することではありませんでした。Secure Input が有効であること自体はエラーではありません。それには正当な理由があり、Apple も、セキュアキーボード入力を有効にすると他のアプリに影響することがあると明示的に警告しています。それらのキー入力を必要とするアプリのことです。
したがって、この鍵が伝えるのは状態であって、危機ではありません。通常のパスワード入力中は、Comoji が一時的に使えない理由を説明します。その状態が予期せず続くときは、何が起きたのかを理解するための出発点をユーザーに与えます。
私は Chrome や macOS が引っかからないようにしたわけではありません。それらが引っかかったときに、Comoji を使っている人にとって混乱が少なくなるようにしただけで、Comoji が尊重すべき保護を弱めてはいません。
なぜ大企業もなお外部依存なのか?
Google のブラウザと Apple のオペレーティングシステムが絡む問題に備えて、ちっぽけなユーティリティを堅牢化することには、どこか腹立たしさがあります。これらは私が何も考えずにプロジェクトへ引きずり込んだ無名のコンポーネントではありません。二つの巨大テクノロジー企業の製品であり、それでもその振る舞いは、私の小さなアプリを欠陥品のように見せることに成功したのです。
しかし、彼らの規模はエンジニアリング上の判断を変えません。自分より大きな会社が作ったものはすべて常に正しく振る舞う、という前提の上に Comoji を築くことはできません。苛立っているユーザーに、この問題は十分に立派な会社のものですと告げて、自分の仕事は終わったと見なすこともできません。
この特定の一連の出来事がどれくらいの頻度で起こるのかは分かりません。珍しいのかもしれません。しかし私は実際に経験し、その結果は有用な区別を浮かび上がらせました。Comoji はすでにセキュリティ上の条件を安全に扱えていましたが、そこから生じる混乱はまだうまく扱えていなかったのです。
だからといって、あらゆる仮想的な障害に新しい設定や警告ダイアログ、復旧サブシステムが必要だというわけではありません。今回の対応は小さく、問題に直結したものでした。鍵のアイコンが状態を見えるようにしました。ヘルプ記事がそれを理解できるようにしました。どちらも、自分のアプリの内側から他人のアプリケーションを修理できるふりをする必要はありませんでした。
私にとって、これは防御的なソフトウェアを作るうえで重要な部分です。あなたの責任は、周囲のすべてが動いているときにコードが動くことを保証するだけでは終わりません。コードが自分の仕事を果たせないときに何が起こるかも決めなければならず、その理由が他人のミスである場合も含まれます。
正しい振る舞いが「止まること」である場合もあります。良いソフトウェアは、その理由を伝えられるべきです。