[RUBY] Suchen Sie einen geeigneten Wert für eine Methode und machen Sie sie zu einem ValueObject

Wenn ich nach domänengesteuertem Design recherchiere, sehe ich manchmal Geschichten über das Erstellen von ValueObjects in allen Spalten einer Datenbank oder das Erstellen von ValueObjects, die keine Methoden haben, nur durch Eingabe von Werten. Ich denke, dies ist das Ergebnis eines übermäßigen Bewusstseins für die Definition von ValueObject als "unveränderlich, austauschbar und gleichwertig als Wert". Abgesehen von einer solchen Definition möchte ich in diesem Eintrag sagen, dass die Idee "Gibt es keinen geeigneten Wert, wenn es eine Methode gibt?" Das ValueObject finden kann, das wirklich benötigt wird.

Wert Objektmuster

Bevor wir zum Hauptthema kommen, ist es einfacher, ValueObject zu finden, wenn Sie wissen, welche Methoden nützlich sind. Lassen Sie uns darüber sprechen. Ich finde vier Wertobjektmuster.

Wrapper ValueObject

Erstellen Sie eine Beurteilungsmethode, indem Sie den Codewert usw. einschließen.

Codebeispiel [^ 1] [^ 2] mit HTTP-Statuscode als Betreff und Wertobjekt.

[^ 1]: Da es sich um einen Beispielcode handelt, handelt es sich um eine grobe Beurteilung des Statuscodes.

[^ 2]: Ich verwende attr_accessor, aber wenn Sie befürchten, dass die Unveränderlichkeit beeinträchtigt wird, können Sie es privat machen oder ändern, um auf Instanzvariablen zu verweisen.

http_status_code_value_object.rb


class HttpStatusCodeValueObject
  attr_accessor :status_code
  def initialize(status_code)
    self.status_code = status_code
  end

  #2xx Erfolg Erfolgsstatuscode
  def success?
    200 <= status_code && status_code < 300
  end
end

Ich denke, dass Ruby und Rails dies oft tun, indem sie den Standardtyp erweitern. Sie können value% 2 == 1 als value.odd? Schreiben.

Berechenbares ValueObject

Angenommen, Sie erstellen eine EC-Site, wird der geschätzte Liefertermin als "Bestelldatum + Arbeitszeit bis zum Versand + Lieferzeit vom Lager zum Kunden" berechnet. Es gibt jedoch eine Reihe von "Arbeitszeit bis zum Versand" und "Lieferzeit vom Lager zum Kunden", sodass der Code so aussieht.

order_date = Date.parse('2020-01-01')
work_days = 0..1 #Die Arbeitszeit vor dem Versand beträgt 1 Tag
delivery_days = 1..2 #Die Lieferzeit vom Lager zum Kunden beträgt 1-2 Tage
#Ich schreibe das gerne, bekomme aber eine Fehlermeldung
#Bestelldatum+Arbeitszeit zum Versand+Lieferzeit vom Lager zum Kunden
# order_date + work_days       + delivery_days

#Schwere Realität
delivery_date_from = order_date
delivery_date_to = order_date
delivery_date_from += work_days.first
delivery_date_to += work_days.last
delivery_date_from += delivery_days.first
delivery_date_to += delivery_days.last

Erstellen Sie also eine Klasse als ValueObject, die den Datumsbereich berechnen kann.

date_range_value_object.rb


class DateRangeValueObject
  attr_accessor :from, :to
  def initialize(from, to = nil)
    self.from = from
    self.to = to || from
  end

  #Es wird nur die Addition definiert, da kein anderer Operator erforderlich ist
  def +(other)
    other_from = other
    other_to = other
    if other.is_a?(Range)
      other_from = other.first
      other_to = other.last
    end
    self.class.new(from + other_from, to + other_to)
  end

  #In primitive Werte exportieren
  def to_range
    from..to
  end
end

Diese Klasse erleichtert das Schreiben von Berechnungen.

value_object = DateRangeValueObject.new(order_date)
value_object += work_days
value_object += delivery_days
value_object.to_range

