Die Konvertierung zwischen der Form-Klasse, die den Eingabewert erhält, und der Entität ist schwierig, daher habe ich mir vier Lösungen überlegt.
Ich denke, die Lösungen, die verwendet werden könnten, sind 2 und 4. Dieses Mal haben wir es in 4 basierend auf der internen Kultur gelöst.
Ich habe mit Entity für die Persistenz in der Form-Klasse wie folgt konvertiert.
PurchaseForm.java
@Data
public class PurchaseForm {
@NotNull
private Integer commodityId;
@NotNull
private Integer count;
/**
*Generieren Sie eine Entität basierend auf dem Eingabewert
*/
public Purchase toEntity() {
//Kürzung
}
}
Wenn es sich um eine einfache Konvertierung handelt, gibt es überhaupt kein Problem, aber wenn es sich um das folgende Muster handelt, stirbt es.
Mit zunehmender Menge an Code im Programm, der in Entity konvertiert werden soll, wird die Sichtbarkeit des Quellcodes schlechter. Besonders wenn versucht wird, eine untergeordnete Klasse der zu generierenden Klasse zu generieren, ist dies ziemlich schmerzhaft. In den Projekten, an denen ich beteiligt bin, verlasse ich mich bei der Nummerierung des Primärschlüssels häufig auf AUTO INCREMENT. Daher ist es zwangsläufig erforderlich, den Primärschlüssel und den externen Schlüssel durch die Serviceklasse zu ergänzen. Ein Problem ist in mehrere Klassen unterteilt, z. B. das Initialisieren eines Teils mit Form und das Initialisieren des Restes mit der Service-Klasse, und es wird schwierig, dem Quellcode zu folgen.
PurchaseForm.java
@Data
public class PurchaseForm {
//Kürzung
/**
*Generieren Sie eine Entität basierend auf dem Eingabewert
*/
public Purchase toEntity() {
//Dies
//Dies
//Aber
//Mich
//Tsu
//Chi
//Ja
//Lange
//ich
//Wann
//Fazit
//Struktur
//Einer
//Et al.
//ich
}
}
Wenn Sie bisher ein beständiges Objekt als Argument benötigen, sollten Sie es nicht mehr in die Form-Klasse konvertieren.
PurchaseForm.java
@Data
public class PurchaseForm {
//Kürzung
/**
*Generieren Sie eine Entität basierend auf dem Eingabewert
*Wenn Sie eine große Anzahl von persistierten Objekten als Argumente verwenden, fragen Sie sich, ob Sie hier eine Entität erstellen müssen.
*/
public Purchase toEntity(Hoge hoge, Fuga Futa, ... etc) {
//Kürzung
}
}
Ich habe es versucht, aber es ist schmerzhaft. Denn mit zunehmendem Eingabewert von Form steigt die Anzahl der Argumente.
PurchaseController.java
@Controller
@RequireArgsConstructor
public class PurchaseController {
public final PurchaseService purchaseService;
public ModelAndView create(@ModelAttribute @Valid PurchaseForm form, BindingResult result) {
// check
// Ah...!
purchaseService.purchase(form.input1, form.input2, form.input3, form.input4, form.input5,...);
}
}
PurchaseController.java
@Controller
@RequireArgsConstructor
public class PurchaseController {
public final PurchaseService purchaseService;
public ModelAndView create(@ModelAttribute @Valid PurchaseForm form, BindingResult result) {
// check
purchaseService.purchase(new Hoge(form.input1, form.input2), new Fuga(form.input3, form.input4, form.input5),...);
}
}
Dies hat den Vorteil, dass Sie das Argumentobjekt vorkonditionieren können, um die Wertintegrität sicherzustellen. Voraussetzungen werden im Konstruktor geprüft.
Es ist sehr einfach, aber es ist ein wirklich schlechtes Muster! Es ist schwierig für die Abhängigkeitsrichtung, Form ← Service zu sein. Form ist eng mit Bildschirmspezifikationen verbunden, daher möchte ich nicht, dass die Seite der Geschäftslogik von Form abhängt. Es ist seltsam, dass die Serviceklasse geändert werden muss, da sich die Bildschirmspezifikationen geändert haben, obwohl sich die Geschäftslogik nicht geändert hat.
PurchaseController.java
@Controller
@RequireArgsConstructor
public class PurchaseController {
public final PurchaseService purchaseService;
public ModelAndView create(@ModelAttribute @Valid PurchaseForm form, BindingResult result) {
// check
// Fuck...!
purchaseService.purchase(form);
}
}
Dies wurde mit dem vierten Plan gelöst.
Zuerst habe ich die Service- und Argumentschnittstelle in einem Paket in der Nähe der Domäne definiert.
PurchaseService.java
@Service
public class PurchaseService {
public void purchase(PurchaseRequest request) {}
}
PurchaseRequest.java
public interface PurchaseRequest {
String getInput1();
Integer getInput2();
// etc...
}
Dann habe ich die Wertvalidierung in eine andere Implementierungsklasse geschrieben.
PurchaseForm.java
public class PurchaseForm implements PurchaseRequest {
@NotEmpty
private String input1;
@NotNull
private Integer input2;
public String getInput1() {
return input1;
}
public Integer getInput2() {
return input2;
}
}
Das Schöne an dieser Implementierungsmethode ist, dass sie den in der Service-Klasse verwendeten Wert auf der Ebene in der Nähe der Domäne deklariert, sodass sie nicht auf der Bildschirmseite geändert werden kann. Wenn sich Input und Output als Geschäftskonzept ändern, muss dies natürlich überprüft werden, aber einige Unterschiede können auf der Bildschirmseite kontrolliert werden.
Besser noch, ich denke, es ist gut, den Eingabewert vom Bildschirm an den auf der Domänenseite definierten Typ zu binden. Ich denke, dass es oft als die optimale Lösung bezeichnet wird. Dies ist die Lösung, die wir in unserem Projekt ohne eine Kultur der Implementierung der Validierung auf domänenseitigen Entitäten oder der semantischen Erfassung und Implementierung von Werttypen durchgeführt haben.
Danach habe ich beschlossen, eine API zu erstellen, um den Kaufpreis basierend auf den Informationen zu den gekauften Produkten und der Menge zu berechnen. Wenn Sie eine Methode namens "PurchaseService # berechnePreis (CalculatePriceRequest)" definieren und "PurchaseRequest" "CalcululatePriceRequest" erben lassen, können Sie den Kaufpreis auch mit einem Argument vom Typ "PurchaseRequest" problemlos berechnen. Das ist richtig, da die Produktkaufanfrage Informationen zu Produkt und Menge enthält, ist es ganz natürlich, den Kaufpreis anhand dieser Informationen berechnen zu können.
Ich mache viel Versuch und Irrtum, aber ich denke, dass ich in der Lage sein sollte, die Hand der Montagemethode zu erhöhen, indem ich die Muster analysiere, die funktionierten und die Muster, die nicht funktionierten. Insbesondere entwickle ich häufig WEB-Anwendungen, daher möchte ich über verschiedene E / A mit dem Bildschirm nachdenken.
Recommended Posts