nikkie-ftnextの日記

イベントレポートや読書メモを発信

読書ログ | #ちょうぜつ本 第7章 〜依存性注入で作ると使うを分ける💉 作るはDIコンテナに任せてオートワイヤリング!〜

はじめに

変更しやすいコードが書けないのにソフトウェア開発とか舐めているのですか
天使様1ごめんなさい〜、nikkieです

「かわいい」と技術書が夢の合体を果たした、ちょうぜつ本(『ちょうぜつソフトウェア設計入門』)!🤗
先日(10/20)第7章「依存性注入」の読書会をしました。
会の後にはなりますが、予習した分を読書ログに綴ります。

目次

前回のちょうぜつ本!

いわしまんさんの書評エントリがきっかけで、手に取りました。
第6章まで読み進め、SOLID原則を完全に理解し、設計手法としてのテスト駆動開発で変更しやすいコードを書いていけそう!(天使様にこれ以上刺されないぞ🛡)

今回は第7章です。

nikkieと依存性注入

依存性注入(dependency injection=DI)という概念との出会いはAngularです。
Pythonと出会った頃は色々な言語やフレームワークのハンズオンに参加していて、AngularのハンズオンでDIと出会いました。

ただDIという概念は全く自分のものにできずに、今回のちょうぜつ本に至ります。
ちょうぜつ本 第7章で、待望の完全に理解した感があります🙌

依存性注入、完全に理解した!

作ると使うを分ける

鍵となる考え方は、作ると使うを分けるだと思います。
ちょうぜつ本には「使用と生成の分離」(7-1。Kindle版 p.293)という言い回しもあります。

思えば、作りもするし同時にそれを使いもする関数やメソッドを書いてきました。
これはめちゃくちゃ変更しづらいんですよ!(経験からの主張)

作ると使うが分かれていないと、まず大きいです😫。
それゆえにテストも書きづらいです(長くなります😫)。
これまで書いていたコードの変更のしづらさ(言い換えたらあるべき)が言語化された感覚です。

作ると使うを分けるとは、使う側は完成品(作られたもの)を与えてもらう前提とすることです。
使う側に必要な依存が外から与えられる=注入、というわけですね。
例のFizzBuzzアプリケーションでは、依存が外から与えられているのでコードがとてもスッキリします。

FizzBuzzアプリケーション:FizzBuzzSequencePrinter

  • 2つの依存
    • FizzBuzzロジック:NumberConverter(6章まででできている)
    • 出力処理:OutputInterface
      • 実装したConsoleOutputを用意
  • 利用者はprint_rangeメソッドを呼び出すだけ
    def print_range(self, begin: int, end: int) -> None:
        for i in range(begin, end + 1):
            text = self.fizzbuzz.convert(i)
            formatted_text = f"{i} {text}\n"
            self.output.write(formatted_text)

self.fizzbuzzself.outputは完成品が注入されているので、それを使うだけ
作るを一切気にしなくていいので、このメソッドは小さくていい感じです。

DIコンテナとオートワイヤリング

ちょうぜつ本は最初Factoryクラス(FizzBuzzAppFactory)から始めて、DIコンテナへと移行します。

Factoryクラスは依存のうち1つだけを生成するメソッド(create_xxx)たちを入れ子に呼び出していく実装です(依存の作り方は数珠つなぎ)。

  • FizzBuzzAppFactoryFizzBuzzSequencePrintercreate_fizzbuzzcreate_outputの返り値から作る
  • create_fizzbuzzではNumberConvertercreate_fizz_rulecreate_buzz_rulecreate_pass_through_ruleの返り値から作る
  • ...

この作り方をDIコンテナというフレームワークに任せます。
DIコンテナ(PHPSymfonyのServiceContainer2)は、最初は設定ファイルに作り方を書きます。
その後DIコンテナのオートワイヤリングを使って、設定ファイルから自明なオブジェクト生成を省略します。
作り方をDIコンテナに任せる + オートワイヤリングで、"作る"を担う設定ファイルは非常にスッキリし、さらに実装は"使う"(print_range)だけに集中できます。

7-2のイラストがめちゃめちゃうまくて、国旗などが繋がって出てくる手品の箱=DIコンテナのたとえなんですよ!

つながって出てくる不思議な箱でーす

数珠つなぎ!

DIコンテナのコンテナは、容器や入れ物の意味と理解しています。
箱というたとえとも一致しますよね。
あとそけっとさんかわいい

PythonでのDIはどんなコードになる?

FizzBuzzAppFactoryまではPythonでの写経例が以下にあります。

injectorというライブラリを素振りした記事を先行して書いています。

いままで使ったことのない頭を使いましたね(もっと上達したい!)

終わりに

ちょうぜつ本 第7章で依存性注入を完全に理解しました。
作ると使うを分けるという考え方、これを徹底すると同時にDIコンテナを導入することで、これまでの私のプログラミングとは全然別世界が開けた感覚です🙌
作ると使うを分けることで使うだけのコードを書けばよくなりますし、作るはDIコンテナという"魔法の箱"が支えてくれます

現状はDIにいいことしかなさそうと思ってしまっているのですが、(銀の弾丸などないこの世界では)うまい話すぎる気もするのですよね。
素振りを重ねて使い所を見定められるようになりたいと思ってます。


  1. ちょうぜつ本読書ログシリーズではおなじみのこちらの書き出し。元は『お隣の天使様にいつの間にか駄目人間にされていた件』の「家事ができないのに一人暮らしとか舐めているのですか」です
  2. Pythonで同様のYAMLで設定ファイルを書くDIフレームワークがあるかは探してみたいですね