[JAVA] Es fühlt sich gut an, unterschiedliche Klassen für dieselben Tabellenwerte zu haben

Einführung

Fassen Sie die Geschichte zusammen, dass es nicht ausreichte, dieselbe Klasse zu verwenden, nur weil die Werte gleich sind.

Schreiben wir drei leicht unterschiedliche Beispiele. Ich habe den Verarbeitungsinhalt entsprechend geändert, aber die Konfiguration so angepasst wie der Teil, in dem ich mit dem von mir gepflegten Dienst zu kämpfen hatte.

Eigentlich wird das Klassendesign basierend auf der Idee von DDD entschieden, aber dieses Mal werde ich nur sagen, dass es ziemlich gut sein wird, wenn man nur den Typ entwickelt.

Artikel Prämisse

Fall 1 Behandeln Sie zwei Primärschlüssel

Angenommen, ein an einen Mitarbeiter verliehenes Firmenhandy ist defekt und wird ersetzt. Erhalten Sie die aktuell verwendete Seriennummer und ersetzen Sie sie durch die neu vorbereitete Seriennummer.

Klassen und Implementierungen

number_1.png (SerialNumber) und (SerialNumber, SerialNumber) sind anfällig für Fehler.

number_3.png Da die beiden Seriennummern nur durch den Variablennamen unterschieden werden, kann sie auch mit "(geändert, geändert)" kompiliert werden. .. Dann, wahrscheinlich durch Durchsuchen der Daten mit dem ersten Argument, fühlt es sich wie eine Ausführungsausnahme an, wie "Eine solche Seriennummer ist nicht ausgeliehen". (Abgesehen davon ist mir gerade aufgefallen, dass ich einen Fehler machen könnte, wenn ich ihn mit der Ergänzung des Editors schreibe, weil sowohl "geändert" als auch "aktuell" von "c" stammen. Es ist unerwartet, dass ein solcher Fehler ein langes Wort ist.)

Refactor

number_2.png Da "Domänen" nur eine Zahlenklasse hat, ist die Handhabung einfach und bezieht sich auf die Methode zur Identifizierung aller Teile, die hart mit dem Variablennamen "aktuell" und "geändert" mit den Klassen "aktuell" und "geändert" arbeiten. ..

number_4.png Es fühlt sich gut an.

tatsächlich

Schließlich wird es in dieselbe Spalte derselben Tabelle verschoben. Wenn Sie also zu der Ebene gehen, die so nah wie möglich an der Datenbank liegt, können Sie aus "CurrentSerialNumber" eine "SerialNumber" erstellen, um den Abstraktionsgrad zu erhöhen.

"SerialNumber" sollte jedoch in der Nähe von "Table" anstelle von "Domains" erstellt werden und "SerialNumber.from (CurrentSerialNumber)" anstelle von "CurrentSerialNumber.toSerialNumber ()" sein. Wenn Sie es mit "to" generieren, hängt "Domains" von "Table" ab, und "Domains" ermöglichen die Verwendung von "SerialNumber".

Fall 2 Aktualisieren Sie den Status einer Klasse

Angenommen, es gibt ein Mitgliederverwaltungssystem, das Mitgliederabhebungen akzeptiert. Stellen Sie beim Austritt aus der Mitgliedschaft den Status als zurückgezogen ein und geben Sie das leere Rücktrittsdatum ein, um den Status zu aktualisieren.

Klassen und Implementierungen

user_1.png Es ist schwierig, sich der Konsistenz von "Status" bewusst zu sein, und "0..1" ist sehr anfällig für Ausführungsausnahmen.

user_3.png Ich weiß nicht, welches ** Mitglied ich von find (id) bekommen habe, also überprüfe ich es.

Selbst wenn der Mitgliedsstatus zurückgezogen und dauerhaft gemacht wird, wird danach etwas, das nicht zurückgezogen wird, dauerhaft, wenn die Einstellung falsch ist.

Refactor

user_2.png Wenn ein solches Zustandsaktualisierungssystem für jeden Staat in eine andere Klasse eingeteilt wird, kann eine beträchtliche Anzahl von Landminen beseitigt werden.

"Nicht abonnierte Mitglieder" können nur aus "in Gebrauch befindlichen Mitgliedern" erstellt werden, "in Gebrauch befindliche Mitglieder" haben nicht immer ein Widerrufsdatum und "zurückgezogene Mitglieder" haben immer ein Widerrufsdatum.

user_4.png Sie können darauf vertrauen, dass das Ergebnis von "find (id)" ein "Mitglied in Verwendung" ist. (Natürlich ist Table stattdessen für die Prüfung verantwortlich)

