血糖値管理をWebアプリにする③ 理解のまとめ4

プログラミング

DI(依存性の注入)について、理解したことをまとめておきます。
チュートリアルでは DIコンテナ というものが登場するのですが、それを理解するために、まず、DIについて理解する必要があります。


とても参考になったサイトがありました。
DIは美しいデザインパターン – Qiita

今回は、このサイトで使用しているサンプルコードを参考に、私なりに、理解のポイントをまとめていきたいと思います。

完全に理解できた、とは言えないのですが、現段階までを固めておきたいと思います。
なお、掲載量があるため、2回くらいに分けて掲載します。
第一回は、依存性とはなにか、依存性の問題点、について掲載します。

理解へのアプローチとして、つぎの順番で理解をしていきました。

  • 依存性とはなにか
  • 依存性の問題点
  • 依存性をなくす(弱める)方法
  • 注入とは何か

サイトのサンプルコードは、次のような内容を題材にしています。

HondaEngineクラスというエンジン用のクラスがあり、エンジンを起動するstartEngineと停止するstopEngineの2つのメソッドを持っています。

Carクラスという車体用のクラスがあり、HondaEngineを搭載しいます。
Carクラスには、goメソッドがあり、このメソッドは、まずエンジンを起動(スタート)し、その次に停止(ストップ)を行います。
エンジンの起動と停止は、HondaEngineクラスのメソッドを使います。

Mainクラスでは、この2つのクラス(HondaEngine、Car)を使って、車を3台作ります(Car1、Car2、Car3)。
そして、それぞれの車でGoメソッドを実行し、エンジンの起動と停止を行います。

なお、コードはJavaで記述されています。
また、一部私が変更をしたり、書き足したコードもあります。

まずは、依存性のあるコードの例を示します。

HondaEngine.java
public class HondaEngine {
 
    public void startEngine() {
        System.out.println(“ホンダスタート”);
    }
 
    public void stopEngine() {
        System.out.println(“ホンダストップ”);
    }
}
Car.java
public class Car{

    private HondaEngine hondaEngine;
 
    public Car(HondaEngine hondaEngine) {
        this.hondaEngine = hondaEngine;
    }
 
    public void go() {
        hondaEngine.startEngine();
        hondaEngine.stopEngine();
    }
}
Main.java
public class Main {
 
    public static void main(String[] args) {
        HondaEngine engine1 = new HondaEngine();
        HondaEngine engine2 = new HondaEngine();
        HondaEngine engine3 = new HondaEngine();
 
 
        Car car1 = new Car(engine1);
        Car car2 = new Car(engine2);
        Car car3 = new Car(engine3);
 
        car1.go();
        car2.go();
        car3.go();
    }

まず、依存性について上記コード例を見ながら確認していきます。

どこに依存性があるかというと、Carクラスの次の青字の部分です。

public class Car {

    private HondaEngine hondaEngine;

    public Car(HondaEngine hondaEngine) {

        this.hondaEngine = hondaEngine;

    }

青字の部分は、HondaEngine型のインスタンスを指定しています。
それは、Carクラスの中で、HondaEngine型のインスタンスのメソッドを使用するためです。
そのためには、当然、HondaEngineクラスが存在していることが前提になります。
CarクラスはHondaEngineクラスが存在していることが前提で作ることができるということです。
このことを、CarクラスはHondaEngineクラスに依存している、といいます。
このように依存性が強い状態を密結合といいます。

まず最初にHondaEngineクラスを作り、次にCarクラスを作れば問題はないのですが、大規模システムの開発では同時進行で開発しますので、これでは困ります。
HondaEngineクラスが開発中でバグがあっても、CarクラスでHondaEngineクラスを使うと、そのバグをもろにかぶってしまいます。
つまり、上記のようなコードでは、あるクラスが別のクラスを使うとどうしても依存性の問題が起こってしまうのです。

依存とは「他のクラスを利用していること」と、言うことができます。

依存性が強い(密結合)場合の問題点として、
あるクラスが別のクラスのメソッドを使う場合、その別のクラスが完成するまで開発できない、ことがあります。
コード例でいうと、CarクラスがHondaEngineクラスのstartEngine()メソッドとstopEngine()メソッドを使う場合、Carクラスの開発は、HondaEngineクラスが完成していないとできない、ということです。

依存性の問題点は、もう一つあります。

これを考えるにあたり、HondaEngineからNIssanEngineにエンジンが変更になった場合を想定してみます。
どちらのエンジンも機能は同じとします。
つまり、どちらのエンジンもstartEngine()メソッドとstopEngine()メソッドを持っています。

上記コードのような依存が密結合の場合、どのような修正を行うことになるか、コードを変更してみます。

NissanEngine.java
public class NissanEngine {
 
