40 votes

Objets de valeur dans DDD - Pourquoi immuables ?

Je ne comprends pas pourquoi les objets de valeur dans DDD devraient être immuables, et je ne vois pas non plus comment cela est facilement réalisable. (Je me concentre sur C# et Entity Framework, si cela a de l'importance).

Par exemple, considérons l'objet classique de valeur Adresse. Si vous deviez changer "123 Main St" en "123 Main Rue "Pourquoi devrais-je construire un tout nouvel objet au lieu de dire myCustomer.Address.AddressLine1 = "123 Main Street" ? (Même si Entity Framework supportait les structs, ce serait toujours un problème, n'est-ce pas ?)

Je comprends (je pense) l'idée que les objets de valeur n'ont pas d'identité et font partie d'un objet de domaine, mais quelqu'un peut-il expliquer pourquoi l'immuabilité est une bonne chose ?


EDIT : Ma dernière question ici devrait vraiment être "Quelqu'un peut-il expliquer pourquoi l'immuabilité est une bonne chose" ? appliquée aux objets de valeur ?" Désolé pour la confusion !


EDIT : Pour clarifier, je ne pose pas de question sur les types de valeur CLR (vs les types de référence). Je m'interroge sur le concept DDD de niveau supérieur des Value Objects.

Par exemple, voici un moyen détourné d'implémenter des types de valeurs immuables pour Entity Framework : http://rogeralsing.com/2009/05/21/entity-framework-4-immutable-value-objects . En gros, il rend tous les régleurs privés. Pourquoi se donner la peine de faire ça ?

0 votes

Les types de valeur et de référence sont généralement mélangés, comme le montre votre question initiale en parlant du type de valeur Adresse (struct) et du type de référence Valeur de la propriété String (class). Y a-t-il un avantage à restreindre votre question aux seuls types de valeur ? Pouvez-vous l'ouvrir sans diluer votre intention ?

0 votes

Je ne suis pas sûr de comprendre. Je ne parle pas des types de valeurs CLR (structs, ints, etc.) par rapport aux types de référence (classes, etc.). Je parle du concept DDD de Value Objects (par opposition aux Entity Objects).

0 votes

J'ai parcouru la question, j'ai vu C# et mon esprit a sauté les contextes. Merci pour la clarification.

50voto

Roger Alsing Points 5542

Ignorez toutes les réponses farfelues sur la sécurité thread etc., cela n'a rien à voir avec DDD. (Je n'ai pas encore vu de mappeur O/R thread safe ou d'autre dal compatible avec DDD).

Imaginez un objet de valeur pour les poids. Disons que nous avons un objet de valeur KG.

échantillon (édité pour plus de clarté) :

var kg75 = new Weight(75);
joe.Weight = kg75;
jimmy.Weight = kg75;

Maintenant, que se passerait-il si nous le faisions :

jimmy.Weight.Value = 82;

Cela changerait aussi le poids de Joe, si nous utilisons toujours les mêmes références d'objets. Notez que nous avons assigné un objet représentant 75kg à la fois à joe et jimmy. Lorsque jimmy prend du poids, ce n'est pas l'objet kg75 qui a changé, c'est le poids de jimmys qui a changé, donc, nous devrions créer un nouvel objet représentant 82 kg.

Mais que se passe-t-il si nous avons une nouvelle session et que nous chargeons à la fois Joe et Jimmy dans un UoW propre ?

 var joe = context.People.Where(p => p.Name = "joe").First();
 var jimmy = context.People.Where(p => p.Name = "jimmy").First();
 jimmy.Weight.Value = 82;

Que se passerait-il alors ? Eh bien, puisque EF4 dans votre cas chargerait Joe et Jimmy et leurs poids sans aucune identité, nous obtiendrions deux objets de poids différents et lorsque nous changerions le poids de Jimmy, Joe aurait toujours le même poids qu'avant.

Nous aurions donc deux comportements différents pour le même code. si les références de l'obejct sont toujours les mêmes, alors Joe et Jimmy auront un nouveau poids. si joe et jimmy sont chargés dans un uow propre, seul l'un d'entre eux serait affecté par le changement.

Et ce serait assez incohérent, je pense.

En utilisant des VO immuables, vous obtiendrez le même comportement dans les deux cas et vous pourrez toujours réutiliser les références d'objets pour réduire l'empreinte mémoire lors de la construction des graphes d'objets.

