Ich habe versucht, ein Wertobjekt aufgrund des domänengesteuerten Designs zu erstellen, aber es war ziemlich problematisch, daher habe ich eine übergeordnete Klasse erstellt. (Da es für die persönliche Entwicklung entwickelt wurde, um die Entwicklung zu beschleunigen, können wir nicht garantieren, dass es so verwendet werden kann, wie es im Produkt enthalten ist.)
https://qiita.com/kichion/items/151c6747f2f1a14305cc Es ist ein Objekt mit den in beschriebenen Eigenschaften.
Wenn Sie es in Ruby schreiben, ist es ein Objekt wie ↓. Dieses Beispiel ist ein Wertobjekt, das den Namen des Benutzers enthält. (Wenn Sie eine legitime Definition vornehmen möchten, ist es besser, etwas wie "gleich" zu definieren, aber ich verwende es nicht so oft, sodass ich es jetzt nicht definiert habe.)
domain/user/name.rb
module Domain::User
class Name
attr_reader :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
def update_first_name(first_name)
self.new(first_name, @last_name)
end
def update_last_name(last_name)
self.new(@first_name, last_name)
end
def fullname
"#{@last_name} #{@first_name}"
end
end
end
Es ist bequem zu bedienen, aber es ist mühsam, ein paar Zeilen mit Gettern und Setzern in dieses Routinefeld zu schreiben. Also habe ich eine übergeordnete Klasse erstellt, die diese willkürlich definiert.
domain/base/value_object.rb
module Domain::Base
class ValueObject
attr_reader :changed_fields
FIELDS = []
class << self
#Definieren Sie die folgende Methode neu_date = date.update_month(11)
def attr_updater(*attrs)
attrs.map(&:to_sym).each do |defining_attr|
define_method("update_#{defining_attr}") do |defining_value|
values = attrs.map { |attribute| attribute == defining_attr ? defining_value : instance_variable_get("@#{attribute}")}
changed_fields = @changed_fields.include?(defining_attr) ? @changed_fields : @changed_fields + [defining_attr]
self.class.new(*values, changed_fields: changed_fields)
end
end
end
end
# NOTE
# -Grundsätzlich werden auf der Wertobjektseite nur FELDER und Accessoren definiert.
# -Mit initialize kann der Elternteil diese Klasse von Dingen verwenden.
# -Es ist möglich, eine eigene Initialisierung zu implementieren. In diesem Fall wird jedoch nur die Initialisierung dieser übergeordneten Klasse von der Wertobjektseite verwendet, und der Benutzer des Wertobjekts darf die Initialisierung dieser Klasse nicht direkt verwenden.
# - changed_Änderungen wie Felder werden nur intern vorgenommen
# -Achten Sie darauf, die Initialisierungsargumente des Wertobjekts selbst so einfach wie möglich zu halten
def initialize(*field_values, fields: self.class::FIELDS, changed_fields: [])
define_fields(fields, field_values)
@changed_fields = changed_fields
end
private
def define_fields(fields, field_values)
fields.zip(field_values).each do |field, field_value|
instance_variable_set("@#{field}", field_value)
end
end
end
end
Auf diese Weise kann die ursprüngliche Methode durch die folgende Schreibmethode bereitgestellt werden.
domain/user/name.rb
module Domain::User
class Name < ::Domain::Base::ValueObject
FIELDS = %I(first_name last_name)
attr_reader *FIELDS
attr_updater*FIELDS
def fullname
"#{@last_name} #{@first_name}"
end
end
end
Bemerkungen
――Wenn Sie zu viel schwarze Magie der Metaprogrammierung verwenden, können Sie dieser nicht folgen (ob grep oder visuell), daher haben wir keine komplizierten Methoden definiert
――Sie können attr_reader
automatisieren, aber wenn Sie attr_reader
haben, wird der Leser nicht belastet, daher folge ich dem grundlegenden Ruby-Schreibstil.
――Diese Schreibweise gibt implizit an, dass die Argumente in der Reihenfolge eingegeben werden sollten, die zum Zeitpunkt der Initialisierung in FILED angegeben ist, und ich habe sie nicht angegeben, aber ich kenne das Problem selbst, also jetzt Es wird durch die Operation vermieden.
--changed_fields
wurde nach Ihren Wünschen erstellt, da ich nur die Felder aktualisieren wollte, die bei der Aktualisierung der Datenbank aktualisiert wurden.
Recommended Posts