[JAVA] Erklären Sie DI in einer fettleibigen Geschichte

Einführung

Dieser Artikel ist der 12. Tagesartikel von Java Advent Calendar 2018.

Es ist ungefähr ein halbes Jahr her, seit ich mit Javas DI in Kontakt gekommen bin. Ich habe mich entschlossen, ein neues Mitglied des Teams in Eile zu unterrichten, daher werde ich es in einem Artikel für meine Rezension zusammenfassen.

Hier ist ein Beispielprojekt. https://github.com/segurvita/FatnessChecker

Ziel dieses Artikels

Für diejenigen, die Klassen und Konstruktoren verstehen, DI aber nicht gut kennen.

Ich werde versuchen, es nur mit Klassen und Konstruktoren zu erklären, damit ich es verstehen kann, ohne Bean oder Interface zu kennen.

Ich verstehe die Bedeutung von "DI bedeutet Injektion von Abhängigkeit" nicht.

Der Zweck dieses Artikels ist es, die Bedeutung dieser ** Abhängigkeitsinjektion ** zu verstehen.

DI bedeutet, in der Klasse kein "neues" zu verwenden!

Haben Sie keine Angst vor Missverständnissen. ** DI bedeutet, dass Sie in einer Klasse nicht new verwenden **. (Ich verstehe, dass es kein genauer Ausdruck ist, aber dieser Artikel wird mit einem Schwerpunkt auf Klarheit erklärt.)

Nicht-DI-Muster

public class Hoge{
    //Feld (Mitgliedsvariable)
    Fuga piyo;
    
	//Konstrukteur
	public Hoge() {
	    //Ich benutze neu in meiner Klasse.
		this.piyo = new Fuga();
	}
}

DI-Muster

public class Hoge{
    //Feld (Mitgliedsvariable)
    Fuga piyo;
    
	//Konstrukteur
	public Hoge(Fuga mogera) {
	    //Nicht neu verwenden. Ich spritze von außen.
		this.piyo = mogera;
	}
}

Ich verstehe jedoch nicht das Verdienst damit allein. Von hier aus werde ich im Story-Format erklären.

Folge 1: Ich ging zu einer Adipositas-Urteilsfirma

Eine Geschichte, die plötzlich beginnt

: Mann: Bin ich fett? Das ist es! Lassen Sie uns eine Firma zur Beurteilung von Fettleibigkeit um Inspektion bitten!

Nach einigen Stunden

: person_frowning: Willkommen bei der Firma zur Bestimmung von Fettleibigkeit. Was für ein Geschäft haben Sie heute?

: man: Ich möchte den Grad der Fettleibigkeit beurteilen.

: person_frowning: Sie sind ein Kunde, der den Grad der Fettleibigkeit beurteilt. Ist es in Ordnung, nach Größe und Gewicht zu fragen?

: man: Nun, ich bin 170 cm groß und wiege 70 kg.

: person_frowning: Ich bin schlau. Bitte warte einen Moment. Wir werden den BMI mit unserem neuesten Roboter berechnen.

: Roboter: Berechnung Shimasu ・ ・ ・ 70 kg ÷ 1,70 m de, BMI Ha ** 41,18 ** Tod!

: person_frowning: Wenn der BMI 41,18 beträgt ... ist er 40 oder mehr, also ** 4 Grad fettleibig **.

: man: Ja! Eine solche!

Nach einigen Stunden

: man: Es ist absolut seltsam, dass ich fettleibig bin. Ist dieser Roboter nicht ein Fehler?

Was ist BMI?

Der BMI (physikalischer Index) wird nach Gewicht (kg) ÷ Größe (m) ÷ Größe (m) berechnet.

Ist die Berechnung von: Roboter: falsch?

Was ist Adipositas-Urteil?

In Japan gelten Menschen mit einem BMI von 25 oder höher als ** fettleibig **. Es gibt vier Stadien der Fettleibigkeit von 1 bis 4 Grad.

Bildzitat: OMRON / vol.103 überarbeitete erstmals seit 11 Jahren die diagnostischen Kriterien für Fettleibigkeit

