nekoTheShadow’s diary

IT業界の片隅でひっそり生きるシステムエンジニアです(´・ω・`)

『なぜ依存を注入するのか DIの原理・原則とパターン』を読んだ

honto.jp

「なぜ依存を注入するのか」←ここだけ見ると、サイケでスピリチュアルな本かと身構えますが、もちろんそんな内容ではなく、「依存性の注入」について書かれた本になります。「依存性の注入」とは、モジュール間の結合度を下げるためのデザインパターンで、英語ではDependency Injectionといい、この頭文字をとってDIと略することもあります。その特徴はオブジェクトの生成と利用を分離すること。

たとえば、商品IDが与えられたら、商品レポジトリからその商品IDに該当する商品情報を取得する、商品サービスクラスがあるとします。これをナイーブに実装してみると、以下のようになります。

class ProductService:
    def get_product_by_product_id(product_id):
        product_repository = ProductRepository()
        for product in product_repository.get_all_products():
            if product.product_id == product_id:
                return product
        return None

これはモジュール結合度が高い状態で、たとえば、単体テストなどでProductRepositoryをモック化したい場合、このコードではそれを簡単に実現することはできません。そこで、依存性の注入を採用し、以下のようにリファクタリングします。

class ProductService:
    def __init__(self, product_service):
        self.product_service = product_service

    def get_product_by_product_id(product_id):
        for product in self.product_repository.get_all_products():
            if product.product_id == product_id:
                return product
        return None

あとは、すべてのプログラムのエントリポイントで、ProductServiceクラスを初期化します。

if __name__ == '__main__':
    product_repository = ProductRepository()
    product_service = Product_Service(product_repository)

こうすることで、モジュールの結合度が下げり、単体テストにモックを使うなどが容易になりました。またオブジェクトの生成と利用を分離し、オブジェクトの生成を一元化することで、たとえばシングルトンにするかしないかなど、オブジェクトのライフタイム管理がしやすくなったり、プログラム全体の見通しが良くなったりと、さまざまなメリットを享受することができます。

上記の例は依存性の注入の一部を示したにすぎません。本書では「そもそも依存性の注入ってなんだっけ?」というところから始まって、そのメリットやデメリット、実装のテクニックからアンチパターンまで、こと細かに解説しています。また、共通的な関心事をうまく取り扱うためのアスペクト志向プログラミング、オブジェクトの生成部分を自動化するDIコンテナといった、依存性の注入に関連したトピックについても、かなりの紙幅がされています。依存性の注入について、ありとあらゆる内容が体系的に学べるといって間違いないでしょう。

ちなみに本書の分量ですが、B5判で656ページもあります。しかも、字は小さい方で、スマートフォンだと読むのがつらいぐらい。それだけの分量を依存性の注入にだけ費やしているわけですから、中身のつまり具合は半端ではありません。逆にいうと、単なるデザインパターンのひとつについて、それだけ書いているわけで、ある意味サイケでスピリチュアルといえるかも(´・ω・`)

サンプルコードはC#で書かれていますが、C#や.NET特有の知識はそれほど求められないので、オブジェクト指向プログラミングとC系言語の経験があれば、まったく問題ないと思います。現に自分はJavaメインのSEで、C#はホビープログラミング以上の経験はありませんが、それでも困るということはありませんでした。ただし、最後の3章「第13章: DIコンテナ: Autofac」「第14章: DIコンテナ: Simple Injector」「第15章: DIコンテナ: MS.DI(Microsoft.Extensions.DependencyInjection)」については、.NETのライブラリを解説しているだけなので、ここはC#や.NETに関心がない人は読み飛ばしてもよいと思います。

ところでは自分はJavaメインのSEと書きましたが、Javaの世界ではSpring Frameworkというアプリケーションフレームワークがデファクトスタンダードになりつつあります。実はこのSpring Frameworkですが、依存性の注入の考え方をふんだんに取り入れたフレームワークになっています。要するにJavaでお仕事をする以上は依存性の注入からは逃れられない可能性が高いわけです。自分のキャリアが今後どうなるかは不透明ですが、当面はJavaを利用しそうなので、Javaと関連が深い依存性の注入についてしっかり勉強できたことはよかったかなと思います。