views:

41

answers:

2

Considering architecture....

I normally have a shopping cart class with addItem and removeItem methods (amongst a couple of others). However in the spirit of real world shananigans carts should be acted on by customers - therefore should the addtoCart / removefromCart not be a method of the customer?

OR should I have an itermediate CustomerActsOnCart object that takes the customer and cart objects as arguments in the constructor and perform the manipulation in there???

Any musings would be most welcome...

+1  A: 

the way i see it... a Customer class and a Cart class have a 1x1 relation between each other, so you could put a reference of the Customer object in the Cart.. or put a Cart object inside the Customer, i'd say that it is better to use the second option cause it would be easier to get the current user and then you could do something like:

$current_user->getCart()->addtoCart()

and keep the addtoCart/removeItem methods inside the Cart object

hope it helps

pleasedontbelong
I think the 1:1 relationship is the key insight. In a real life suppermarket many customers use a single shopping cart, albeit serially. In a virtual shop like Amazon the ShoppingCart is an attribute of a single Customer. But a Customer has many different activities, so it is cleaner to keep the cart-related methods on the Cart.
APC
The 1:1 relationship seems overly restrictive. ---- What if multiple people want to share a shopping cart? (Family shopping for a birthday gift for someone). Or what if a customer wants multiple shopping carts (business shopping and personal shopping w different credit cards being done at the same time)?
Peter Ajtai
A 1 to 1 relationship is not a given. You could need a customer to have access to many carts or indeed many customers to access one cart - depending on your requirements. Shifting the add/removeto the actor is I think most logical way of modelling real world. Just MO ofcourse ;)
ToonMariner
yeap it depends on the requirements, anyway it always good to have the "traditional way" as a reference, because I have never seen a website where different accounts share the same Cart, in that case the relation would change to 1xN and i'd still keep the reference Cart in the Customer class.
pleasedontbelong
+1  A: 

Even if you give a Customer the methods addToCart() and removeFromCart(), you would still have to have some logic in ShoppingCart to have these methods actually do the state change when an item is added or removed. IMO, the actor in this case is much better represented by a reference to the owning Customer and/or viceversa, e.g.

$cart = new ShoppingCart;
$cart->setOwner(new Customer);
$cart->addItem(new Item('Apples'));
$cart->checkout();

You could approach this from the customer as well, e.g.

$customer = new Customer;
$customer->setShoppingCart(new ShoppingCart);
$customer->addItemToShoppingCart(new Item('Apples'));
$customer->checkout();

But the method name addItemToShoppingCart already implies that the Customer acts on a ShoppingCart, so inside you are likely doing

$this->getShoppingCart()->addItem($item);

If ShoppingCart was a composite element of Customer for which we wanted to hide implementation details, we could use something like that, but since the ShoppingCart is IMO not an essential part of a Customer this method shouldnt be on Customer. It's nothing but a convenience proxy.

You could create a Decorator for the Customer to handle the Shopping Behavior. This would decouple the concern/responsibility of How-To-Shop from the Customer, e.g. something like

class ShoppingDecorator
{
    protected $actor;
    protected $cart;
    protected function __construct($actor) { ... }
    public function getCart() { ... };
    public function addToCart() { ... }
    ...
}

This would also allow you to apply the Shopping Behavior to other actors that might need this behavior.

The CustomerActsOnCart approach sounds somewhat like the Mediator Pattern. Not sure if it's a feasible approach though.

Gordon
I like the first two illustrations of how one can think about this using a cart or a customer acting upon a cart. Really helps clear things up.
Peter Ajtai
actually think the mediator is perfect in this case...
ToonMariner