Ich denke, dies ist auch etwas, was Ruby und Rails oft tun, indem sie Standardtypen erweitern.

Sensitive ValueObject und Insensitive ValueObject

Es ist üblich, den Wert zu überprüfen und eine Ausnahme auszulösen, wenn ein seltsamer Wert eingeht. Manchmal können Sie das Ergebnis eines Fehlers zurückgeben, wenn nicht, bis Sie eine Ausnahme auslösen.

Die Person, die eine Ausnahme auslöst, ist, wenn bei der Berechnung des Geldes eine nicht existierende Währung angegeben wird, und wenn Sie ein Geldmuster erstellen [^ 3], werden Sie meiner Meinung nach eine Ausnahme machen, wenn es sich um eine ungültige Währung im Konstruktor handelt. Ich nenne diese Wertobjekte sensible Wertobjekte. [^ 3]: Ein berühmtes Muster als Wertobjekt für Geld Ich denke, dass die Wertobjekte, die in Mr. Masanori Naruses "Einführung in das domänengesteuerte Design" erscheinen, grundsätzlich sensible Wertobjekte sind. [^ 4]

[^ 4]: Ich habe es nicht richtig gelesen, es tut mir leid, wenn es anders ist ...

Der Fall, in dem Sie das Ergebnis eines Fehlers zurückgeben können, ist, wenn der Wrapper ValueObject einen unerwarteten Wert angibt. Ich habe die Klasse "HttpStatusCodeValueObject" im Codebeispiel des Wrappers ValueObject geschrieben, aber sie funktioniert auch dann einwandfrei, wenn "-1" für "status_code" angegeben ist. Dies ähnelt der Operation für "NaN" bei der Berechnung von Gleitminderwertpunkten und "NULL" bei RDB. Sie können es auch zur Validierung von Benutzereingaben verwenden, indem Sie eine "valid?" - Methode erstellen, die prüft, ob ein gültiger Wert angegeben ist. Ich nenne diese Wertobjekte unempfindliche Wertobjekte. Es ist empfindlich, weil es reagiert, sobald ein ungültiger Wert eingeht, und es ist unempfindlich, weil es erst bemerkt wird, wenn "gültig" aufgerufen wird.

Denken Sie: "Gibt es keinen geeigneten Wert, wenn es eine Methode gibt?"

Eine Technik, um herauszufinden, was Sie brauchen, besteht darin, alles auf Ihren Schreibtisch zu legen und dann das zu entfernen, was Sie nicht benötigen. Es ist ein leicht verständlicher Weg, um fertig zu werden, ohne etwas zu verpassen. Sie können diese Methode auch verwenden, wenn Sie ein ValueObject suchen.

Schauen Sie sich zunächst die User Story und den Bildschirm an, an denen Sie arbeiten, und notieren Sie sich die im Editor verwendeten Daten. Daraus entfernen wir die Werte, die nur eingegeben und ausgegeben werden.