5 votes

Cet argument est erroné. Vous défendez d'un point de vue technique quelque chose qui est choisi pour des raisons conceptuelles. Ces concepts d'objet de valeur et d'entité existent en dehors de toute implémentation spécifique.

3 votes

Cela couvre la raison pour laquelle nous avons besoin d'objets de valeur immuables, peu importe si vous utilisez une technologie spécifique ou autre, le poids de 75kg est immuable peu importe si vous utilisez EF4 ou toute autre technologie. si le poids d'une personne a changé, ce n'est pas l'objet représentant 75kg qui doit changer, vous devez attribuer un nouveau poids à cette personne à la place

7 votes

Se contenter d'évoquer les aspects théoriques ne permettra pas de comprendre pourquoi vous aurez des problèmes si vous ne tenez pas compte de ces aspects. Il est plus facile de comprendre pourquoi les concepts existent si vous pouvez voir pourquoi quelque chose échouerait dans un scénario plus concret.

41voto

Jason Points 125291

Pourquoi 6 est immuable ?

Comprenez cela, et vous comprendrez pourquoi les Value Objects doivent être immuables.

Edit : Je vais maintenant intégrer notre dialogue dans cette réponse.

6 est immuable car 6 L'identité d'une personne est déterminée par ce qu'elle représente, à savoir l'état d'avoir six de quelque chose. Vous ne pouvez pas changer ça 6 représente cela. C'est le concept fondamental des objets de valeur. Leur valeur est déterminée par leur état. Une Entité, cependant, n'est pas déterminée par son état. A Customer peuvent changer leur nom de famille, ou leur adresse et rester les mêmes. Customer . C'est pourquoi les Value Objects doivent être immuables. Leur état détermine leur identité ; si leur état change, leur identité doit changer.

2 votes

J'ai vu des exemples comme celui-ci, et ils semblent trop simplistes. 6 est immuable car, comme String, toute opération que vous effectuez sur lui vous donne un nouvel objet. 6+2 n'est pas le nombre six qui a été changé en huit ; c'est un nouveau nombre. Je comprends, mais je n'aime pas l'analogie. Dans le cas de Address, le type est plus complexe et il est plus difficile (et ridicule) de définir des opérations sur ce type qui renvoient un nouveau type. Par exemple, newAddress = oldAddress.ChangeLine1("123 Main Street") ?

1 votes

Tu n'y réfléchis pas assez attentivement. Vous pourrait créer un type qui imite int qui modifie effectivement l'objet lorsque vous invoquez une méthode au niveau de l'instance (appelez la classe Integer et, à titre d'exemple, une méthode au niveau de l'instance Increase qui accepte un paramètre de type Integer ). Pourquoi ne faisons-nous pas cela ? Pourquoi modélisons-nous les nombres comme des objets de valeur ?

0 votes

Mon Dieu, je ne sais pas. Il ne me viendrait même pas à l'esprit de faire autrement =) Peut-être me donner un indice ?

14voto

David Points 1280

J'interviens très tard dans la discussion, mais je me suis moi-même posé la question. (J'apprécierais tout commentaire).

Je ne pense pas que cela ait été explicitement cité ici, mais je pense que les références d'Evans à l'immuabilité étaient principalement dans le contexte du partage :

pour qu'un objet soit partagé en toute sécurité il doit être immuable : il ne peut être modifié que par un remplacement complet. (Evans p100)

Le livre d'Evan contient également un encadré intitulé "Is Address a Value Object ? Qui le demande ?

Si des colocataires appellent chacun pour commander un service d'électricité [c'est-à-dire si deux clients ont la même adresse], l'entreprise doit s'en rendre compte. doit s'en rendre compte. [L'adresse est donc une entité. (Evans p98)

Dans l'exemple que vous avez donné, supposons que l'adresse du domicile et l'adresse professionnelle du client soient toutes deux 123 Main Street. Lorsque vous effectuez la correction que vous décrivez, les deux adresses changent-elles ? Si c'est le cas, et si je lis correctement Evans, il semble que vous ayez vraiment une Entité.

Prenons un autre exemple, supposons que nous ayons un objet pour représenter le nom complet d'un client :

public class FullName
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Customer
{
    public FullName Name { get; set; }
}

Sans objet de valeur, l'opération suivante échouerait :

