概要
- Protocol Buffers(protobuffers) の設計と実装に対する批判的な考察
- 型システムの欠陥 や 合成性のなさ といった構造的問題の指摘
- 後方互換性・前方互換性 の主張に対する反論
- Googleの内部実装 における課題の具体例
- より良い設計案 の提案と現状の問題点のまとめ
Protocol Buffers(protobuffers)批判
- protobuffers は アマチュア的 で アドホック な設計による問題の温床
- Google内部 でも同じ問題が発生
- 型システムの貧弱さ が最大の課題
- Javaの型システムに似ており、静的型付け・動的型付けの両者から不満
- 多くの仕様が 後付け で追加されており、 一貫性・合成性 に欠ける
- 既知の問題 に対して、 既に解決されている設計原則 を無視した対応
合成性の欠如
- oneof フィールドは 繰り返し不可 という制約
- map<k,v> の専用構文は他の型では使えない
- ユーザー定義型 のパラメータ化ができず、汎用データ構造の再実装が必要
- map のキーに使える型が限定的(stringのみ、enum不可)
- map の値に他のmapを使えない
- これらは 設計上の一貫性のなさ と 後付け仕様 の弊害
改善案の提案
- すべてのフィールドを 必須 にし、 積型 として扱う
- oneof を 独立した型(余積型) として昇格
- 積型・余積型 を型パラメータで拡張可能に
- これにより 任意のデータ構造 をシンプルに表現可能
スカラー型とメッセージ型の問題
- スカラー型 は常に値が存在し、 未設定とデフォルト値の区別が不可能
- メッセージ型 は内部的に有無の状態を持つが、アクセス方法が複雑
- フィールド未設定時にデフォルト初期化が返される仕様
- msg.foo = msg.foo; という代入が副作用を持ち、 直感に反する動作
- has_foo() のようなメソッドで有無を判定する必要
- これらの仕様により 抽象化・汎用化が困難
oneofフィールドの実装上の問題
- oneof は本来 余積型 となるべきだが、実態は 排他的なオプション集合
- セッターが他のフィールドを自動的にunsetするため、 予期しないデータ消失 の原因
- 法則に則ったPrismやLens としての利用が不可能
- 型安全・ポリモーフィックな操作 が実質的に不可能
後方互換性・前方互換性の幻想
- protobuffersは データの意味的な保証をしない ことで互換性を主張
- すべてがオプション扱いとなり、 不正なデータも型検査を通過
- 防御的コーディング が全コードベースに拡散し、 集中管理が困難
- 未知フィールドの保持 も現実的なアプリケーションではほぼ活用されない
- DRY原則 を否定し、定義のインライン化を推奨
- 将来的な分岐のために 再利用性・保守性を犠牲
より良い設計への示唆
- 現代的な型システム の理解と適用があれば、仕様の大幅な簡素化と制約の撤廃が可能
- 必須フィールド・積型・余積型・型パラメータ の導入による柔軟なデータ表現
- 抽象化・型安全性・再利用性 を重視した設計の重要性
最初の一行も終わらないうちに「明らかに素人が書いたものだ」とか言ってる。これ、ただの怒りを煽るためのもので、読む価値ないよ。