Bei einer früheren DDD-Diskussionsrunde wurde ich gefragt: "Wenn Sie DDD in einer statischen Sprache ausführen, benötigen Sie einen Test?", Und mehr Menschen waren überrascht, "Ja / Vielleicht" zu hören. Also habe ich beschlossen, es ein wenig zu klären.
Zusammenfassend lautet meine Theorie: "Natürlich hat das Kompilieren viele Vorteile, aber das Aufhören des Denkens löst nicht alles, und es wird viel gelernt, daher ist es besser, es zu schreiben."
Zum Beispiel ist eine Änderung, die "else if" erhöht, ziemlich gefährlich, wenn es nur einen Typ gibt.
Plan.java
public enum Plan {
PLAN_1,
PLAN_2,
PLAN_3;
}
Price.java
public class Price {
private final int value;
public static Price of(Plan plan) {
if (plan == Plan.PLAN_1)
return new Price(100);
else if (plan == Plan.PLAN_2)
return new Price(200);
else
return new Price(300);
}
}
Ich habe "PLAN_4" hinzugefügt.
Ich wollte, dass der Preis 400 Yen beträgt, aber ich habe vergessen, "else if" hinzuzufügen.
public enum Plan {
PLAN_1,
PLAN_2,
PLAN_3,
+ PLAN_4;
}
Natürlich geht die Zusammenstellung durch und PLAN_4
kostet 300 Yen.
erschrocken. sehr gruselig.
Es ist ein dummes Beispiel, aber es ist kein Witz.
Es ist nicht ungewöhnlich, dass Produkte daran denken, "else if" wie "price", "detail item", "mail text", "system code" usw. gemäß "Plan" hinzuzufügen. ** Es ist ziemlich rücksichtslos, diese Art von Leckage in großem Maßstab zu verhindern. ** ** **
Das Schreiben eines Tests sollte etwas besser sein.
Es kann festgestellt werden, ob alle Elemente von enum (Plan.values ()
) im Testcode gut verflochten sind.
PriceTest.groovy
//Der Testcode verwendete Groovy und Spock
class PriceTest extends Specification {
def "#plan -> #exp"() {
expect:
Price.of(plan) == new Price(exp)
where:
plan || exp
Plan.PLAN_1 || 100
Plan.PLAN_2 || 200
Plan.PLAN_3 || 300
}
def guard() {
expect:
Plan.values().length == 3
}
}
Es ist einfach, aber wenn ein Test, der von "Plan" abhängt, "== 3" enthält, werden Sie feststellen, wann "Plan" zunimmt oder abnimmt.
Ich benutze "else" nicht für die Preisbeurteilung.
Price.java
else if (plan == Plan.PLAN_3)
return new Price(300);
else
throw new RuntimeException("match error");
Wenn Sie Testcode haben, werden Sie ihn bemerken.
Im Gegenteil, wenn Sie es gut machen, können Sie solche Fehler perfekt verhindern.
Beispiel 1
MailService.java
public class MailService {
public void send(String itemName, String userName) {
String mailBody = MailBodyFactory.create(itemName, userName);
...
}
}
Beispiel 2
FooService.java
public class FooService {
FooRepository fooRepository;
public void replace(Foo usingOne) {
Foo newOne = Foo.newOne();
fooRepository.replace(newOne, usingOne);
}
}
Was falsch ist, ist ...
Beispiel 1
MailFactory.java
public class MailBodyFactory {
public static String create(String userName, String itemName) {
return String.format("%s%Vielen Dank für den Kauf von s", userName, itemName);
}
}
Beispiel 2
FooRepository.java
public interface FooRepository {
void replace(Foo usingOne, Foo newOne);
}
Die Reihenfolge der Argumente wurde umgekehrt.
Hast du gedacht "Weißt du!"? Aber die meiste Zeit erinnere ich mich nicht an die Reihenfolge der Produktcode-Argumente, und es ist unerwartet anstrengend, sie sorgfältig zu implementieren.
Außerdem ist so etwas sehr schlecht, weil es sich schlecht bewegt.
Missbrauche String
nicht und erstelle Klassen für UserName
und ItemName
.
Dann kann man es nie umkehren.
Foo
scheint eine Domain-Klasse erstellt zu haben, aber teilen wir sie zum Beispiel durch den Status.
public interface FooRepository {
- void replace(Foo usingOne, Foo newOne);
+ void replace(UsingFoo usingFoo, NewFoo newFoo);
}
Dies wird niemals das Gegenteil sein. (Ich habe diesen Artikel zusammen mit dem Impuls über die Klassen nach Status geschrieben → [Stoppen wir die göttliche Entität, die alle Status in einer Klasse ausdrückt!](Https://qiita.com/suzuki-hoge/items / d3ea5940898d85bbc03e)))
Es ist eine grobe Anleitung, aber ich denke, es ist besser, ** einzugeben, wo Sie versuchen, mit Variablennamen zu erklären **.
Es ist viel einfacher, die rote Linie zu bekommen, und der Herausgeber denkt auch klug über Komplementkandidaten nach.
Übrigens habe ich schon einmal eine ähnliche Geschichte geschrieben. Wenn Sie also interessiert sind, schauen Sie bitte auch dort nach. Es fühlt sich gut an, unterschiedliche Klassen für dieselben Tabellenwerte zu haben
String
überhaupt nicht genießenZum Beispiel dieser Code
CampaignCode.java
public enum CampaignCode {
CODE_A, CODE_B;
public static CampaignCode create() {
if (LocalDateTime.now().getDayOfMonth() < 15) {
return CODE_A;
} else {
return CODE_B;
}
}
}
Wenn ich versuche, einen Testcode zu schreiben, stört "jetzt" und ich sollte sagen "Oh, ich kann keinen Test schreiben ... ??".
Dies bedeutet, dass das von Ihnen hergestellte Produkt nur mit "jetzt" funktioniert, sodass es das Testen anderer Teile stört und bei Verspottungs- und Integrationstests nicht flexibel ist.
** Der Testcode verwendet zuerst diese Methode **, daher ist es eine gute Chance, so etwas wie "das? Ist diese Methode schwierig zu verwenden?" Zu bemerken.
(In diesem Beispiel sollte "jetzt" als Argument übergeben werden.)
Foo using
Im Fall von Enum treten beispielsweise Warnungen und Kompilierungsfehler in Abhängigkeit von der Sprache auf, aber ich dachte, dass der Hauptfluss des Veranstaltungsortes "Beseitigt die Kompilierung die Notwendigkeit von Testcode?". Also dachte ich darüber nach, ihn als Antithese zu schreiben. Ich tat.
Dieser Artikel ist meine persönliche Theorie.
Wenn Sie die Worte einer Person imitieren möchten, die Sie kürzlich gehört haben, wenn Sie denken "Ich habe gehört, Sie brauchen keinen Test, oder?", Schreiben Sie den Test gehorsam. Ich denke. Das ist es.
Recommended Posts