Shah,
to answer your question, I would have to step back to the root of our other discussions about the basic architectural concepts, the definitions of Domain, services, etc.
Your concept of Domain Objects differs from mine, or from the authors' of JPetStore, for that matter. I define a functional Domain as a combination of 1) business entities and 2) operations that may be performed over those entities. So far, our views are similar, I think. But when it comes to the implementation, I strongly disagree with the school of thought you seem to belong to. I am not saying it is bad, and I do believe that objects must encapsulate both data and behavior. However, I also believe that being an "object purist" is not necessarily a good thing. Not all functionality that may be applied to a class must live on
that class. The most essential concept of the art and craft of software engineering - and the most disregarded, unfortunately - is the concept of
de-coupling things that are better off managed separately. Not melting things together allows creating flexible software, it gives you options to use the same things in various contexts without having to repeat yourself, without creating more work and hurdles for yourself. "Object puritanism", or, perhaps "object zealotry", is a dangerous thing.
There are reasons why the great
Edger Dijkstra all but rejected the idea of OO! He once said:
Now, let's not dismiss his point of view without thinking. Dijkstra spent all his professional life promoting elegance and correctness in programming, and he knew a thing or two about that! His contributions to Computer Science and programming languages are colossal! Every serious programmer absolutely must read Dijkstra's
The Humble Programmer article (the ACM Turing Lecture) before they read any modern flavor-of-the-day books on coding practices and design patterns! That may open some people's eyes on what programming should be all about, what testing is really for (not for ensuring the
absence of the bugs, if that's what you are tempted to say!) , and many other things...
Of course, all of us here in this forum are devoted Java programmers, and we appreciate the value of good OO design. I can't speak for Dijkstra and interpret why exactly he personally disliked the idea of OO. Perhaps he saw the danger in the concept that could easily be misinterpreted and taken to the extreme? I'd completely understand that. I definitely disagree with the notion that any object should always be literally self-contained, which implies that it should store the
business logic applied to it. I believe (and so do many others) that objects that represent entities must encapsulate their properties/attributes and
only the behavior essential to the object's definition - without any business-specific operations that may or may not be applied to that entity. In other words, it is not appropriate to put application-specific business operation into an all-purpose entity. Things like that should be
externalized. Therefore, my idea of domain entities is closer to your idea of a DTO or value objects, but not exactly that. I do believe that such entities must implement the kind of behavior without which the entity may not be considered valid and usable. For example, a UsZipCode class may implement zip validation, parsing of the input data, splitting the zip into 5-digit code, 4-digit extension, or representing itself in several different ways: 5-, 9-, or 11-digit code, etc. All of such functionality is essential to defining a US Zip Code concept but it has nothing to do with the world outside the class itself. Nothing in such Zip Code class depends on, or makes assumptions about, how the objects of the class will be
used in applications. This is the most essential point that I am trying to make.
The entity definitions must be decoupled from any external operations that may be performed on the entity instances. The necessity in such operations (use cases) may come and go, but the domain entity objects will remain what they are - regardless of how they used.
That is why, I clearly separate the concept of a domain entity, and a domain service. Note that I said "domain service". That's because I see a service as a software module that implements use cases/operations in a particular
functional domain. For example, the User service implements user-related use cases and operates on User domain entities. Therefore a DOMAIN concept covers both: entities and operations, but keeps the two separate.
In your interpretation, the business operations and data are molded together, and then you add a notion of a pure VO/DTO. The advantage of my approach is that I can apply any necessary business logic at any time to my domain entity objects (that carry the data and the encapsulated behavior that
only describes the nature of the object, without the business logic). I define the business operations in dedicated services that implement use cases. I can add or remove service operations, but the
Domain Object model remains the same. I don't need a separate layer of DTOs, and, most importantly, it is absolutely valid to expose the domain entity objects to the presentation tier (controllers/presenters.) In fact, that is how it should be! And that's what you saw in JPetStore. For example, if you decide that your application needs to use a notion of a User with some of the user-management functionality, you add the User component (e.g. user.jar) as a dependency for your application. Your front-end actions/controllers are aware of the User class and other entity classes defined in that component. They are also aware of the UserService (or UserManager) class that implements some user management functionality. You have no problem injecting that manager instance into your front-end controller, so why would you object the Controller being exposed to the entity classes that are also defined by the same User component? (Remember, in other our discussions I explained how to package classes by functionality, not by type; if yo do that you will always end up with a single independent module that defines both the service API and entity objects.)
So, there you have it. The Controller receives the application-specific form/command object and maps the data to the domain entity that is recognized by the service (manager), and makes the call to the business method on the service to execute the business operation. Very simple. No additional DTOs, no "gateways". It's nothing new. It's just all about separating things and responsibilities that do not necessarily belong together. It is ok to have a "manager/service" object vs. stuffing everything into a "domain [entity] object." Once you wire something in, you are stuck with that. You should never make assumptions about what operations will and should be performed on an object. A desk is a desk. You can't force everyone to use it in the same way. Some people use desks for work, for writing, for reading, some folks eat at their desks, some might want to do things you won't imagine... None of those behaviors have anything to do with the concept of a desk itself, even though they are often applied to desks... You get my point, right?
Good discussions.