システム設計における2つの抽象化:隠蔽か削減か
The Two Abstractions of System Design: Hide or Reduce (muratbuffalo.blogspot.com)
要約
この記事では、システム設計における抽象化には「モジュラリティ抽象化(隠蔽)」と「モデリング抽象化(削減)」の2種類があると論じています。前者はカプセル化と境界線設定に焦点を当て、内部を隠蔽するのに対し、後者は数学や物理学のように、関心のある特性を保つために本質的な部分だけを残し、システムを最小限の骨子にまで削減することを目指します。この違いを理解することが、特にモデリングの分野で重要であると述べています。
全文翻訳
TLA+について話すとき、私は常に「抽象化」を「学ぶべき最も重要なこと」として参照しています。
そして、それは「学ぶのが最も難しいこと」でもあります。
しかし、矛盾が私を悩ませています。CS(コンピュータサイエンス)の学生は、すでに抽象化が得意であるはずではありませんか? 抽象化は、OS、ネットワーキング、ソフトウェアエンジニアリングの根幹をなすものではないのでしょうか? 抽象データ型(ADT)は、すべてのCSカリキュラムの定番です。では、なぜ私(そして他のすべての形式手法/モデリング担当者)は、抽象化における大きなスキルギャップを見て、それをモデリングにおける核心的な、成功を左右するスキルと見なすのでしょうか?
この認識の不協和音の根本原因が、ようやく分かった気がします。同じ「抽象化」という言葉の下に、2つの種類の「抽象化」が混同されているのです。
- モジュール化抽象化(Modularity abstraction):これは、ADT、API、レイヤードデザインなどでCSカリキュラムで教えられる伝統的な抽象化です。カプセル化、境界線の設定、内部の隠蔽がすべてこれにあたります。
- モデリング抽象化(Modeling abstraction):これは、私がモデリングの文脈で抽象化について話すときに言及するものです。これは、数学者や物理学者が思考や推論のためのモデルを構築する際に用いる抽象化と同じ意味合いです。目標は、関心のある特性を保持する最小限で最もエレガントな記述を見つけることです。それは、その特性の本質に直交するすべてを切り捨てることなのです。
これら2つは、その目標においてこれ以上ないほど異なっています! 次の2つのセクションで説明を試みましょう。
モジュール化抽象化は隠蔽し、モデリング抽象化は削減する。
モジュール化抽象化は、内部を隠蔽するインターフェースに関するものです。モデリング抽象化は、振る舞いに関するものであり、関心のある特性のためにシステムを最小限の振る舞いの骨格に削減することに関するものです。
モジュール化抽象化はカプセル化し、垂直な境界を引き、下のレイヤーを隠蔽します。モデリング抽象化は横断的です。システムの振る舞いの平面に沿ってスライスし、調査中の特性に絶対に関連するものだけを保持します。そして、それは「どのように」ではなく「何を」という形で保持します。このスライスは、通常、システムの組織とは似ても似つかないものになります。
モジュール化抽象化は並行性を隠蔽し、モデリング抽象化はそれを露呈させる。
モジュール化抽象化は、リークを封じることを目的としています。そのため、Joel Spolsky の有名な投稿「すべての抽象化はリークする」があります。
[彼のリストはすべてモジュール化抽象化に関するものです:TCP(IPを隠蔽)、文字列ライブラリ(文字配列を隠蔽)、ファイルシステム(回転ディスクを隠蔽)、仮想メモリ/フラットアドレス空間(MMUとページングを隠蔽)、SQL(クエリプランを隠蔽)、NFS/SMB(ネットワークを隠蔽)、C++文字列クラス(char*を隠蔽)。] モジュール化抽象化は、インターリーブを隠蔽し、操作をアトミックであるかのように提示することを目指します。その目標は、モジュールを使いやすくすることですが、その過程で並行性や効率の機会を露呈することを諦めてしまいます。
対照的に、モデリング抽象化は、何がリークすべきかを特定し、それを活用することに関するものです! それは、細かい粒度の操作と順序を露呈し、インターリーブにもかかわらず不変条件が成り立つことを証明します。この作業の報酬は、システムから最大限の安全な並行性を引き出すことです。
モデリング抽象化の例
分散システム分野には、モデリング抽象化が豊富にあります。ほとんどすべてのプロトコルがこのように設計されているように感じます。
- ラムポートの論理時計:ウォールクロック時間を捨て、happens-before(先行関係)を保持する
- ハイブリッド論理時計:ウォールクロックと因果関係を保持し、残りを捨てる
- TrueTime:不確実性の区間で区切られた時間として扱う
- コンセンサス:単一の決定に合意する。ラムポートがPaxosを設計した方法は、抽象化の傑作です。コンセンサス、投票から最終的なプロトコルまで。
- 線形化可能性(そして実際にはすべての整合性モデル):レプリケーション、キャッシング、リトライを捨てる
- データベースとしてのログという考え方:マテリアライズされた状態を真実の源として捨てる。順序付けられた、追記のみのイベントシーケンスのみを保持する。
- MapReduce/Spark:オーケストレーション、並列処理、スケジューリング、耐障害性を捨てる。パーティション化されたデータに対する決定論的な変換のDAGを保持し、フレームワークに残りをその骨格から再構築させる。
時には、2つの定義が重複しているように見えるかもしれません(例:線形化可能性、コンセンサス、データベースとしてのログ、Map-Reduce)。しかし、これは重複というより再利用です。本当にうまく設計された成果物は、洗練するための仕様(モジュール化)と、推論するための骨格(モデリング)の両方として機能することができます。これは単に、2つが1つの成果物で一致したことを意味しますが、抽象化の役割は依然として区別されたままです。