追記: 振り返りを書いてみました~
-- ここから元記事
別題: 抽象化って言葉もう。。
社内の記事にて、オブジェクト指向のこころ (SOFTWARE PATTERNS SERIES) | アラン・シャロウェイ, ジェームズ・R・トロット, 村上 雅章 |本 | 通販 | Amazonを紹介してもらいました。
取り上げられた、共通性/可変性分析の解説を見て、はっと思うことがありポエムを仕立てました。
共通性/可変性分析
共通性/可変性分析については、書籍を読むかググって頂けると良いですが、社内記事が良かったので引用させて頂きます。
- 問題領域にある概念を見つける(共通性の分析)
- その流動的要素を洗い出す(可変性の分析)
- 流動的要素を見ながら、その概念が持つ責務を果たすための抽象的側面(≒インタフェース)を導く
- 各流動的要素の実装上の観点から、インタフェースが適切かどうかを見極め、補正する
オブジェクト指向設計としての模範的な流れですが、分析に利用している "共通性/可変性"って、そういや科学的分析の基本だよねと、はっとしました。分野に乏しい私でさえ、未知の言語を解析したり、社会学の研究とか、データ分析の基礎とかにも使われてるなと気付く程度に。
ようするに "それが何であり/何でないか" を、調べているだけだったりします。共通性/可変性って、そこだったねとなりました。
オブジェクト指向プログラミングの幼年期の終わり
オブジェクト指向プログラミングには、強い目的として再利用性がありました。世間一般に認知されたOOPであるC++の生まれがそういうとこだった気がしますが、語り調べると長いので略。
再利用をどこまで煮詰めても、捗りきらないのが、オブジェクト指向設計(OOD)の歴史でした。技術的には、継承の失敗からインタフェースと委譲を利用するデザパタ、原則論の普遍化などもあり、大きなフィードバックがあったと思います。
ですが、現実の課題解決の世界は、様々に変化することが分かりました。予測不可能さえも受け入れました。こうなると再利用を見抜くことが難しく、見抜くことよりも "適応する" ことが重要になりました。アジャイル開発がずっとも。
再利用性という幼年期がまず終わりました。
オブジェクト指向プログラミングのブレイクスルー
共通性と可変性の話に戻ります。たしかに、共通性と可変性を蒸留すると、再利用性のあるクラスは誕生します。共通性と可変性で得られた概念を定義し、クラスやインタフェースを導出することでポリモーフィズムが可能になり、再利用できるようになります。一言で言うと、抽象化するわけです。
しかしながら、科学分析って、再利用性が目的でしょうか?抽象化が目的でしょうか?未知なる言語から、人類の共通言語を定義したいんだっけ?そのような分野もあると思いますが、応用分野です。あくまで原初的な考えは、未知なる言語が何なのかを知りたい。
純粋に"それが何か"を調べたいのです。そのために共通性や可変性を利用していました。
そして、オブジェクト指向プログラミングも、その考えにたどり着きます。(というか再認知されただけな気も)
「 オブジェクト指向プログラミングだって、"それが何か"知ることが、最も大切で良いんじゃない? 」
ドメイン駆動設計のような、ドメインを中心とした考えに繋がっていくのです。
オブジェクト指向プログラミングの終焉
そして、オブジェクト指向プログラミングは終わります。
"それが何であり何でないか"それこそが重要である。設計的な文脈で言えば高凝集であると言えます。そして、高凝集であれば、インタフェースで 抽象化せずとも変更に強い のです。これはアジャイル開発という歴史的な学習が教えてくれました。
抽象化は、もはや関心毎ではありません。再利用性が必要になったら、ポリモーフィズムを利用すればよい程度のもの。(むしろ、定義時に抽象表現を作らないとポリモーフィズム出来ないクラスベースのオブジェクト指向は不便。。)
抽象化を軸にするオブジェクト指向プログラミングの必要性は薄くなりました、Rust/Goのように、クラスベースOOPの基本文脈が消えて、型と型に紐づくポリモーフィズムの機構のみが残りました。
オブジェクト指向プログラミング後の世界
社内記事の図を拝借。
認証処理をリファクタしたクラス図になります。分析によって「認証プロバイダ」と「認証連携方式」の組み合わせがあると導出されたそうです。抽象化し移譲させることで、再利用性を高めています。一般的なオブジェクト指向設計論として正しい姿です。
ですが、このポエムの文脈で、あえて私がコメントするとこうなるかと思います。
「分析によって、認証プロバイダと認証連携が分かったなら、そこが凝集高いので、そのまま表現してあげれば十分じゃね?」
では、やってみましょう。
凝集の高いオブジェクトがあればいい
凝集が高くて硬い認証プロバイダや認識連携を、それぞれオブジェクトとして切り出します。
Facebook認証プロバイダ / Google認証プロバイダ
OIDC方式認証 / SAML方式認証
パターンも自明化しておくと良いです。列挙で表現するといいかも。
Facebook認証(OIDC) / Facebook認証(SAML) / Google認証(OIDC) / Google認証(SAML)
以上。
あとは、オブジェクト指向プログラミングである必要が無い。
あとは、If文だろうとSwitch文だろうとポリモーフィズムだろうが移譲だろうが関数合成だろうが、なんでも良いのです。プロジェクトのアーキテクチャにそって、これらを組み合わせて認証処理を実現するだけです。個別のオブジェクトは凝集性が高いため、間違いなく変更に適応できます。
追記: コメントに、このあたりの具体例を追記しました(コードで)。興味のある方はご参照頂ければ幸いです。
抽象化のおわり
再利用性は目的じゃないよ。は普及しましたが、正確には 抽象化はもう必須ではない だと感じます。
分析本来の"それは何であり何でないか" は、より重要になりました。ですが、それを示す共通の言葉がありません。 そこで、意味的にはずれていない抽象化を便宜上使っているだけではないでしょうか。OOP原初の再利用性の抽象化とかぶってて、むしろ、あいまいさがそろそろ窮屈に。。
抽象化パラダイムをオミットした言語が登場したのは、その歪みを解決しようとしてるのかもしれません。抽象化を重んじるオブジェクト指向プログラミングの意義は薄れました。オブジェクト指向によって精錬された設計論と分析論は、オブジェクト指向というPrefixを失いながらゆっくりと普遍化するのでしょう。計算機理論のそれに吸収されて、消えてしまう運命かもしれません。ここにたどり着くまでの歴史はせめて。
追記: この辺りの"抽象化"は指す意味も主張もあいまいなため、コメントの議論等も参照頂けると良いかもしれません。注目を頂いたようで恐縮です。 (リンクが飛びずらい、、)
追記2: 振り返り記事 で、改めて考えてみました。
最後に
社内記事のおかげで、OOPの考えがあらためて明確になり、この変化に気付くことが出来ました。ありがとうございました。