Da "Table.unSubscribe ()" nur eine Methode zum Abbestellen ist, muss "Status.UnSubscribe" nicht mehr übergeben werden, und der Einstellungswert für die Systemfreundlichkeit stammt nicht mehr von "Domains".

tatsächlich

Es gibt verschiedene Situationen wie Antragstellung, Änderung der Vertragsform, Nichtzahlung von Gebühren, Einfrieren usw., und nicht nur Mitglieder, sondern auch verschiedene Klassen können nicht ohne Management auskommen. Wenn Sie versuchen, alle Zustände ordnungsgemäß nur mit dem Einstellungswert in derselben Klasse zu verwenden, ist dies so schmerzhaft, dass die Ausführungsausnahme stirbt, da sie mit der Inkonsistenzprüfung des Einstellwerts und der Prüfung "Optional" abgedeckt ist.

Selbst wenn ich eine getippte Sprache verwende, kann ich nicht zuerst kompilieren, also habe ich das Gefühl, welche Sprache ich schreibe ... ??

Hier gibt es verschiedene Designs, und angesichts des Eventdesigns wird es zu lang sein, also habe ich es gerade vorgestellt. (Eher studiere ich noch Eventdesign ...)

Fall 3 Haben Sie eine gemeinsame Elternklasse

Angenommen, alle Benutzeroperationen müssen als Operationsverlauf aufgezeichnet werden. Wenn Sie einen Kauf tätigen, speichern Sie den Verlauf der Kaufanwendung. Wenn abgebrochen, aktualisieren Sie den Anwendungsverlauf auf storniert und erstellen Sie einen Abbruchvorgang.

Operation Anwendungsverlauf Stornierungsgeschichte
Anwenden Tun können nicht existieren
Stornieren Auf storniert aktualisiert Tun können

Es ist kompliziert, aber es sieht so aus.

Klassen und Implementierungen

operation_1.png Da "Anwendung" und "Stornierung" unterschiedlich behandelt werden, werden die Klassen getrennt. Es ist jedoch auch zweckmäßig, sie für allgemeine Zwecke als Operationsverlauf zu behandeln. Dies ist beispielsweise ein Beispiel für das Erstellen einer übergeordneten Klasse.

operation_3.png Da dies kompliziert ist, gibt es viele Einstellwerte, und da alles als ".save ()" gespeichert ist, besteht die Möglichkeit, dass der Wert und die Häufigkeit falsch sind.

Refactor

operation_2.png Um die Anwendung und den Abbruch beim Kompilieren beim Verlassen der gemeinsamen Klasse korrekt zu behandeln, scheint es gut, die übergeordnete Klasse zu trennen.

operation_4.png Wenn Sie eine dedizierte Methode wie die Auszahlung verwenden, können Sie den eingestellten Wert fast eliminieren. Durch Ändern von ".save ()" in ".cancel (angewendet, abgebrochen)" können Sie die beiden immer korrekt aktualisieren.

tatsächlich

Schließlich fällt der Operationsverlauf ab, um abzubrechen oder abzuschließen. Nach der Bewerbung können Sie es verwenden, nachdem Sie bestätigt haben, dass es angekommen ist. Der Grund für die Erstellung eines separaten Stornierungsverlaufs besteht darin, dass von nun an Rückerstattungen akzeptiert werden müssen und die Stornierung abgeschlossen ist, wenn die erforderliche Verarbeitung abgeschlossen ist.

In Bezug auf das Bild sieht die endgültige Form so aus.

Operation Anwendungsverlauf Stornierungsgeschichte
Anwenden Tun können nicht existieren
Erreichen Komplett nicht existieren
Stornieren Auf storniert aktualisiert Tun können
Rückerstattung Bleibt storniert Komplett

Grundsätzlich liegt es in dieser Form vor, es gibt jedoch ebenso viele Betriebsverläufe wie Dienste, z. B. das Aktualisieren der Mitgliederinformationen und den Kauf zusätzlicher Geräte.

Es ist äußerst schwierig, diese jedes Mal korrekt zu aktualisieren, daher möchte ich die Kompilierungsleistung erhalten, während ich einige übergeordnete Klassen vorbereite.

Zusammenfassung

Grundlegende Richtlinien

Ein Zeichen, das gefährlich zu sein scheint

Bewältigung

Was als Grundhaltung zu tun

So ähnlich.

Recommended Posts

Es fühlt sich gut an, unterschiedliche Klassen für dieselben Tabellenwerte zu haben
Was Java-Ingenieure benötigen, um sich auf die Java 11-Version vorzubereiten
Ich möchte mehrere Rückgabewerte für das eingegebene Argument zurückgeben
"Warten Sie, bis der Prozess abgeschlossen ist" und beenden Sie den Prozess, da er bestehen bleibt