SOLID は 1 つの理論ではない — 5 原則の出自
SOLID という語は、5 つの原則が 1 つの理論として設計されたかのような印象を与えます。実際にはそうではありません。出自を追うと、提唱者も年代も動機もばらばらで、束ねられたのは後からです。
この章では原典にあたって、5 つがどこから来たのかを確認します。それは歴史の趣味ではありません。5 つを同格の一枚岩として扱うと、原則同士が衝突する場面で判断できなくなるからです。
原典に 5 原則は載っていない
出発点とされるのは、Robert C. Martin が 2000 年に公開した「Design Principles and Design Patterns」です1。SOLID の名前が付く前の文書で、オブジェクト指向設計の原則を一覧にしています。
この文書が挙げる原則を、実際の並び順で書き出します。
クラス設計の原則 (原文の節名は "Principles of Object Oriented Class Design")
| 略称 | 原文の定義 |
|---|---|
| OCP | "A module should be open for extension but closed for modification." |
| LSP | "Subclasses should be substitutable for their base classes." |
| DIP | "Depend upon Abstractions. Do not depend upon concretions." |
| ISP | "Many client specific interfaces are better than one general purpose interface" |
パッケージ設計の原則 (同 "Principles of Package Architecture")
凝集に関する 3 つ (REP / CCP / CRP) と、結合に関する 3 つ (ADP / SDP / SAP) が続きます。たとえば CCP は "Classes that change together, belong together." です。
ここで気づくことが 2 つあります。
1 つめ。SRP がありません。 単一責任の原則は、この文書の本文にも、巻末の参考文献にも登場しません。参考文献に並ぶ Martin 自身の記事は [OCP97] [LSP97] [DIP97] [ISP97] に [Granularity97] [Stability97] (パッケージ設計の 6 原則の出典) を加えた 6 本で、SRP に対応するものがありません。
2 つめ。クラスの原則とパッケージの原則が同格で並んでいます。 現在 SOLID として語られる 4 つと、パッケージの 6 つは、この文書では対等な扱いです。片方だけを取り出して 5 点セットにする、という発想はまだありません。
つまり 2000 年の時点では「SOLID の 5 原則」という括りが存在しませんでした。 存在したのは、10 個の原則が並んだ一覧です。
5 原則それぞれの出自
原典と、そこから辿れる範囲で出自を整理します。
| 原則 | 誰の考えか | 出所 |
|---|---|---|
| SRP | Robert C. Martin | **上記の 2000 年の文書には無い。**初出の媒体は未確認 |
| OCP | Bertrand Meyer | Martin は "It originated from the work of Bertrand Meyer" と書き、『Object-Oriented Software Construction』を参照します2 |
| LSP | Barbara Liskov | Martin は "coined by Barbar Liskov" (原文ママ) とし、参考文献で "Data Abstraction and Hierarchy" を挙げます3 |
| ISP | Robert C. Martin | 参考文献のキーは [ISP97] |
| DIP | Robert C. Martin | 参考文献のキーは [DIP97] |
Martin が自分の記事に付けた参考文献キーは 6 本とも 97 です。これらが雑誌 C++ Report に載った連載だという記述は解説記事に見られますが、原典の参考文献は書誌情報が省略されており (「...」で終わっている項目が並びます)、発表年月を原典から確定できません。本連載では「1990 年代後半の Martin 自身の記事」という粒度で扱います。
出自の分布を見ると、5 つのうち 2 つは Martin 以外の人の仕事です。OCP は Meyer が別の目的で書いたもので、LSP はプログラミング言語の型理論から来ています。残る 3 つは Martin のものですが、そのうち SRP だけは原典の一覧に含まれていません。
「SOLID」という名前が付いたのは後
頭字語 SOLID を作ったのは Martin ではなく Michael Feathers で、2004 年頃とされます。ただしこれは二次情報です — Wikipedia が典拠付きで記述していますが、Feathers 本人が命名を述べた一次資料には到達できませんでした4。
名前が付いた順序は次のようになります。原則が個別に提唱される (1980 年代後半から 1990 年代) → 一覧にまとめられる (2000 年) → 5 つを選んで頭字語にする (2004 年頃)。
頭字語が隠したもの
頭字語は覚えやすさと引き換えに、いくつかの情報を落としました。
選ばれなかった原則が見えなくなりました。 パッケージ設計の 6 原則は、原典では同格でした。今それらを諳んじられる人は多くありません。5 文字に収まらなかったからです。
抽象度の違いが平らになりました。 5 つは同じ粒度の規則ではありません。LSP は型階層が満たすべき性質で、破れば型が嘘をつきます。SRP はモジュールの切り分け方の指針で、守るかどうかに幅があります。DIP は依存の向きの話で、単位はモジュール間です。同じ「原則」という語で呼ばれていますが、違反したときに起きることの深刻さが違います。
原則同士が衝突することが見えなくなりました。 これは頭字語の副作用のうち、実務でいちばん効いてくるものです。しかも原典は衝突を明記しています。パッケージの凝集に関する 3 原則について、Martin はこう書いています。
These three principles are mutually exclusive. They cannot simultaneously be satisfied. (この 3 つの原則は互いに排他的である。同時に満たすことはできない。)
原則が互いに排他だと原典が言っているのに、頭字語はそれを「5 つ全部守るべきもののリスト」に見せます。頭字語に選ばれた 5 つも同じで、SRP の方向に分割を進めると 1 つの変更で触るファイルが増え、OCP のために拡張点を先に用意すると使われない抽象が残ります。ただし原典がここまで明記しているのはパッケージの 3 原則についてで、クラス側の衝突は実務で観察されるものです。どちらを取るかは、原則の一覧を眺めても決まりません。
原則間の関係についても原典に記述があります。LSP 違反の節の末尾で、Martin は次のように書いています。
Thus, violations of LSP are latent violations of OCP. (したがって LSP 違反は、潜在的な OCP 違反である。)
5 つは並列ではなく、依存関係を持っています。この関係は最終章で改めて扱います。
この連載の読み方
以上を踏まえて、本連載は 5 原則を次の順で扱います。原典の並び (OCP / LSP / DIP / ISP) ではなく、頭字語の並び (SRP / OCP / LSP / ISP / DIP) を採ります。読者が既に知っている順序に合わせるためで、原典の構成を追認するものではありません。
各章の構成は共通です。
- 原典は何を言ったか — 提唱者が実際に書いたことを、二次情報を経由せずに確認します
- なぜ守るのか — その原則が下げようとしているコストを特定します
- どう誤用されるか — 守りすぎたときに何が起きるかを扱います
- いつ破っていいのか — 適用しない判断が妥当になる条件を書きます
- TypeScript での現在地 — 言語の型システムが前提を変える箇所を扱います
原典が確認できなかった主張には、その旨を本文に書きます。この章でいえば、SRP の初出媒体と頭字語の命名者がそれにあたります。
まとめ
- 2000 年の原典が挙げるのはクラス設計の 4 原則とパッケージ設計の 6 原則で、SRP は本文に登場せず参考文献にも無い
- 5 つのうち OCP は Meyer、LSP は Liskov の仕事で、Martin 以外の人が別の文脈で提唱した
- 頭字語 SOLID を作ったのは Michael Feathers とされ、2004 年頃 (二次情報)
- 頭字語は、選ばれなかった原則・抽象度の違い・原則同士の衝突を見えなくした
- 原典自身が、パッケージ凝集の 3 原則 (REP / CCP / CRP) について「互いに排他で同時には満たせない」と書いている
次に読む
次章では単一責任の原則を扱います。原典の一覧に無かったこの原則が、後にどう定義され、その「理由」が何を指すのかを提唱者自身がどう明示したのかを見ていきます。
練習問題
次の 4 つの主張のうち、この章で確認した原典に照らして誤っているものを選び、理由を述べてください
- SOLID の 5 原則は、Robert C. Martin が 2000 年の文書で 1 つのまとまりとして提示した
- OCP は Martin ではなく Bertrand Meyer の仕事に由来する
- LSP に違反すると、OCP にも潜在的に違反することになる
- 原則同士は互いに独立で、すべて同時に満たすことを目指せる
解答例
誤っているのは 1 と 4 です。
1 が誤りである理由: 2000 年の文書が挙げるクラス設計の原則は OCP / LSP / DIP / ISP の 4 つで、SRP は本文に登場せず参考文献にもありません。またパッケージ設計の 6 原則が同格で並んでおり、「5 つのまとまり」という括り自体がこの時点では存在しません。5 つを選んで頭字語にしたのは 2004 年頃の Michael Feathers とされます (二次情報)。
4 が誤りである理由: 原典はパッケージの凝集に関する 3 原則について "These three principles are mutually exclusive. They cannot simultaneously be satisfied." と明記しています。原則は互いに排他でありうる、というのが原典の立場です。
2 と 3 は原典の記述どおりです。2 は "It originated from the work of Bertrand Meyer"、3 は "violations of LSP are latent violations of OCP" に対応します。
なお 4 について補足すると、原典が排他だと述べているのはパッケージ設計の 3 原則についてです。頭字語の 5 原則が同じ意味で排他だとは書かれていません。ただし実務では 5 原則の間にもトレードオフが生じます。この点は最終章で扱います。