Business Logic in Domain Objects?
One of the design principles of any enterprise application which I found difficult to make up my mind about is Anemic domain models + Service Objects Vs. Fully featured domain objects.
Most of my business application layer consists of many Service Objects (DAOs, Session Beans, BOs, Delegates, Facades etc) AND many POJO domain objects. Here the domain objects are nothing but data holders. There is no business logic in it. Arguably, this is an application of "separation of concerns", where business and/or data access logic is separated from data holders (in other words, Transfer Objects or Value Objects). In my opinion, this also improves the testability of the code.
Whereas, there is a counter argument from another side (mostly the proponents of Domain- Driven Development (DDD)) that separating domain objects from its operations is nothing but going back to procedural style of programming. I don't know if I necessarily agree with that argument. Frameworks like Hibernate (even JPA) allows us to embed custom SQL's inside the domain model. In my mind that is a 'mixing' of concerns.
Also, imagine a method called sell() inside a 'Book' object. Does a book know how to sell it? Should it know? Also, Book has an existence without a sell() functionality. In cases like this, I prefer the business logic to be separated in to respective Service Classes which results in methods like BookServiceImpl.sell(book) and BookServiceImpl.calculatePrice(book) rather than Book.sell() and Book.calculatePrice().
This is not to totally dismiss the other argument. If we are developing software for a rapidly changing business domain, from a maintainability perspective, DDD approach may sound attractive. For example, when the way company sell books change , the place it requires the code change is most likely the Book.sell() method; where as, if we are to change the service method, it might affect various other sub-systems in which the service methods are re-used. But when Book object requires another domain object (e.g: 'CreditCard' object) to do its selling, things become complicated. Yes, we can inject CreditCard object into Book object, but effectively we are introducing a level of coupling and reducing testability.