2017-07-05 1 views
1

Je suis en train de développer un panier en php à la suite de POO et de DDD. J'ai une classe ShoppingCart agissant comme collection pour différents types d'instances CartItem (Type1ProductItem, Type2ProductItem, etc.), toutes implémentant une CartItemInterface.POO - gérer un identifiant unique dans une collection

Qu'en est-il de la meilleure façon de gérer l'identifiant unique à utiliser comme clé dans la collection interne de la Boutique?

Ma solution actuelle est une méthode "getPrimaryKey()" dans CartItemInterface retournant un identifiant unique basé sur le type et id:

ShoppingCart:

public function add(CartItemInterface $CartItem) { 
    $this->items[$CartItem->getPrimaryKey()] = $CartItem; 
} 
public function remove(CartItemInterface $CartItem) { 
    unset($this->items[$CartItem->getPrimaryKey()]); 
} 

résultant en:

ShoppingCart->add($CartItem); 
ShoppingCart->doSomething($CartItem); 

Mais de cette façon, je dois créer un CartItem avant chaque action sur le chariot (ajouter, supprimer, mettre à jour ..), en fonction des paramètres de l'uri, et ensuite le passer à la méthode appropriée de ShoppingCart:

// type and id coming as parameters 
switch ($type) { 
    case 1 : $CartItem = new Type1ProductItem($id); break; 
    case 2 : $CartItem = new Type2ProductItem($id); break; 
    .... 
} 
ShoppingCart->doSomething($CartItem); 

Ce n'est pas un grand problème que je peux utiliser une usine pour éviter la logique dupliquée, mais il sera une solution plus réalisable si l'identifiant unique (UID) a été créé en dehors des instances de CartItem et passé à ShoppingCart la première fois qu'un article est ajouté?

ShoppingCart->add($UID, CartItemInterface $CartItem); 
ShoppingCart->doSomething($UID); // no need of CartItem instance here 

Je ne sais pas si c'est bien que l'UID soit géré en dehors des instances de CartItem. Que pensez-vous? Quels sont les avantages et les inconvénients des solutions? Merci beaucoup.

+1

Passez le '$ UID' à l'usine. Il devrait l'utiliser pour initialiser le champ 'PK' des objets' CartItemInterface' qu'il crée. Ne modifiez pas l'interface du 'ShoppingCart'. – axiac

+0

Pourquoi avez-vous besoin de passer un 'CartItemInterface' à' add'? Pourquoi ne transmettez-vous pas les propriétés nécessaires telles que productId, productType, quantity et price? –

+0

Je pense que vous n'avez pas besoin de la clé primaire cartItem à l'intérieur de la classe shoppingCart. Pourquoi ne pas simplement faire $ this-> items [] = $ CartItem; Je pense que le cartItem devrait être un objet de valeur puisqu'il s'agit juste d'une description d'un élément et non de l'élément lui-même. Donc, il n'a pas vraiment besoin d'un ID –

Répondre

2

En général, il n'est pas recommandé de passer des objets mutables à l'instance d'un agrégat en raison du risque de mutation de l'agrégat en dehors de ses propres méthodes. Vous pouvez passer des objets mais ils doivent être immuables, comme les objets de valeur.

Dans votre cas, si CartItemInterface sont des objets mutables, cela n'est pas une bonne chose. Vous devez les rendre immuables (donc des objets de valeur) ou de ne pas transmettre eux, mais passer leurs propriétés à la place (et les propriétés doivent aussi être immuable), comme ceci:

public function addItemToCart($productId, $productType, $quantity, $price) 

Ensuite, si vous avez besoin de faire quelque chose un article de panier, par exemple pour changer la quantité, puis passez l'identifiant d'article de panier à la méthode ShoppingCart (la méthode Agréger). Cet identifiant proviendrait du ShoppingCart Agréger lui-même, lorsque vous affichez les éléments de panier à l'utilisateur et ne doit pas nécessairement être GUID ou autre chose globalement unique, il doit être unique uniquement dans l'agrégat, donc même un index basé sur zéro suffirait. De cette façon, l'agrégat décide lui-même comment identifier ses articles de chariot, l'agrégat est responsable, l'agrégat est l'autorité quand il vient à ses propres articles de chariot et l'agrégat peut changer ceci à tout moment sans "demander" la permission d'autres parties du système. Par exemple, si vous devez supprimer un élément du panier vous comme ceci:

public function remove($cartItemIndex) { 
    unset($this->items[cartItemIndex]); 
} 

Parce que vous avez dit (dans les commentaires) que vous avez besoin d'un comportement à l'intérieur des articles de panier, je recommande de les fabriquer des objets de valeur (donc immuable) et vous pouvez ensuite les passer quand vous en avez besoin (c'est-à-dire en affichant le chariot à l'utilisateur sans avoir besoin de créer une classe DTO locale supplémentaire).

+0

Merci beaucoup pour votre effort, sûr que je suis beaucoup moins expérimenté que vous :-). J'apprécie vos suggestions, elles vont même au-delà de la portée de la question. Encore une fois, merci. –

+0

J'ai essayé de partager une partie de mon expérience concernant les agrégats car ils sont très importants. –