ソフトウェア設計

OOPの本質はメッセージング――アラン・ケイが語った本当のOOP

OOPを学ぶと、まず継承・カプセル化・ポリモーフィズムの3語を暗記しがちです。

読了 5 分
OOPの本質はメッセージング――アラン・ケイが語った本当のOOPのカバー画像

OOPの本質はメッセージング――アラン・ケイが語った本当のOOP

OOPを学ぶと、まず継承・カプセル化・ポリモーフィズムの3語を暗記しがちです。

しかし「オブジェクト指向プログラミング」という言葉を作ったアラン・ケイは、その3つを核心とは考えていませんでした。

先に結論を言うと、アラン・ケイが語った本当のOOPの本質は、オブジェクトそのものではなく、オブジェクト間で交わされるメッセージです。クラスをどう分けるかより、オブジェクト同士が何をやり取りするかが先なのです。

最後まで読めば、なぜ彼が「オブジェクト指向という名前を後悔している」とまで言ったのか、そしてその視点がコードをどう変えるのかが見えてきます。


アラン・ケイはなぜ「OOP」という名前を後悔したのか?

アラン・ケイは1970年代、Xerox PARCでSmalltalkを作った人物です。「オブジェクト指向プログラミング」という用語も彼が生み出しました。

2003年、ある開発者からメールで「OOPとは何か」と尋ねられた彼は、こう答えました。

「私は『オブジェクト』という言葉を使ったことを後悔している。

人々の関心を、それほど重要でない概念に向けてしまったからだ。本当に大きなアイデアは『メッセージング』だ。」

初めて読むと少し戸惑いますよね。私たちが学んだOOPは、いつも「オブジェクトをうまく設計する方法」だったからです。

ケイにとって本当に重要なのは、オブジェクトの内部ではありません。オブジェクトがメッセージを交わして生み出す関係と相互作用こそが、システムの本質なのです。

彼はプログラムを生物の細胞にたとえました。細胞はそれぞれ内部を隠し、化学信号、つまりメッセージだけで通信します。インターネットも同じです。無数のコンピューターが独立して動きながら、メッセージだけをやり取りします。


メッセージ中心の考え方は何が違うのか?

「メソッドを呼び出す」と「メッセージを送る」は似ていますが、視点が異なります。

メソッド呼び出しは「このオブジェクトのこの関数を実行して」に近いものです。送信側は受信側の内部をある程度知る必要があります。

一方、メッセージは「これを処理して。方法は任せる」に近いものです。送信側が欲しいのは結果だけで、相手がどう処理するかを知る必要はありません。

例を見てみましょう。会員ランクごとのオブジェクトに、割引計算を「メッセージ」として委譲するコードです。

protocol Member {
    func discountedPrice(for price: Int) -> Int
}

struct Gold: Member {
    func discountedPrice(for price: Int) -> Int { price * 80 / 100 }
}
struct Silver: Member {
    func discountedPrice(for price: Int) -> Int { price * 90 / 100 }
}

// 送信側はランクごとの計算方法をまったく知りません.
let members: [Member] = [Gold(), Silver()]
for m in members {
    print(m.discountedPrice(for: 10000))
}
// 出力: 8000
// 出力: 9000

呼び出し側のコードにはif文もランク名もありません。

「割引価格を計算して」というメッセージを送るだけで、実際の計算は各オブジェクトが担当します。新しいランクが増えても、呼び出し側を変更する必要はありません。

これがケイの語ったメッセージングの力です。目的はオブジェクトを細かく分割することではなく、結合を弱めるコミュニケーション方法が核心なのです。

呼び出し側はランクを知らなくても、メッセージを送るだけで済みます
呼び出し側はランクを知らなくても、メッセージを送るだけで済みます

では、カプセル化とポリモーフィズムは不要なのか?

いいえ。むしろ逆です。

メッセージングを真剣に捉えると、カプセル化とポリモーフィズムは自然についてきます。

オブジェクトがメッセージだけで通信するには、内部状態を隠す必要があります。それがカプセル化です。同じメッセージにオブジェクトごとに異なる反応をすることがポリモーフィズムです。

これらは暗記すべき規則ではなく、メッセージ中心に設計すれば自然に導かれる結果です。

問題は順番です。多くの人は「まずクラスをうまく分けよう」と始めます。するとオブジェクトは増えますが、互いの内部を丸見えにする、名前だけオブジェクト指向のコードになりがちです。

ケイの視点は順番を逆にします。「このオブジェクトはどんなメッセージに応答すべきか?」を先に問うのです。

図を描く前に、この問いを書き出してみました
図を描く前に、この問いを書き出してみました

この視点はいつ使い、いつ力を抜くべきか?

メッセージ中心設計が常に正解とは限りません。状況に応じて使うことが大切です。

状況 判断
要件が頻繁に変わるドメインロジック メッセージ中心の委譲構造が有利
協調するオブジェクトが多い複雑なフロー 結合度の低減に大きな効果
単純なデータ変換・計算スクリプト 無理にオブジェクトで包まず、関数にする
性能が極めて重要な部分 過度な抽象化はかえって負担になる

まとめると、こうです。

  • 協調と変更が多い場所ほど、メッセージという視点が生きます。
  • 単純で固定されたロジックは、力を抜くほうがよいでしょう。
  • 目的は「オブジェクトを分けること」ではなく、「コミュニケーションを設計すること」だと覚えておいてください。

面接ではこう聞かれます

Q. アラン・ケイが語ったOOPの本質は何ですか?

オブジェクトそのものではなく、オブジェクト間で交わされるメッセージです。ケイはオブジェクトを独立して通信する細胞にたとえ、継承やカプセル化よりメッセージングを大きなアイデアと考えました。

Q. メッセージ中心設計には、実務上どんな利点がありますか?

呼び出し側が相手の内部実装を知らなくてもよいため、結合度が下がります。その結果、新しい型を追加しても呼び出し側を直さずに済み、変更に強い構造になります。


OOPを難しく感じたら、クラス図を描く前に「このオブジェクトたちは互いに何を話しているのだろう?」と考えてみてください。

視点を一つ変えるだけで、コードがずっと堅牢になるのを感じられるはずです。今日もよい設計を!

あわせて読みたい