メインコンテンツまでスキップ

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 原則それぞれの出自

原典と、そこから辿れる範囲で出自を整理します。

原則誰の考えか出所
SRPRobert C. Martin**上記の 2000 年の文書には無い。**初出の媒体は未確認
OCPBertrand MeyerMartin は "It originated from the work of Bertrand Meyer" と書き、『Object-Oriented Software Construction』を参照します2
LSPBarbara LiskovMartin は "coined by Barbar Liskov" (原文ママ) とし、参考文献で "Data Abstraction and Hierarchy" を挙げます3
ISPRobert C. Martin参考文献のキーは [ISP97]
DIPRobert 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 つの主張のうち、この章で確認した原典に照らして誤っているものを選び、理由を述べてください
  1. SOLID の 5 原則は、Robert C. Martin が 2000 年の文書で 1 つのまとまりとして提示した
  2. OCP は Martin ではなく Bertrand Meyer の仕事に由来する
  3. LSP に違反すると、OCP にも潜在的に違反することになる
  4. 原則同士は互いに独立で、すべて同時に満たすことを目指せる

解答例

誤っているのは 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 原則の間にもトレードオフが生じます。この点は最終章で扱います。


Footnotes

  1. 出典: Robert C. Martin, "Design Principles and Design Patterns" (2000)。原本を公開していた objectmentor.com は消滅しています。本連載は大学が公開している PDF を参照しました。本文に "Copyright (c) 2000 by Robert C. Martin"、各ページのフッタに www.objectmentor.com の記載があります。なおこの文書の参考文献リストは、書誌情報が省略された項目を複数含みます。

  2. 原典 4 ページの OCP の節に "It originated from the work of Bertrand Meyer" とあり、参考文献キー [OOSC98] を参照しています。Meyer の『Object-Oriented Software Construction』は 1988 年に初版、1997 年に第 2 版が出ています。**Martin が参照しているのは、キーの表記から第 2 版と読めます。**ただし参考文献の項目自体が "OOSC..." と省略されているため、版は確定できません。

  3. 原典 8 ページに "This principle was coined by Barbar Liskov in her work regarding data abstraction and type theory" とあります (人名の綴りは原文ママ)。参考文献キー [Liksov88] は "Data Abstraction and Hierarchy" を指します。同じ節に "It also derives from the concept of Design by Contract (DBC) by Bertrand Meyer" という記述もあります。

  4. 出典: SOLID(Wikipedia)。"The SOLID acronym was coined around 2004 by Michael Feathers." と典拠付きで記述されています。**Feathers 本人がこの命名について述べた一次資料は確認できていません。**本連載ではこの帰属を二次情報として扱います。