-
Hyrum の法則と Golang
- 最近 Gocodebase を調べている中で、興味深いコメントを見つけた
- 「Hyrum の法則のため、このテキストは変更できない」というコメントがあるコード例
MaxBytesError 構造体の Error() メソッドは "http: request body too large" というエラーメッセージを返す
-
Hyrum の法則
- Google のソフトウェアエンジニア Hyrum Wright の名前にちなんだ原則
- 多くのユーザーが API を利用している場合、システムの観測可能なあらゆる動作は誰かに依存されるようになるという内容
- コードにおける観測可能な動作は、意図的であれ偶然であれ、最終的には誰かに依存される
- エラーメッセージを変更すると既存のコードが壊れうる理由を説明
-
Golang での事例
crypto/rsa と internal/weak パッケージでも Hyrum の法則に言及するコメントを発見
crypto/rsa/rsa.go と crypto/rsa/pss.go にあるコメントの例
internal/weak パッケージにあるコメントの例
-
観察
- Golang に限った話ではない
- JavaScript の進化の過程でも同様の現象を観察できる
- このような現象は Hyrum の法則 と呼ばれる
-
最後の考え
- 他の人が依存している可能性のあるコードを変更する際には注意が必要だと改めて認識させられる
- 意図しない動作に依存されないようシステムを設計することが重要
- 小さな変化が大きな影響を与える可能性があることを忘れてはならない
1件のコメント
Hacker Newsのコメント
Hyrum's Lawは有用な観察だが、誤った結論を導かないよう注意が必要だ。関数の総実行時間も観測可能な特性であるため、関数を最適化して高速化することは99.99999999%のユーザーにとって良いことかもしれないが、破壊的変更になり得る。したがって、「破壊的変更」は技術的な契約ではなく社会的な契約であることを理解すべきだ。ライブラリ作者はAPIのどの部分が変わらないのかを文書化し、ユーザーに共感すべきだ。ライブラリ利用者は、文書化されていないインターフェースを使うことにはリスクがあると理解し、作者に共感すべきだ
Go言語ではHyrum's Lawと下位互換性を非常に重視している。たとえば、GenerateKey関数ではMaybeReadByteを使ってアルゴリズムが固定化されないようにしている。ECDSAキーの問題を解決しようと取り組んでいる。マップの反復順序は内部を露出しないようランダム化されている。rand.Randの出力は互換性保証の一部と見なされており、改善のために多くの努力が払われている。ドキュメントで何を約束し、どの挙動を否定するかについて常に議論している
特定の問題への解決策として、文字列ベースのエラーではなくセンチネルエラーを使うことが推奨される。API利用者が非技術的な文字列に依存しないよう、事前定義されたエラー値、型、または定数を使うべきだ。Hyrum's Lawは存在するが、その影響は緩和できる
Hyrum's Lawに対抗する方法の1つはランダム性を追加することだ。QUICプロトコルでは未使用フィールドをランダムな値に設定し、ルーターがそれに依存してパケットを識別しないようにしている。これは「greasing」と呼ばれ、「ossification」を防ぐ
Golangの設計者は例外を望まなかったが、非形式的なエラーには問題がある。パターンマッチングなしで型付きエラーを扱う方法について議論が必要だ
ある職場でエラーメッセージのタイプミスを見つけて修正したが、そのタイプミスに依存する依存関係があまりに深く、修正できず元に戻さざるを得なかった経験がある
Goのエラーは列挙型にできたはずだが、文字列を型として使ったため、利用者がどのように依存するか分からない。これはより良い代替案があるにもかかわらず残っている古い設計判断だ
Hyrum's LawはRobustness Principle/Postel's Lawと正反対だ。受け入れるものに寛容であるなら、その方法を理解し文書化しなければならない。APIが受け入れるものに対して寛容すぎないよう設計しようとしている
Hyrum's Lawはテストで頻繁に現れる。保証されていない挙動に関する仮定のせいで、さまざまな種類のテストが壊れる。たとえば、Hashmapの要素順序の変更、エラーメッセージの変更、うるう年の扱いの変更などがある
一部のパッケージ作者はHyrum's Lawをより受け入れているかもしれない。
jsonパッケージのコメントでは、内部詳細であるにもかかわらず広く使われるパッケージがlinkname経由でそれにアクセスしていることが分かった