    public void startEngine() {
        System.out.println(“ニッサンスタート”);
    }
 
    public void stopEngine() {
        System.out.println(“ニッサンストップ”);
    }
}
Car.java
public class Car {
 
    private NIssanEngine nissanEngine;
 
    public Car(NissanEngine nissanEngine) {
        this.nissanEngine = nissanEngine;
    }
 
    public void go() {
        nissanEngine.startEngine();
        nissanEngine.stopEngine();
    }
}
Main.java
public class Main {
 
    public static void main(String[] args) {
        NissanEngine engine1 = new NissanEngine();
        NissanEngine engine2 = new NissanEngine();
        NissanEngine engine3 = new NissanEngine();
 
 
        Car car1 = new Car(engine1);
        Car car2 = new Car(engine2);
        Car car3 = new Car(engine3);
 
        car1.go();
        car2.go();
        car3.go();
    }

上記コードの赤字の部分が主な変更点です。
赤字の部分はNissanEngineのクラスであり、NissanEngineクラスのインスタンス型でもあります。
(nissanEngineは変数なので、hondaEngineのままでも動作に問題ないので、赤字にしていません。)

NissanEngineクラスを作成するのは、どうしようもありません。作るしかありません。

問題は、
Carクラスの次の赤字の部分

    private NIssanEngine nissanEngine;

    public Car(NissanEngine nissanEngine) {

そして、

Mainクラスの次の赤字の部分

        NissanEngine engine1 = new NissanEngine();

        NissanEngine engine2 = new NissanEngine();

        NissanEngine engine3 = new NissanEngine();

です。

今回は、HondaEngineからNissanEngineに変更するクラスは、CarクラスとMainクラスの2つだけなので、修正は何ということもありません。
しかし、Carクラス以外に、たくさんのクラスがHondaEngineを使っているとしたら、どうでしょう。
例えば、HondaEngineを使っているクラスが100クラスあれば、Carクラスと同じような修正を100クラスで行わなければなりません。
見落としも心配です。

依存性が強い(密結合)場合の問題点の2つ目は、
依存しているクラスを変更したいときに修正する箇所が多い
という問題です。

まとめると、
依存とは
「他のクラスを利用していこと」

依存性が強い=密結合 の問題点は
あるクラスが別のクラスのメソッドを使う場合、その別のクラスが完成するまで開発できない」
「依存しているクラスを変更したいときに修正する箇所が多い」

以上、依存性とは何か、依存性の問題点 について、サイトの情報を参考に、理解した点をまとめました。
次回は、依存性をなくす(弱める)方法 と 注入とは何か について、理解のまとめを掲載したいと思います。

徒然に思うこと
もうすぐ65歳になる方とお話ししました。
65歳定年のため、65歳になったらどうしようか、という話です。
あらためて「働く」ということを考えました。
現役の時は「仕事」とう感覚でしたが、今の私は「働く」という感覚です。
明確に言葉にできないのですが、私の中ではこの2つは違っています。
生きるうえで、なすべきことは、そんなに複雑なことではないと思います。
自分なりに最善は尽くしますが、結局は、あるがまま、ながれるままという感覚です。
結果を求めるというより、充足感を求めているのかもしれません。

タイトルとURLをコピーしました