aspose file tools*
The moose likes OO, Patterns, UML and Refactoring and the fly likes Confused about Domain Model Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "Confused about Domain Model" Watch "Confused about Domain Model" New topic
Author

Confused about Domain Model

Chandra Sekar
Ranch Hand

Joined: Apr 12, 2006
Posts: 94
Hi,

I have been trying to understand Domain model as described in P of EAA. If I write a service using the domain model, where domain objects also have domain logic (as described in Martin Fowlers article on anaemic domain model), then the service will have to return the domain objects to the client. Now that means the client can as well invoke the domain logic present within the objects right? How do we avoid this?


Chandru
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
What would be wrong with a client being able to do that?


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Chandra Sekar
Ranch Hand

Joined: Apr 12, 2006
Posts: 94
Originally posted by Ilja Preuss:
What would be wrong with a client being able to do that?


I'm quite new to this. But wouldn't it be problem if say a sequence of methods on BOs are to be invoked within a single transaction? If client can access the same methods, it might invoke it directly.
Chandra Sekar
Ranch Hand

Joined: Apr 12, 2006
Posts: 94
So do you suggest that exposing BOs' domain logic methods to the client is fine?
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
I would say it depends on how separate your client and your server are and how well the service implements a complete Domain Model.

It sounds like in your example you have a rather fine grained object model in the service, with some business logic living in the objects. However you have the service itself providing the transaction assurances needed. To me this would be a sign that either
a) the service layer isn't implementing a complete Domain Model
or
b) the client and service have legitimately different Domain Models

If your client and service are remote and highly decoupled, then I would guess (b) is more likely. Which, to me, might lead to needing some form of domain translating -- either DTOS, or an adapter, or a facade. If both sides share the same business logic, but not the same transactional nature, perhaps look at making the returned objects a read-only variant of the base class.

In the case of (a) I would expect that the client and the service are running within the same VM. If there are operations that always need to be paired with other updates, then the public API should expose something that does both things, and hide the lower level modifiers. Or if the lower level updates are sometimes used in isolation, and you're only worried about sometimes needing to wrap changes in transactions, look into the Command pattern for example to wrap these combined operations within a transaction.
Chandra Sekar
Ranch Hand

Joined: Apr 12, 2006
Posts: 94
Originally posted by Eric Nielsen:
In the case of (a) I would expect that the client and the service are running within the same VM. If there are operations that always need to be paired with other updates, then the public API should expose something that does both things, and hide the lower level modifiers. Or if the lower level updates are sometimes used in isolation, and you're only worried about sometimes needing to wrap changes in transactions, look into the Command pattern for example to wrap these combined operations within a transaction.

Thanks for the detailed explanation. My design falls in case (a). Would a design as below form a valid command pattern? I use Spring for injecting the DAOs into services. This is just a sample and not exactly the application code.

Book Entity

Customer Entity

Service Implementation

[ December 30, 2008: Message edited by: Chandra Sekar ]
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
I wouldn't consider that following the command pattern. As I would expect the service to have multiple methods. Normally in a command pattern each Command has one (sometimes two) public methods... normally a generic "execute" (and matching "undo" if two methods). So every operation would be its own class, not an exposed method on a service layer.

I would probably make the book.lendTo call also include the customer.assignBook call. Typically one side of a bidirectional relationship should take responsibility for updating both sides. Of course the service will still need to invoke the save on both daos (unless your persistence provider provides transitive persistence). This is the type of place where you almost want the "customer.assignBook" to be "private" to everyone aside from Book. sorta like C++'s friend methods, but that doesn't exist in Java.

Other possible refinements...
a) introduce a "LoanedBook" class that holds a Book, a Customer, and the return date, customer to it. Convert the book to a purely immutable class. Now Book is perfectly safe to return to any client code... You won't be able to ask a Book who has it -- you'll have to see "for this book, is there a checkout, if so, who has it?"

b) the constructor for LoanedBook, or the factory method returning a LoanedBook, would now contain all the logic about when a checkout is allowed, and what duration to set for the return. To me this would seem much cleaner than embedding that within the book, and the customer.
Chandra Sekar
Ranch Hand

Joined: Apr 12, 2006
Posts: 94
Originally posted by Eric Nielsen:

Other possible refinements...
a) introduce a "LoanedBook" class that holds a Book, a Customer, and the return date, customer to it. Convert the book to a purely immutable class. Now Book is perfectly safe to return to any client code... You won't be able to ask a Book who has it -- you'll have to see "for this book, is there a checkout, if so, who has it?"

b) the constructor for LoanedBook, or the factory method returning a LoanedBook, would now contain all the logic about when a checkout is allowed, and what duration to set for the return. To me this would seem much cleaner than embedding that within the book, and the customer.


Thanks for the awesome explanation and suggestions. While Book object as such cannot be made immutable as there would be CRUD operations editing its state, the idea of creating a LoanedBook class is interesting.

Is there any thumb rule to be followed when deciding between using a mapping class like this and putting the relationships directly within the entities?
[ December 31, 2008: Message edited by: Chandra Sekar ]
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
I think everyone will have their own rule of thumb, but to me:

If there is any information that belongs to the relationship and not to either end, that pushes me strongly to create the join entity.
(In your case, I say yes -- the due date is a property of the relationship, not the book nor the customer -- especially if you had to implement features regarding renewals as some libraries for instance provide progressive shorter renewal windows, or a maximum of one renewal. We would now have even more logic and state to hang off the LoanedBook class.)

If, when talking about the application your users would commonly use a name to refer to what the join entity represents,, that strongly pushes me to create the join entity.
(In this case "maybe" -- we don't talk about a "LoanedBook" in conversation. We might talk about the action of "Loaning" or "Checking Out", but I tend to avoid using a verb as a class. We might be able to name it the "DueDateSlip" which does have physical meaning to librarians... customers probably don't use that term, but probably would understand it. However it doesn't capture the "who" has the book aspect. And it doesn't track the state needed for renewal logic, if that's an issue.

Basically when working on a Domain Model, I would read up on Domain Driven Design. The books by Evans or Nilsson are wonderful at helping to explain these ideas.
Chandra Sekar
Ranch Hand

Joined: Apr 12, 2006
Posts: 94
That makes it pretty clear. I'd definitely look into the book(s) you suggested.

One last query, In case if I add a domain specific behavior to one of my mutable (used for CRUD operations in UI) entities, which would be invoked by my service but not relevant to client, is it a good idea to make the entity implement an interface which would expose only relevant operations to client? I felt this would help in solving my first query in this thread. But I don't know whether it is a good practice.
Eric Nielsen
Ranch Hand

Joined: Dec 14, 2004
Posts: 194
Yes, that's definitely an approach I've found useful at times.
Chandra Sekar
Ranch Hand

Joined: Apr 12, 2006
Posts: 94
Wow, what a quick response! Thanks a ton for all the time spent in solving my naive queries.
 
 
subject: Confused about Domain Model