views:

198

answers:

4

Let's say you have a domain entity User and you want to support the ability for a User to add an item to their shopping cart. Now, we want to make sure that the items in the shopping cart are unique, so we create the following function inside the User class:

function AddItemToCart(Item item)
{
    // Add business logic to make sure item is unique
}

This works great. But what if we now want to also e-mail the user whenever an item is added to their cart? We can add this into the AddItemToCart, but it would require injecting some sort of IEmailer dependency into the User class.

The alternative would be to create a service to handle this transaction (e.g. ShoppingCartService) which would perform the business logic and send out the e-mail. However, this leads to a rather anemic domain (i.e. the User class is nothing but getters/setters)

A: 

Keep the method as is, Then create a service class to handle the transaction. When the call is made to the service class method, then you can inject your emailing logic there.

Jobo
+1  A: 

"However, this leads to a rather anemic domain (i.e. the User class is nothing but getters/setters)"

The User isn't the whole domain.

You have Cart, Item, and sophisticated Cart.add() that puts Items into the Cart.

So what if the User class seems simplistic?

S.Lott
Then you shall have a simplistic User class....life goes on.
Jobo
+3  A: 

Logic that is part of the domain logic of the User should stay in the user. This may or may not involve injecting the User entity with a service. I think it depends on whether the service is part of the business logic of the User class, and whether doing this adheres to your ubiquitous language.

I would write this:

class ShoppingCartService
{
    private EmailService emailer;

    public void addItemToUserCart(User u, Item i)
    {
        u.addItemToCart(i);
        this.emailer.sendEmailTo(u, "Item " + i.toString() + " was added to your cart");
    }
}

This related question has discussion you might find helpful.

I'd also advise you to keep the getters and setters as restricted in scope as possible to reduce coupling.

moffdub
A: 

In large systems User-class would end up having lots of different kinds of operations. The class might get too big. To avoid that, there should be other classes that do things for the user.

Silvercode