Deine Rolle

Die Leute, die in der ersten Folge erschienen sind, sind wie folgt.

-: Mann: ist eine Person, die ihre Fettleibigkeit kennenlernen möchte. Da es sich um einen Benutzer handelt, nennen wir ihn "Benutzer". -: Person_frowning: ist die Rezeption der Adipositas-Urteilsfirma. Berechnen Sie den BMI nicht selbst, sondern fragen Sie: Roboter: um es zu tun. Der Grad der Fettleibigkeit kann anhand des BMI-Werts bestimmt werden. Nennen wir es "FatnessChecker". -: Roboter: ist ein Roboter, der den BMI berechnet. Es gibt immer noch einen Fehler im Prototyp. Nennen wir es "BmiRobot".

Problem des Falles der ersten Folge

: robot: BmiRobot hat einen Fehler bei der Berechnung des BMI gemacht. Anscheinend gibt es einen Fehler.

Basierend auf diesem falschen Berechnungsergebnis: person_frowning: FatnessChecker hat ein Adipositas-Urteil abgegeben, daher war auch das Beurteilungsergebnis falsch.

Mit anderen Worten, das Problem ist, dass: person_frowning: FatnessChecker sich auf einen unzuverlässigen Roboter stützte :: robot: BmiRobot.

Folge 2: Auftritt von BMI Sennin

: man: Es ist absolut seltsam, dass ich fettleibig bin. Ist dieser Roboter nicht ein Fehler?

: senior_man: Hat diese Person Probleme mit der BMI-Berechnung?

: man: Wer bist du?

: senior_man: Ich bin ein BMI-Einsiedler. Bitte erzähl mir die Geschichte, wenn du magst.

: man: Ja, es ist eigentlich ein Geheimnis ...

Ein paar Tage später

: information_desk_person: Willkommen bei der Firma zur Bestimmung von Fettleibigkeit. (Ausgelassen) Darf ich Sie nach Ihrer Größe und Ihrem Gewicht fragen?

: man: Er ist 170 cm groß und wiegt 70 kg. Ich werde diese Person jedoch bitten, den BMI zu berechnen, nicht den Roboter neulich.

: old_man: Hohoho, in diesem Fall 70 kg ÷ 1,70 m ÷ 1,70 m, BMI ist ** 24,22 **.

: information_desk_person: Ich bin schlau. Wenn der BMI 24,22 beträgt ... ist er mehr als 18,5 und weniger als 25, also ** normales Gewicht **.

: man: Ich habe es geschafft! Ich bin kaum fettleibig!

Deine Rolle

Die Leute, die in der zweiten Folge erschienen sind, sind wie folgt.

-: Mann: ist eine Person, die ihre Fettleibigkeit kennenlernen möchte. Da es sich um einen Benutzer handelt, nennen wir ihn "Benutzer". -: Older_man: beherrscht die Berechnung des BMI. Ich habe viel trainiert, deshalb werde ich bei der Berechnung nie einen Fehler machen. Nennen wir es "BmiMaster". -: Information_desk_person: ist eine Person, die Folgendes verwendet: old_man: um Fettleibigkeit zu bestimmen. Es ist dieselbe Person wie: person_frowning: aber zur Erklärung werden wir es unterscheiden und es "FatnessCheckerDi" nennen.

DI-Lösung

: man: User fragte: information_desk_person: FatnessCheckerDi, um den Grad der Fettleibigkeit zu bestimmen, unter der Bedingung, dass: senior_man: BmiMaster den BMI berechnen soll.

Infolgedessen hängt das Beurteilungsergebnis von: information_desk_person: FatnessCheckerDi von der zuverlässigen Person ab :: senior_man: BmiMaster.

Dies ist ** DI ** (Abhängigkeitsinjektion)! Mit anderen Worten

: man: User injiziert: älter_man: BmiMaster in: information_desk_person: FatnessCheckerDi!

Vorteile von DI

