Slide 1

Slide 1 text

DI-DIP勉強会 Github: @sor4chi 𝕏 Twitter: @monica18_pr

Slide 2

Slide 2 text

今日の目標 オブジェクト指向の基本を再確認する DIとDIPの概念を理解する 保守性の高いコードを書くための考え方を学ぶ

Slide 3

Slide 3 text

おさらい

Slide 4

Slide 4 text

オブジェクト指向とは class が一般的に使われており、 データ (プロパティ)と 操作 (メソッド)をまとめて提供することができる。 オブジェクト指向とは、プログラムをオブジェクトと呼ばれ る単位で構成し、オブジェクト間の相互作用によってプログ ラムを実現する考え方である。

Slide 5

Slide 5 text

オブジェクト指向の特徴 カプセル化 継承 ポリモーフィズム

Slide 6

Slide 6 text

DIやDIPを理解するために必要な概念とは...?

Slide 7

Slide 7 text

カプセル化

Slide 8

Slide 8 text

内部で保持しているデータに対して、外部から直接アクセスす ることを防ぐことで、データの不整合を防ぎやすい。 カプセル化とは、オブジェクトの内部にデータと操作を隠蔽 し、外部からはオブジェクトのデータに対して操作のみを行 うことができるようにすること。

Slide 9

Slide 9 text

例えば

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

このように、外部から直接アクセスすることを防ぐことがで き、必要のない機能を露出させないことができる。

Slide 12

Slide 12 text

おさらい終わり

Slide 13

Slide 13 text

DIを体験してみる

Slide 14

Slide 14 text

ゲームのプログラムを考えましょう。 Boardがあって、その中にPlayerがいるとします。 これをオブジェクト指向で書いてみましょう。

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

依存関係を集合として表すとこんな感じ Player Board ⊂

Slide 17

Slide 17 text

これだとBoardの中でPlayerを生成しているので、Boardと Playerは密結合(=強い依存関係)になってしまう。

Slide 18

Slide 18 text

じゃあどうすればいいの

Slide 19

Slide 19 text

DI を使えばいいじゃない

Slide 20

Slide 20 text

DIとは DI = Dependency Injection DIとは、依存性の注入と呼ばれ、クラスの外部から依存する オブジェクトを注入することで、クラスの内部で依存するオ ブジェクトを生成することを防ぐこと。

Slide 21

Slide 21 text

つまり クラス内部で他のクラスを生成しない こと

Slide 22

Slide 22 text

DIを使った改善

Slide 23

Slide 23 text

BoardのコンストラクタでPlayerを受け取るようにする

Slide 24

Slide 24 text

すると、さっきと同じBoardをこのように書いて生成すること ができる

Slide 25

Slide 25 text

よく見ると... Board内部でPlayerを生成していないことがわかる 外からPlayerを注入している

Slide 26

Slide 26 text

結局何が嬉しいの?

Slide 27

Slide 27 text

DIをすれば、クラスを他クラスの実体がない(=依存がない)状 態でプログラムできる

Slide 28

Slide 28 text

つまり Mock ができる。

Slide 29

Slide 29 text

Mockとは テストでよく使われる用語で 環境やライブラリなどの外部要因による影響を排除して、単 体の機能をテストすること。

Slide 30

Slide 30 text

例えばDI前のBoardクラスをテストするとき、Playerの実体が 内包されているため、Boardのテストが通る条件として Playerのテストが通る必要がある

Slide 31

Slide 31 text

一方でDI後のBoardクラスをテストするとき、Playerの実体が 外部から注入されるため、 Playerのテストが通らなくても Boardのテストが通る

Slide 32

Slide 32 text

他にも Date クラスをDIすることで、テスト時に固定した日 付を注入することで、テストの結果が変わらないようにするこ とができたり、 Random をDIすることで、テスト時に固定し た乱数を注入することで、テストの結果が変わらないようにす ることができたりする。

Slide 33

Slide 33 text

Web開発におけるDI

Slide 34

Slide 34 text

Web開発ではDIが必須というくらいよく使われているので、そ の例を見ていきましょう。

Slide 35

Slide 35 text

このコードはどこが問題か?

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

予想回答1 クエリが直書きされている

Slide 38

Slide 38 text

定数化しておくことで、クエリの変更に強くなり、再利用の ための共通化もしやすくなる。

Slide 39

Slide 39 text

予想回答2 内部でクラスインスタンスを生成している

Slide 40

Slide 40 text

PostUsecase がDBクライアントを内包している MySQLからPostgreSQLに変更したい場合、DBクライアン トの種類を変更する必要があるかも その度に全てのDBアクセスのコードを書き直さないといけな いので大変

Slide 41

Slide 41 text

つまり DBクライアントに依存 している

Slide 42

Slide 42 text

こんなイメージ

Slide 43

Slide 43 text

DBクライアントをインターフェースを拡張することで渡すよう にしてみる

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

こうすることで、DBクライアントの種類を変更する際に、 PostUsecase のコードを変更する必要がなくなる。 -> ライブラリや環境に依存しないコードになった

Slide 49

Slide 49 text

DIを使うと クラスを抽象化して 外部から注入 することで、クラスの内部で 依存するオブジェクトを生成することを防げる。

Slide 50

Slide 50 text

DI前

Slide 51

Slide 51 text

DI後

Slide 52

Slide 52 text

レイヤーの外側に環境やライブラリが来るので、よりプログラ ムが疎になって綺麗なアーキテクチャになる。

Slide 53

Slide 53 text

この、依存関係を注入する手法のことを**DI(Dependency Injection) と呼ぶのに対して、 それをした結果依存関係が逆転することを DIP(Dependency Inversion Principle)**と呼ぶ。 直訳: 依存関係の逆転の原則

Slide 54

Slide 54 text

https://ja.wikipedia.org/wiki/依存性逆転の原則 上位モジュールはいかなるものも下位モジュールから持ち込 んではならない。双方とも抽象(例としてインターフェー ス)に依存するべきである。

Slide 55

Slide 55 text

今回の例では、 PostUsecase が HogeDBClient に依存し ていたが、それを IDBClient という抽象化されたインター フェースに依存するようにした。

Slide 56

Slide 56 text

おまけ

Slide 57

Slide 57 text

レイヤードアーキテクチャ

Slide 58

Slide 58 text

Layered Architectureは「自分より変更されにくいものに依存 しましょう」という設計手法 より環境やライブラリなどの外的要因に依存するほど「変更さ れやすい」ので、外側に配置するようにする。 外側は変更されやすく、内側は変更されにくい という認識で十 分

Slide 59

Slide 59 text

レイヤードアーキテクチャの例

Slide 60

Slide 60 text

Clean Architecture

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

DBやDevice,Webなどのより外的環境なものほど外側に配置さ れているのがわかる。 対してEntity(=プログラム設計の最小単位)やUsecase(=サー ビスを実装するコード)などは内側に配置されている。

Slide 63

Slide 63 text

ご清聴ありがとうございました 質問などあれば気軽にどうぞ!