Lorsque je recherche une conception axée sur le domaine, je vois parfois des histoires de création de ValueObjects dans toutes les colonnes d'une base de données, ou de création de ValueObjects qui n'ont pas de méthodes simplement en entrant des valeurs. Je pense que c'est le résultat d'une trop grande conscience de la définition de ValueObject comme «immuable, échangeable et équivalent en tant que valeur». Mettant de côté une telle définition, je voudrais dire dans cette entrée que l'idée de "N'y a-t-il pas une valeur pratique s'il y a une méthode?" Peut trouver le ValueObject qui est vraiment nécessaire.
Avant d'entrer dans le sujet principal, il est plus facile de trouver ValueObject si vous savez quelles méthodes sont utiles, alors parlons-en. Je trouve quatre modèles d'objets de valeur.
Créez une méthode de jugement en enveloppant la valeur de code, etc.
Exemple de code [^ 1] [^ 2] avec le code d'état HTTP comme sujet et objet de valeur.
[^ 1]: Puisqu'il s'agit d'un exemple de code, il s'agit d'un jugement de code d'état approximatif.
[^ 2]: J'utilise attr_accessor, mais si vous craignez que l'immuabilité soit altérée, vous pouvez la rendre privée ou la changer pour faire référence à des variables d'instance.
http_status_code_value_object.rb
class HttpStatusCodeValueObject
attr_accessor :status_code
def initialize(status_code)
self.status_code = status_code
end
#2xx Code d'état de réussite de réussite
def success?
200 <= status_code && status_code < 300
end
end
Je pense que Ruby et Rails le font souvent en étendant le type standard. Vous pouvez écrire valeur% 2 == 1
comme value.odd?
.
En supposant que vous créez un site EC, la date de livraison estimée est calculée comme suit: «date de commande + temps de travail à expédier + délai de livraison de l'entrepôt au client». Cependant, il existe une plage de «temps de travail pour expédier» et de «délai de livraison de l'entrepôt au client», de sorte que le code ressemble à ceci.
order_date = Date.parse('2020-01-01')
work_days = 0..1 #Le temps de travail avant l'expédition est dans 1 jour
delivery_days = 1..2 #Le délai de livraison de l'entrepôt au client est de 1 à 2 jours
#Je suis heureux d'écrire ceci, mais j'obtiens une erreur
#Date de commande+Temps de travail pour expédier+Délai de livraison de l'entrepôt au client
# order_date + work_days + delivery_days
#Réalité sévère
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
Alors, créez une classe en tant que ValueObject qui peut calculer la plage de dates.
date_range_value_object.rb
class DateRangeValueObject
attr_accessor :from, :to
def initialize(from, to = nil)
self.from = from
self.to = to || from
end
#Seul l'addition est définie car aucun autre opérateur n'est requis
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
#Exporter vers des valeurs primitives
def to_range
from..to
end
end
Cette classe facilite l'écriture des calculs.
value_object = DateRangeValueObject.new(order_date)
value_object += work_days
value_object += delivery_days
value_object.to_range
Je pense que c'est aussi quelque chose que Ruby et Rails font souvent en étendant les types standard.
Il est courant de vérifier la valeur et de lever une exception si une valeur étrange entre. Parfois, vous pouvez renvoyer le résultat d'un échec, sinon jusqu'à ce que vous lanciez une exception.
La personne qui lève une exception est comme lorsqu'une devise qui n'existe pas est spécifiée dans le calcul de l'argent, et si vous faites un modèle Money [^ 3], je pense que vous ferez une exception si c'est une devise invalide dans le constructeur. J'appelle ces objets de valeur des objets de valeur sensibles. [^ 3]: Un modèle célèbre comme objet de valeur pour l'argent Je pense que les objets de valeur qui apparaissent dans «Introduction à la conception pilotée par domaine» de M. Masanobu Naruse sont essentiellement des objets de valeur sensibles. [^ 4]
[^ 4]: Je ne l'ai pas lu correctement, donc je suis désolé si c'est différent ...
Le cas où vous pouvez renvoyer le résultat d'un échec est celui où le ValueObject de l'encapsuleur spécifie une valeur inattendue. J'ai écrit la classe HttpStatusCodeValueObject
dans l'exemple de code du wrapper ValueObject, mais cela fonctionne bien même si -1
est spécifié pour status_code
. Ceci est similaire à l'opération pour "NaN" dans le calcul en virgule flottante minoritaire et "NULL" dans RDB. Vous pouvez également l'utiliser pour la validation des entrées utilisateur en créant une méthode valide?
Qui vérifie si une valeur valide est spécifiée.
J'appelle ces objets de valeur des objets de valeur insensibles.
Il est sensible car il réagit dès qu'une valeur invalide entre, et il est insensible car il n'est pas remarqué tant que «valide?» Est appelé.
Une technique pour trouver ce dont vous avez besoin est de tout mettre sur votre bureau, puis de retirer ce dont vous n'avez pas besoin. C'est un moyen facile à comprendre de terminer sans rien manquer. Vous pouvez également utiliser cette méthode lors de la recherche d'un ValueObject.
Tout d'abord, regardez la user story et l'écran sur lesquels vous travaillez, et notez les données utilisées dans le Bloc-notes. À partir de là, nous supprimerons les valeurs qui ne sont que des entrées et des sorties.
Même si le nom d'utilisateur est requis, il y a des cas où il est préférable de le laisser au processus de validation du framework sans créer un ValueObject sensible. [Varidata personnalisées](https://railsguides.jp/active_record_validations.html#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%] même dans des cas complexes tels que les numéros de téléphone 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) peuvent être utilisés.
Posez une question sur les valeurs restantes.
[^ 5]: pas une seule valeur, mais plusieurs valeurs peuvent être utilisées comme un ensemble
Si oui dans les deux cas, créez un ValueObject. En plus de cela, je pense que la propriété en tant qu'objet de valeur peut être créée si nécessaire.
Remarque: pour les langues à typage statique, notation hongroise ([Application en hongrois](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%B3%E3%82%AC%E3%83] % 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% Je pense qu'il est normal de créer un ValueObject sans méthode afin de réaliser E3% 82% A2% E3% 83% B3)) avec un type.
Cette entrée concerne le dictionnaire de données (https://linyclar.github.io/software_development/requirements_analysis_driven_desgin/#%E3%83/) dans la conception axée sur l'analyse des exigences (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) a été réorganisé et réécrit en contenu général. C'est une longue histoire, mais c'est une histoire de choses de type DDD dans Rails.
Recommended Posts