Je voudrais écrire une application quelque chose comme le commerce électronique.
Et vous savez que dans des applications similaires, les produits peuvent avoir des propriétés et des fonctionnalités différentes. Pour simuler une telle opportunité, j'ai créé les entités de modèle de domaine suivantes:
Catégorie - c'est quelque chose comme "électronique> ordinateurs", c'est-à-dire les types de produits. Les catégories contiennent une liste de propriétés (Liste <Propriété>).
Propriété - entité indépendante qui contient le nom, les unités de mesure et le type de données. Par exemple, "nom", "poids", "taille d'écran". La même propriété peut avoir différents produits.
Produit - contient uniquement le nom et la liste des valeurs relatives aux propriétés. La valeur est un objet qui contient uniquement le champ de valeur et l'ID de champ de la propriété.
J'ai initialement décidé de faire de la catégorie un seul agrégat dans ce schéma, car par exemple, lorsque j'ajoute un nouveau produit, j'ai besoin de connaître toutes les données liées à la catégorie actuelle, y compris les propriétés liées à la catégorie actuelle ( category.AddNewProduct (product) ). Mais que dois-je faire lorsque j'ai juste besoin d'ajouter une nouvelle propriété qui n'appartient à aucune catégorie. Par exemple, je ne peux pas faire cette catégorie.AddNewProperty (propriété) car cela dit clairement que nous ajoutons la propriété à une catégorie spécifique.
Ok, l'étape suivante, j'ai décidé de séparer la propriété en un agrégat distinct, mais ce sera une liste avec des entités simples.
Bien sûr, je peux créer quelque chose comme PropertyAggregate pour conserver la liste des propriétés et les règles commerciales, mais lorsque j'ajoute un produit, j'ai besoin d'avoir dans la catégorie la liste complète des propriétés appartenant à cette catégorie pour vérifier les invariants. Mais je suis également conscient que conserver les liens à l'intérieur de l'agrégat sur d'autres agrégats est une mauvaise pratique.
Quelles sont les options pour concevoir cette analyse de rentabilisation?
Réponses:
Dans la perspective DDD
Category
,Product
etProperty
sont des entités: elles correspondent toutes à des objets qui ont leur propre identité.Option 1: votre design original
Vous avez créé
Category
la racine d'un seul agrégat. D'un côté, cela a un sens, parce que l'ensemble assure la cohérence en cas de modifications de ses objets, etProduct
doit avoir leProperties
sonCategory
:Mais d'un autre côté, le seul agrégat signifie que tous ses objets sont liés à une racine qui les possède, et toutes les références externes doivent être faites via cette racine agrégée. Cela implique que:
Product
appartient à un et un seulCategory
. Si leCategory
est supprimé, il en sera de mêmeProducts
.Property
appartient à un seul et uniqueCategory
. Autrement dit, si "Écrans de télévision" et "Écrans d'ordinateur" seraient deux catégories, "Écrans de télévision: taille" et "Écrans d'ordinateur: taille" seraient deux propriétés différentes.Le deuxième point ne correspond pas à votre récit: " Mais que dois-je faire quand j'ai juste besoin d'ajouter un nouveau
Property
qui n'appartient à aucune catégorie ". Et il n'est pas clair si le mêmeProperties
peut être utilisé dans différentsCategories
.Option 2: propriété en dehors de l'agrégat
Si un
Property
existe indépendamment duCategories
, il doit être en dehors de l'agrégat. Et la même chose si vous souhaitez partagerProperties
entreCategories
(ce qui a du sens pour la hauteur, la largeur, les tailles, etc ...). Cela semble définitivement être le cas.La conséquence est sur le lien entre
Property
et les choses qui appartiennent à l'agrégat: alors que vous pouvez naviguer de l'intérieur de l'agrégat versProperty
, vous n'êtes plus autorisé à passer directement de aProperty
aux valeurs correspondantes. Cette restriction de navigabilité peut être représentée dans un diagramme UML:Notez que cette conception ne vous empêche pas d'avoir un
List<Property>
inCategory
, avec une sémantique de référence (par exemple java): chaque référence dans la liste fait référence à unProperty
objet partageable dans un référentiel.Le seul problème avec cette conception est que vous pouvez le modifier
Property
ou le supprimer: comme il est en dehors de l'agrégat, l'agrégat ne peut pas prendre soin de la cohérence de ses invariants. Mais ce n'est pas un problème. C'est la conséquence des principes DDD et de la complexité du monde réel. Voici une citation d'Eric Evans dans son livre fondateur " Domain-Driven Design: Tackling Complexity in the Heart of Software ":Donc oui, si vous modifiez un
Property
, vous devrez vous assurer qu'un service vérifie que les catégories qui s'y réfèrent sont mises à jour au besoin.Option 3: catégorie, propriété et produit dans différents agrégats
Je me demande simplement si l'hypothèse selon laquelle un
Product
appartient à un célibataireCategory
est fondée:Product
sous plusieursCategories
. Par exemple, vous trouverez "Laptop Brand X Model Y" dans la catégorie "Laptops" et la catégorie "Computers", et une "multifunction printer Z" dans la catégorie "printer", "scanner" and "fax".Product
première, puis l'attribue plus tard aux catégories et remplisse les valeurs?Cela ne simplifiera pas les agrégats et vous auriez encore plus de règles qui s'étendent sur les agrégats. Mais votre système serait beaucoup plus à l'épreuve du temps.
la source
Property
dépasse les limites de l'Category
agrégat, cela signifie-t-il que celaProperty
devient un agrégat en soi et a besoin d'un référentiel? Si c'est vrai, alors comment passer requisList<Property>
enCategory
instance? Par le constructeur? Ce sera vrai? Et comment puis-je trouver la liste desProperty
identifiants d'unCategory
qui n'a pas encore été créé?Feature
qui n'appartiendra qu'à laProduct
. et cette entité ne participera pas à la recherche. Que dis-tu ?À mon avis, vous pouvez résoudre ce problème de deux manières:
La catégorie est un type de produit spécial
Cela signifie que pour tout produit donné dans votre base de données, il contient une clé étrangère pointant vers le même produit de table. Un produit n'est un produit que s'il n'existe aucun produit dont la clé étrangère est égale à l'id dudit produit. En d'autres termes, s'il n'a aucun produit en dessous, c'est un produit.
Cela simplifierait un peu les choses. Les produits aux propriétés auraient une relation un-à-plusieurs et, par conséquent, vos catégories ont également une relation un-à-plusieurs car elles sont également des produits. Ajouter une propriété à une catégorie serait aussi simple que d'ajouter une propriété à un produit dans votre programme. Le chargement de toutes les propriétés impliquerait de combiner les propriétés du produit avec les propriétés de son produit de catégorie associé et ainsi de suite jusqu'à ce que vous atteigniez un produit de catégorie sans parent.
Votre application de commerce électronique devrait faire cette distinction, mais si vous êtes de toute façon susceptible de charger des produits d'une catégorie, ce n'est pas une perte de performances de savoir si vous avez affaire à une catégorie ou à un produit. Il se prête également bien à la recherche arborescente au niveau du produit, car chaque produit (catégorie) s'ouvrirait à une liste de sous-produits sans beaucoup de travail supplémentaire.
L'inconvénient est bien sûr que des informations supplémentaires présentes dans le produit qui n'ont pas de sens pour une catégorie créeraient des champs inutilisés maladroits dans le produit. Bien que cette solution soit plus flexible dans votre application, elle est également un peu moins intuitive.
Relation plusieurs à plusieurs
Les produits ne sont plus dans une relation composite avec la propriété. Vous créez une table ProductProperty avec des clés étrangères de la table de produit et de la table de propriétés qui lient les deux. De même, vous avez une table de catégories avec une relation plusieurs-à-plusieurs avec la table de propriétés et une table CategoryProperty avec des clés étrangères de la table des catégories et de la table des propriétés.
Le produit lui-même aurait une relation plusieurs-à-un avec la catégorie, vous permettant essentiellement de créer une liste de propriétés uniques se rapportant à la fois au produit et à la catégorie via une déclaration de sélection bien formalisée.
Du point de vue de la base de données, c'est définitivement plus propre et plus flexible. Votre application pourrait probablement faire la plupart du temps sans traiter directement avec CategoryProperty ou ProductProperty si la requête est effectuée correctement. Cependant, vous ne devez pas non plus considérer la catégorie ou le produit comme le propriétaire d'un bien. Il doit s'agir de sa propre entité au sein de votre programme. Cela signifie également que la gestion desdites propriétés consisterait à créer la propriété elle-même, puis à l'associer à une catégorie ou à un produit en deux étapes distinctes. Certes, plus de travail que la première solution, mais en aucun cas plus difficile.
En plus de cela, vous devrez également effectuer une vérification supplémentaire lors de la suppression de la catégorie ou du produit si l'une de ses propriétés est utilisée par d'autres (contrairement à la première solution où vous pouviez éliminer en toute sécurité toutes les propriétés associées d'un produit / catégorie donné) .
Conclusion
Dans un contexte professionnel, j'irais dans la catégorie mile supplémentaire et distance du produit et du produit de la propriété en utilisant l'approche plusieurs-à-plusieurs. Il n'y aurait aucune possibilité de chevauchement des données, et dans un sens, il est plus facile de raisonner chacun de ces trois en tant qu'entité propre. Cependant, la première solution n'est en aucun cas mauvaise, car elle vous permet également d'écrire une application plus simple. Sachez simplement que si vous pensiez que vous deviez éventuellement passer d'une solution à l'autre, il serait probablement dans votre intérêt de choisir la seconde.
Bonne chance!
la source