[Test]
public void SomeTest() {
    var fullname = new FullName { FirstName = "Alice", LastName = "Jones" };
    var customer1 = new Customer { Name = fullname };
    var customer2 = new Customer { Name = fullname };

    // Customer 1 gets married.
    customer1.Name.LastName = "Smith";

    // Presumably Customer 2 shouldn't get their name changed.
    // However the following will fail.
    Assert.AreEqual("Jones", customer2.Name.LastName);
}

En ce qui concerne les avantages en général, certains sont récupérés à Dans DDD, quels sont les avantages réels des objets de valeur ? . Notamment, il suffit de valider un VO à sa création. Si vous le faites, vous savez alors qu'il est toujours valide.

0 votes

Je vous remercie pour cela. L'explication d'Evan est instructive et votre exemple est vraiment convaincant.

0 votes

C'est de loin la réponse la plus simple et la meilleure. Elle utilise l'exemple de la question et montre pourquoi elle échouerait sans être une VO.

5voto

Pangea Points 36713

Ce n'est peut-être pas la réponse complète. Je réponds seulement à votre question sur les avantages de l'Immutabilité.

  1. Parce que les objets immuables sont sûrs. Puisqu'ils ne peuvent pas changer l'état, ils ne peuvent pas être corrompus par par des interférences entre fils ou observés dans dans un état incohérent.
  2. Les références aux objets immuables peuvent être facilement partagées ou facilement sans avoir à les copier ou à les les cloner, car leur état ne peut pas être modifié après leur construction.
  3. Pour plus d'avantages de l'Immutabilité vous regardez ici (réponse de LBushkin) Quel est l'avantage pour une chaîne de caractères d'être immuable ?

Voici un exemple par Martin Fowler sur les raisons pour lesquelles les objets de valeur devraient être immuables.

D'accord, bien qu'il ne soit pas obligatoire de rendre les VO immuables (même le livre DDD ne dit pas qu'ils doivent être immuables), l'idée principale, dans DDD, d'en faire un VO semble être de ne pas traiter les complexités du cycle de vie comme celui d'une Entité. Regardez ici pour plus de détails .

0 votes

Tout argument qui aborde la question d'un point de vue technique est erroné. Vous n'avez jamais utilisé une seule fois le fait que nous parlons ici d'objets de valeur. Votre analogie avec string est imparfaite puisque string est un type de référence. Votre argument porte en fait sur les avantages des types immuables, et non sur la raison pour laquelle les Value Objects devraient être immuables.

1 votes

L'objet de valeur n'est-il pas implicite ici ? D'ailleurs la question posée est "quelqu'un peut-il expliquer pourquoi l'immuabilité est une bonne chose". J'en viens maintenant au lien que j'ai fourni ; au lieu de copier les avantages textuellement, j'ai spécifié le lien qui parle des avantages de l'immuabilité. Alors pouvez-vous m'éclairer sur la raison pour laquelle Address n'est pas un type de référence.

0 votes

Pangea : Bon point. J'ai demandé "pourquoi l'immuabilité est une bonne chose", mais ce que je voulais vraiment dire est "pourquoi l'immuabilité est une bonne chose" pour les objets de valeur ? Je vais modifier ma question pour la rendre plus claire.

0voto

rhozet Points 318

Les objets de valeur doivent être immuables.

Les objets immuables simplifient effectivement la vie dans de nombreux cas. ... Et ils peuvent rendre la programmation concurrente beaucoup plus sûre et propre. pour plus d'informations

Considérons que l'objet valeur est mutable.

class Name{
string firstName,middleName,lastName
....
setters/getters
}

Disons que votre nom d'origine était Richard Thomas Cook

Supposons maintenant que vous ne modifiez que le prénom (en Martin) et le nom (en Bond), S'il ne s'agit pas d'un objet immuable, vous utiliserez les méthodes pour modifier l'état un par un. Les chances d'avoir le nom comme Martin Thomas Cuisinier dans cet état d'agrégation avant le nom définitif de Martin Thomas Bond n'est jamais acceptable (cela donne également une idée fausse à celui qui regarde le code plus tard, ce qui entraîne un effet domino indésirable dans la conception ultérieure).

Les objets à valeurs mutables doivent explicitement appliquer des contraintes d'intégrité pour les changements apportés au cours d'une transaction, ce qui est gratuit pour les objets immuables. Il est donc logique de rendre les objets de valeur immuables.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X