views:

146

answers:

2

Scenario:

In my application (which utilises an rich domain model, where the logic is in the model, not in the services) I have users. I create new users with a service

User newUser = userService.createNewUser("Hans Dampf");

or get them from the database

User oldUser = userDao.findByName("Hans Dampf");

Because in every call into my application I have direct access to an user object, I would like to use the user object as an entry point into my domain model.

Each user can have different types of Galleries, saved in an other table.

class User {
 @OneToMany(fetch = FetchType.LAZY)
 @JoinColumn(name = "userId")
 private Set<Gallery> automatic = new HashSet<Gallery>();
}

I want to have a simple way to enable a specific gallery. So my API would look like:

User user = ... // creating or retriving user
user.enableMainGallery();

Inside this method it would be necassary to create a new gallery object and add it to the list of galleries. But how to create this new instance? Using a factory? That would require to inject the factory into the domain object (may be problematic).

public void enableAutomaticGallery() {
    automatic.add(automaticFactory.createAutomaticGallery(this));
}

Or is my interface definition flawed? Should I define it in some other way, such that I don't have to inject the factory? How?

+1  A: 

As you say, the domain objects should not be made dependent on application-level objects such as factories or Daos.

The domain is typically :

  • complex-enough with the functional needs, without adding other concerns (such as persistence, validation, GUI etc...)
  • central and used everywhere (so it's complexity damages your productivity in many coding activities)
  • reusable across related applications, and in all layers, can even be serialized and send to a different JVM on a client or a WebService (unless it has dependencies on application-level objects)

So your enableAutomaticGallery method should be on a Service object. It can have the same code, but will be application-dependent.

KLE
But this would lead to an anemic domain model, wouldn't it? I would have to expose the collection of galleries and the logic would be outside the object. Or does I overlook something?
Arne
@Arne Balance is sometimes hard to find, I used to think strictly Object-Oriented as you do, and didn't want to separate concerns in several classes. But the Domain is so complex, so vitally important to understand by every developer, and so much code could get added by all concerns, that I found that impractical. Now my Domain is the center of my code, decorated with annotations (for Persistence, Validation etc...). Concerns are different codes, either in separate classes (DAO, Service, GUI-related) or technical codes (trigger validation).
KLE
The existence of a service layer doesn't make your domain model anemic. It's when all of the logic in your application ends up in services and your domain model contains only state that you've gone "anemic." Remember, the whole point of OO programming is to combine behavior (methods) and state (fields) into a single artifact, the class. But it's perfectly reasonable to have a service layer that helps coordinate activities between objects in the domain.
cliff.meyers
+1  A: 

Your domain model should know nothing about any service or DAO layers or even any factory objects.

I would suggest instead of a method User.enableMainGallery() which needs to add Gallery objects to the instance collection (as you've said), that you instead expose a method User.addGallery(Gallery).

This way, the classes responsible for "enabling the gallery" do so by adding objects to the list collection.

In other words, I don't believe that the User object should be responsible for knowing what it means to "enable a main gallery". This sounds like something that falls under the umbrealla of business logic (ambiguous term, I know).

matt b
This looks promising at first and seem to be a good answere. But does this scale well? I imagine to add a gallery of type "OldGallery" and have the requirement to upgrade this to "NewGallery". In my design this would lead to a method "User.upgradeGallery(x)" (I agree that the user class seem to have to many responsibilities). But if the user only manages the collection, then the logic is again outside the model!? I would have a "GalleryService" that removes the old gallery from the user and adds the new one!?
Arne
In my personal opinion, I don't think that a "domain model" should have the logic in it for things like "add a gallery for this user" or "upgrade old gallery to new gallery". Some people might call this "anemic" - I'm not really familiar with that argument. I prefer to have this logic in a separate layer so that the model can just be purely "the model".
matt b
Ok ... but then what kind of logic belongs into the model?
Arne
Your data, and the relationships between it.
matt b