# Clean Architecture 第II部 第5章 オブジェクト指向プログラミング 読書会#5 ###### tags `book` ## 概要 |項目|内容| |-|-| |開催日|2021/05/02| |開始時間|13:00| |終了時間|16:30| |メンバー|nyx,niro| *** ## オブジェクト指向プログラミング #### 感想・気づき・疑問 ### nothing P59 優れたアーキテクチャの基本となるのは **「オブジェクト指向設計」の原則の理解と適用** である。 - [ ] 凝集度が高くて結合度が低い構造を作れる事がオブジェクト指向のお肝だと考え by 二口さん ```c struct menber{ char[32] name, int age, File** menberFile, *int getBirthDayYear() } ``` オブジェクト指向とは何か?以下3つの答えを提示。 1. 「データと関数の組み合わせ」 著者はこの提示を否定。 >データ構造を関数に渡すことは、1966年にDahlとNygaardが関数呼び出しのスタックフレームをヒープに移動することで「オブジェクト指向」が発明された以前から実行されていた。 >コンウェイの法則 システム設計(アーキテクチャ)は、組織構造を反映させたものになる 設計の話 ->下はモデルの話。 1. 「現実の世界をモデル化する方法」 著者は否定 >ソフトウェアと現実が近くなるので、ソフトウェアのことを理解しやすくなる。 上記を意図した答えであると著者は解釈し、定義が雑で答えを明らかにしていないとしている。 1. カプセル化、継承、ポリモーフィズムの適切な混合物 P60 著者はこの段階ではこの案を否定することも肯定することもしていない。 次のパラグラフで3つの件の詳細に調査していっている。 *** ### カプセル化とは? P60 著者は、 > OO言語がデータと関数のカプセル化を簡単かつ効果的なものしているから カプセル化がOOの定義の一つになっていることの理由としている。:+1: 上記をもう少し細かい概念として以下の表現で説明されている >これらの概念は。「プライベートなデータメンバー」と「クラスのパブリックなメンバー関数」として表現される。 ここで著者はカプセル化の実現は、C言語から存在することを記述し、C++でカプセル化が破られたことを記述している。 また、JavaやC#でヘッダーと実装の分離の廃止が行われたことによりカプセル化は弱体化していることを理由にOOがカプセル化に依存していないことを説明している。これはプログラマが正しく振る舞う運用で解決されているとしている。:+1: ```c struct menber{ char[32] name, int age, File** menberFile, *int getBirthDayYear() } ``` ```c struct menber_column{ char[32] name, char[1] age, char[3] id } FILE* getMenberFile() int main() ``` ```c getMenberFile(){ FILE fi new FILE() FILE* file = fi* } ``` *** ### 継承とは? このパラグラフでは、継承もまた、C言語で実現したことであることを説明している。 ただし、カプセル化のパラグラフで述べているように弱体化しているとは言っておらず、格段に便利になったと表現している。:+1: C言語の時代は構造が同じ場合に同じものとみなすことができることを利用していたがこれを仕組み化することで多重継承も可能になったことを述べている。:+1: ちなみにJavaでは言語使用として多重継承が許されていない。(Interfaceで一部実現している) 以下、ちょっと気になったのでググりました。[なぜJavaでは多重継承できないの?](https://zenn.dev/yohhoy/articles/java-multiple-inheritance) 多重継承の分類 - 状態(state)の多重継承:言語仕様上の選択としてサポートしない - 実装(implementation)の多重継承:Java8で導入された デフォルトメソッド(default method) でサポート - 型(type)の多重継承:インターフェイス(interface)継承でサポート 著者は、もう一つ、継承についてもC言語で実現できたことを理由にOOが優位な特徴であるとは言っていない。 適合コード ```java interface CaseA{ default boolean isValid(){ return true; } } class Support implements CaseA{ } class main{ public static void main(String[] args){ var support = new Support(); System.out.println(support.isValid()); // result=true } } ``` コンパイルエラー(ダイアモンド継承) ```java interface CaseA{ default boolean isValid(){ return true; } } interface CaseB{ default boolean isValid(){ return false; } } class Support implements CaseA , CaseB{ } class main{ public static void main(String[] args){ var support = new Support(); System.out.println(support.isValid()); // result=true } } ``` コンパイルエラー ```java interface CaseA{ default boolean isValid(){ return true; } } interface CaseB extends CaseC{ } interface CaseC{ default boolean isValid(){ return false; } } class Support implements CaseA extends CaseB{ } class main{ public static void main(String[] args){ var support = new Support(); System.out.println(support.isValid()); // result=true } } ``` ```c // a file struct menber_column{ char[32] name, char[1] age, char[3] id } ``` ```c // a alter file struct menber_column{ char[32] name, char[1] age, char[3] id char[5] parentId } ``` ```c // b file include a struct menber_column_extended{ char[32] name, char[1] age, char[3] id, char[3] petId } ``` *** ### ポリモーフィズムとは? **ポリモーフィズムに関してもまたC言語または、Unix時代から存在していた概念であることが記述されている。** これは同等のシグネチャを持つ関数のポインタを交換することで実現できることが記述されている。 >1940年代後半にノイマン型アーキテクチャが実装されて以来、プログラマはポリモーフィズムの振る舞いを実現するために、関数へのポインタを使用してきた。 つまり、**OOは新しいものを提供しているわけではないのである。** 著者はポリモーフィズムについての補足を下記のように綴っている。 >**OO言語がポリモーフィズムをしてくれたわけではないが安全かつ便利にしていくれたのはOO言語だ。** と記述している。 ポインタを初期化するとき「ポインタを経由して関数を呼び出す」という規約を覚えていないと、バグの追跡と掃除が相当難しくなると記述している。 ↑ここでなぜポイント初期化時にポインタを経由して関数を呼び出さないといけないのかがわからなかった。 >OO言語はこうした暗黙的規約を排除することで関数へのポインタの危険性を回避している。OO言語を使えば簡単にポリモーフィズムを使えるようになる。 >**OO言語は間接的な制御の移行に規律を課すものである** a.k.a->データと関数の組み合わせを持つ集合に対して間接的に制御を行う仕組みを提供したもの。 と結んでいる。 ポリモーフィズムを型システムの中の一部と捉えて圏論の枠組みで説明を試みている文書のリンク https://bitterharvest.hatenablog.com/entry/2017/06/07/210510 https://m-hiyama.hatenablog.com/entry/2020/09/10/121121 *** ### ポリモーフィズムのパワー UNIXにおいて、プログラムを**デバイス非依存**にするために、プラグインアーキテクチャが考案された。 しかし、ほとんどのプログラマは、**関数ポインタを扱うには危険性を孕むためプラグインアーキテクチャを採用しなかった。** プラグインアーキテクチャをどこでも何にでも使うことができることがポリモーフィズムのパワー *** ### 依存関係逆転 **ソースコードの依存関係は(たとえどこにあっても)逆転できる** 各コンポーネントを独立してデプロイすることができる独立可能開発性があることが重要なこと。 #### 感想 インターフェースを挿入する事で、疎結合にできるのがうまみ 常にInterfaceに依存させることができる。 上のルールを下が定義できる(?) interfaceで定義すると制御側のコードを制限できる(?) interfaceがあれば実装を完成させることができる。 暗黙的なレイヤー間のIFが明示的にinterfaceとして定義できるようになることによって レイヤーの分離をコードレベルで実現できるようになった。 これによって、開発をレイヤーで分離しても整合性を保つことが容易になった。 *** ### まとめ 著者はOO(オブジェクト指向)とは何かを以下のようにまとめている。 >「ポリモーフィズムを使用することで、システムにあるすべてのソースコードの依存関係を絶対的に制御する能力」である。 これによりアーキテクトは「プラグインアーキテクチャ」を作成できる。 これは、**上位レベルの方針を含んだモジュールを下位レベルの詳細を含んだモジュールから独立させることである。下位レベルの詳細はプラグインモジュールとなり、上位レベルの方針を含んだモジュールとは独立して、デプロイおよび開発することが可能となる。** 作者は、オブジェクト指向は、独立開発可能性と独立デプロイ可能性があることのことであり、 そのためには、ポリモーフィズムという機能を実現することが条件であると言っている。 優れたアーキテクチャの基本だと言っている。 OOとは、モジュール分割を行った開発を行ってデプロイを小さい単位で行うことができる状態にすることでも健全性を保つことができる仕組みを実現可能な形にし易くすることができたことが利点であるといえるのかなと思いました。 >プログラムで実現できる暗黙的な仕組みを明示的な構文として表現できるようにしたプログラミング言語をオブジェクト指向言語 #### 僕たちの一旦の結論 モジュール間(ある種類のデータと関数の集合)の境界(関数のシグネチャ)を明示的に定義し、モジュール実装部の分割または多態性またはその両方を表現されたコードをオブジェクト指向という。それは結果的に独立開発可能性と独立デプロイ可能性を高める。 P.50で端的に要約している > オブジェクト指向プログラミングは、間接的な制御の移行に規律を課すものである *** ## ふりかえり ### YWT #### Y: やったこと - 「第5章 オブジェクト指向プログラミング」の読了 #### W: わかったこと - オブジェクト指向として象徴的な機能であるカプセル化・継承・ポリモーフィズムは実は新しいものではなくて、C言語で既に実装可能なものである - オブジェクト指向は、暗黙的な規約を構文として表現することの大切さを教えてくれたのではないかと思っている。 - 具体的には、暗黙的なレイヤー間のIFが明示的にinterfaceとして定義できるようになることによって レイヤーの分離をコードレベルで実現できるようになった。 これによって、開発をレイヤーで分離しても整合性を保つことが容易になった。 - ただ、言語によっては、カプセル化を構文として提供していないなどの問題は存在しているため、C言語の優位性があると主張されることもあることが分かった。 - 構文としてサポートすることはその言語(Java)の課題であると考える。 - それ以上に明示的にモジュールの境界を定義して多態性を安全に整合性のある形で表現できることを容易にできるような系譜を感じることができてよかったです。 - また自分たちの結論も出せてよかった >モジュール間(ある種類のデータと関数の集合)の境界(関数のシグネチャ)を明示的に定義し、モジュール実装部の分割または多態性またはその両方を表現されたコードをオブジェクト指向という。それは結果的に独立開発可能性と独立デプロイ可能性を高める。 P.50で端的に要約している > オブジェクト指向プログラミングは、間接的な制御の移行に規律を課すものである #### T: 次にやること - 第6章 関数型プログラミング *** ### KPT #### Keep - 事前に書いておくことは時短になり有効 - 事前準備パライムの導入 - 進行の秩序が生まれた。 - 分からないことは分からないので、文章から読み取れることの範囲で十分わかることを分かっていく姿勢 #### Probrem - アーキテクチャの**境界**などの概念を現状放置している状態。 - プログラムをダイクストラにはなぜか証明できなかったのか? - クラス、モジュール、コンポーネントあらゆるレベルで構造化プログラミングの制限しているがその制限のルールはどのようなものか? #### Try - 疑問点のリスト化をしてすぐにアクセスして解消できるような仕組み - KPTを次に持ち越すことで一旦対応 *** ### Fun-Done-Leanrn #### Fun: - a #### Done: - a #### Learn: - a 速度 満足度 進め方