Der Vorteil von DI besteht darin, dass Sie das in der Entwicklung befindliche Teil ** Unit-testen können, auch wenn das abhängige Teil nicht fertiggestellt ist **.

In diesem Fall gab es einen Fehler in: robot: BmiRobot. Wenn es also nicht funktioniert hätte, wäre es in Ordnung, wenn wir genug Tests durchgeführt und den Fehler in: robot: BmiRobot reduziert hätten. ?? Ich denke, es gibt auch eine Meinung. (Das dachte ich zuerst.)

Es wird jedoch einige Zeit dauern, um ** genug zu testen **.

: person_frowning: FatnessChecker hängt ab von: robot: BmiRobot, daher können Sie nicht testen: person_frowning: FatnessChecker bis: robot: BmiRobot abgeschlossen ist. Dies erhöht die Entwicklungszeit.

Auf der anderen Seite: information_desk_person: FatnessCheckerDi ermöglicht das externe Injizieren der abhängigen Teile (: senior_man: BmiMaster) (: man: User). Selbst wenn der abhängige Teil (: älter_man: BmiMaster) nicht abgeschlossen ist, injizieren Sie auf diese Weise einen Mock (nur Test-Haribote) des abhängigen Teils (: älter_man: BmiMaster): information_desk_person: FatnessCheckerDi kann Unit-getestet werden.

Nachteile von DI

Der Nachteil ist, dass ** die Lernkosten hoch sind **.

Im Falle der Teamentwicklung müssen alle Mitglieder DI lernen, wenn DI in das in der Entwicklung befindliche Projekt übernommen wird. Für Teams mit vielen Mitgliederwechseln sind die Ausbildungskosten hoch und können nicht ignoriert werden.

Beispielcode

Ich denke, dass es schwierig ist, nur Sätze zu vermitteln, deshalb werde ich es mit Java-Code erklären.

Hier ist ein Beispielprojekt. https://github.com/segurvita/FatnessChecker

: robot: Bei Berechnung mit BmiRobot (vor DI-Einführung)

Erstens: man: User sieht so aus.

User.java


/**
 *Menschen, die den Grad der Fettleibigkeit wissen wollen
 */
public class User {
	/**
	 *Bitten Sie ein Unternehmen zur Beurteilung von Fettleibigkeit, ein Urteil ohne BMI-Master zu fällen.
	 */
	public void runWithoutBmiMaster() {
		//Beginnen Sie ein Gespräch mit einer Person eines Unternehmens zur Beurteilung von Fettleibigkeit.
		FatnessChecker fatnessChecker = new FatnessChecker();

		//Sagen Sie ihnen Ihre Größe und Ihr Gewicht und bitten Sie sie, ihre Fettleibigkeit festzustellen.
		String result = fatnessChecker.check(170.0, 70.0);

		//Das Beurteilungsergebnis des Grads der Fettleibigkeit wird angezeigt.
		System.out.println("Ergebnis der Beurteilung der Fettleibigkeit (ohne BMI-Master):" + result);
	}
}

Sie fordern Arbeit bei fatnessChecker.check an.

Dann: person_frowning: FatnessChecker sieht so aus:

FatnessChecker.java


/**
 *Unternehmen zur Beurteilung von Fettleibigkeit (mit BMI-Roboter)
 */
public class FatnessChecker {
	/**
	 *BMI bestimmen
	 * @param Höhe Höhe[cm]
	 * @param Gewicht Gewicht[kg]
	 * @Fettleibigkeit zurückgeben
	 */
	public String check(double height, double weight) {
		//Sichern Sie sich einen der neuesten BMI-Roboter im Unternehmen.
		BmiRobot bmiRobot = new BmiRobot();

		//Bitten Sie den BMI-Roboter, den BMI zu berechnen.
		double bmi = bmiRobot.calc(height, weight);

		//Bestimmen Sie den Grad der Fettleibigkeit aus dem BMI-Berechnungsergebnis.
		if (bmi < 18.5) {
			return "Geringes Gewicht";
		} else if (bmi < 25.0) {
			return "Normalgewicht";
		} else if (bmi < 30.0) {
			return "Einmal fettleibig";
		} else if (bmi < 35.0) {
			return "Zweimal fettleibig";
		} else if (bmi < 40.0) {
			return "3. Grad fettleibig";
		} else {
			return "4. Grad fettleibig";
		}
	}
}