Selbst wenn der Benutzername erforderlich ist, ist es in einigen Fällen besser, ihn dem Framework-Validierungsprozess zu überlassen, ohne ein vertrauliches ValueObject zu erstellen. [Benutzerdefinierte Varidaten](https://railsguides.jp/active_record_validations.html#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%] auch in komplizierten Fällen wie Telefonnummern A0% E3% 83% 90% E3% 83% AA% E3% 83% 87% E3% 83% BC% E3% 82% B7% E3% 83% A7% E3% 83% B3% E3% 82% 92% E5% AE% 9F% E8% A1% 8C% E3% 81% 99% E3% 82% 8B) können verwendet werden.

Stellen Sie eine Frage zu den verbleibenden Werten.

[^ 5]: Nicht nur ein Wert, sondern mehrere Werte können als Satz verwendet werden

Wenn ja, erstellen Sie in beiden Fällen ein ValueObject. Darüber hinaus denke ich, dass die Eigenschaft als Wertobjekt bei Bedarf erstellt werden kann.

Hinweis: Für statisch typisierte Sprachen ungarische Notation (Anwendung Ungarisch % AA% E3% 82% A2% E3% 83% B3% E8% A8% 98% E6% B3% 95 #% E3% 82% A2% E3% 83% 97% E3% 83% AA% E3% 82% B1% E3% 83% BC% E3% 82% B7% E3% 83% A7% E3% 83% B3% E3% 83% 8F% E3% 83% B3% E3% 82% AC% E3% 83% AA% Ich denke, es ist in Ordnung, ein ValueObject ohne eine Methode zu erstellen, um E3% 82% A2% E3% 83% B3)) mit einem Typ zu realisieren.


Dieser Eintrag bezieht sich auf das Datenwörterbuch (https://linyclar.github.io/software_development/requirements_analysis_driven_desgin/#%E3%83/) in Requirements Analysis Driven Design (https://linyclar.github.io/software_development/requirements_analysis_driven_desgin). % 87% E3% 83% BC% E3% 82% BF% E3% 83% 87% E3% 82% A3% E3% 82% AF% E3% 82% B7% E3% 83% A7% E3% 83% 8A % E3% 83% AA) wurde neu organisiert und in allgemeine Inhalte umgeschrieben. Es ist eine lange Geschichte, aber es ist eine Geschichte über DDD-ähnliche Dinge in Rails.

Recommended Posts

Suchen Sie einen geeigneten Wert für eine Methode und machen Sie sie zu einem ValueObject
So erstellen Sie eine bequeme Methode, die Generika und eine funktionale Schnittstelle verwendet
Wenn Sie eine Java-Anwendung in ein Docker-Image verwandeln möchten, ist es praktisch, Jib zu verwenden.
So identifizieren Sie den Pfad, auf dem leicht Fehler gemacht werden können
Eine Geschichte, die es Kotlin bequem machte, dass es mühsam ist, Animationen kontinuierlich auf Android auszuführen
So testen Sie eine private Methode und verspotten sie teilweise in Java
Shell-Skript, das ein Docker-Image erstellt und an ECR weiterleitet
JVM-Leistungsoptimierung: Was ist Optimierung und wie erstellt man einen guten Plan?
Eine einfache und bequeme Methode für HashMap
So konvertieren Sie einen Wert eines anderen Typs und weisen ihn einer anderen Variablen zu
Code, der schwer zu debuggen und zu analysieren ist
Eine Funktion, die nur einmal angezeigt wird, während Alert ausgeführt wird, und nie wieder angezeigt wird
Wie erstelle ich ein Vagrant Plugin, das Sie gelernt haben, als Sie Vagrant-Mutagen gegabelt und veröffentlicht haben?
Übergeben Sie ein Argument an die Methode und erhalten Sie das Ergebnis der Operation als Rückgabewert
Eine Lösung, die es einfach macht, Vor- und Nachteile sowie Webtests einzugeben, um die Ergebnisse zu überprüfen
[Docker] Ist es gut genug, um es als mehrstufigen Build zu bezeichnen? → Die Geschichte, die so gut wurde
Session war ein Cookie, das beim Schließen des Browsers gelöscht werden sollte, und eine Methode zum Austauschen: Rails Tutorial Hinweis - Was ist eine Rails-Sitzung?
Für Sie, die beklagen, dass Javas Hauptmethode statisch ist
Weisen Sie Variablen Java8-Lambda-Ausdrücke zu und verwenden Sie sie erneut
Verwechseln Sie Docker mit Pokemon und erleichtern Sie das Anhängen
Ich möchte eine Liste mit Kotlin und Java erstellen!
Ich möchte eine Methode aufrufen und die Nummer zählen
Ich möchte eine Funktion mit Kotlin und Java erstellen!
Suchen Sie eine Switch-Anweisung, die in einen Switch-Ausdruck konvertiert werden kann
Ich bin froh, eine Methode zu haben, um Zeichen auf Android zu blinken
Erstellen Sie eine Spring Boot-Webanwendung, die IBM Cloudant verwendet, und stellen Sie sie in Cloud Foundry bereit