Bei der "check" -Methode wird "new BmiRobot ()" verwendet, um einen zu sichern: robot: "BmiRobot".

Danach wird die BMI-Berechnung von "BmiRobot.calc (Größe, Gewicht)" angefordert, und der Grad der Fettleibigkeit wird basierend auf dem Berechnungsergebnis beurteilt.

Wenn es einen Fehler in: robot: BmiRobot gibt, ist das Bewertungsergebnis falsch. : robot: Kommt auf BmiRobot an.

Das: Roboter: BmiRobot ist implementiert, zum Beispiel:

BmiRobot.java


/**
 *BMI-Roboter (mit Fehlern)
 */
public class BmiRobot {
	/**
	 *BMI berechnen
	 * @param Höhe Höhe[cm]
	 * @param Gewicht Gewicht[kg]
	 * @return BMI
	 */
	public double calc(double height, double weight) {
		//Körpergewicht[kg]÷ Höhe[m]
		return weight * 100 / height;
	}
}

Die Formel lautet "Gewicht [kg] ÷ Höhe [m]", was falsch ist.

Wenn Sie das Programm in diesem Zustand ausführen, ist das Ergebnis

Ausführungsergebnis


Ergebnis der Beurteilung der Fettleibigkeit (ohne BMI-Master): 4 Grad Fettleibigkeit

Es wird sein.

: old_man: Bei Berechnung mit BmiMaster (nach DI-Einführung)

Erstens: man: User sieht so aus.

User.java


/**
 *Menschen, die den Grad der Fettleibigkeit wissen wollen
 */
public class User {
	/**
	 *Bitten Sie bei einem BMI-Master ein Unternehmen zur Beurteilung von Fettleibigkeit, ein Urteil zu fällen.
	 */
	public void runWithBmiMaster() {
		//Sichern Sie sich einen BMI-Master.
		BmiMaster bmiCalculator = new BmiMaster();

		//Bitten Sie eine Person von der Adipositas-Urteilsfirma, die BMI-Berechnung zu einem BMI-Master zu machen.
		FatnessCheckerDi fatnessCheckerDi = new FatnessCheckerDi(bmiCalculator);

		//Sagen Sie ihnen Ihre Größe und Ihr Gewicht und bitten Sie sie, ihre Fettleibigkeit festzustellen.
		String result = fatnessCheckerDi.check(170.0, 70.0);

		//Das Beurteilungsergebnis des Grads der Fettleibigkeit wird angezeigt.
		System.out.println("Ergebnis der Beurteilung der Fettleibigkeit (mit BMI-Master):" + result);
	}
}

Der große Unterschied zum vorherigen besteht darin, dass: man: User`` new BmiMaster () verwendet und eins reserviert: old_man: BmiMaster. Dies wird übergeben an: information_desk_person: FatnessCheckerDi in new FatnessCheckerDi (bmiCalculator).

Dann: information_desk_person: FatnessCheckerDi sieht folgendermaßen aus:

FatnessCheckerDi.java


/**
 *Unternehmen zur Beurteilung von Fettleibigkeit (unter Verwendung des BMI-Masters)
 */
public class FatnessCheckerDi {
	/**
	 *BMI-Meister
	 */
	final private BmiMaster bmiMaster;

	/**
	 *Konstrukteur
	 * @param bmiCalculator BMI-Master vom Benutzer benannt
	 */
	public FatnessCheckerDi(BmiMaster bmiMaster) {
		//Wir begrüßen den vom Benutzer nominierten BMI-Master.
		this.bmiMaster = bmiMaster;
	}

	/**
	 *BMI bestimmen
	 * @param Höhe Höhe[cm]
	 * @param Gewicht Gewicht[kg]
	 * @Fettleibigkeit zurückgeben
	 */
	public String check(double height, double weight) {
		//Bitten Sie den vom Benutzer benannten BMI-Master, den BMI zu berechnen.
		double bmi = this.bmiMaster.calc(height, weight);

		//Bestimmen Sie den Grad der Fettleibigkeit aus dem BMI-Berechnungsergebnis.
		if (bmi < 18.5) {
			return "Geringes Gewicht";
		} else if (bmi < 25.0) {
			return "Normalgewicht";
		} else if (bmi < 30.0) {
			return "Einmal fettleibig";
		} else if (bmi < 35.0) {
			return "Zweimal fettleibig";
		} else if (bmi < 40.0) {
			return "3. Grad fettleibig";
		} else {
			return "4. Grad fettleibig";
		}
	}
}

Der große Unterschied zum vorherigen ist das Aussehen des Konstruktors.

Früher haben wir in der check -Methode eine reserviert: robot: BmiRobot, aber diesmal erhalten wir: senior_man: BmiMaster als Argument des Konstruktors und verwenden es als Feld (Mitgliedsvariable). ) Ist zugeordnet.

Danach wird die BMI-Berechnung von "this.bmiMaster.calc (Größe, Gewicht)" angefordert, und der Grad der Fettleibigkeit wird basierend auf dem Berechnungsergebnis beurteilt.

Jetzt kommt es darauf an: senior_man: BmiMaster.

Das: ältere_man: BmiMaster ist implementiert, zum Beispiel:

BmiMaster.java


/**
 *BMI Master (Master)
 */
public class BmiMaster {
	/**
	 *BMI berechnen
	 * @param Höhe Höhe[cm]
	 * @param Gewicht Gewicht[kg]
	 * @return BMI
	 */
	public double calc(double height, double weight) {
		//Körpergewicht[kg] ÷ (Höhe[m])^2
		return weight * 10000 / (height * height);
	}
}

Die Formel lautet "Gewicht [kg]" (Höhe [m]) ^ 2 ". Dies ist die richtige Formel.

Wenn Sie das Programm in diesem Zustand ausführen, ist das Ergebnis

Ausführungsergebnis


Ergebnis der Beurteilung der Fettleibigkeit (mit BMI-Master): Normalgewicht

Es wird sein.

Bonus: Wo um alles in der Welt soll ich "neu" sein?

In dieser Geschichte: man: User vorbereitet: old_man: BmiMaster (new) und injiziert es in: information_desk_person: FatnessCheckerDi.

Also, wenn: man: User selbst auch mit einem DI-Muster entworfen wurde, wer würde vorbereiten: old_man: BmiMaster?

: man: Wird es eine andere Klasse außerhalb von "User" geben? Was wäre, wenn selbst diese Klasse mit einem DI-Muster entworfen würde?

Hier kommt der ** DI-Container ** ins Spiel. Übernimmt die Verarbeitung von "neu" sofort.

Im Fall von Java Spring entspricht BeanFactory dem.

schließlich

Was haben Sie gedacht. Ich habe versucht, DI mit Story Tailoring zu erklären.

Als ich DI vor einem halben Jahr zum ersten Mal berührte, wurde ich in unbekannten Begriffen wie "Autowired" und "BeanFactory" begraben, und es wurde "DI schwierig ...". (Zu diesem Zeitpunkt gab es keinen Unterschied zwischen DI und DI-Container.)

Als ich es jedoch ein halbes Jahr lang codierte und zurückblickte, dachte ich: "Ist es nicht möglich, DI zu erklären, ohne zu wissen, dass es tatsächlich" Bean "ist?" Also schrieb ich diesen Artikel vor einem halben Jahr für mich. Ich versuchte es.

Ich hoffe es wird dir hilfreich sein.

Referenzseite

Ich habe auf die folgende Seite verwiesen.

Recommended Posts

Erklären Sie DI in einer fettleibigen Geschichte
Die Geschichte einer illegalen staatlichen Ausnahme in Jetty.
[Docker] Eine Geschichte über einen Fehler beim Erstellen von Docker