epbernard wrote:
Can you give us some real life sample of your enhancement needs.
Sure, here's an example:
One of my model objects is a shopping cart. The Cart object obviously has various methods for manipulating the contents of the cart, and for assigning memo's, naming the cart, etc. etc. Naturally it has an addLineItem() method on it - which adds a LineItem object to a collection (list) on the Cart.
I need the Cart (and LineItem) to be persistent, and I've made the great choice of using Hibernate ;-). And I want to build my "shopping cart system" so that it is essentially a re-usable library that I can plug into various applications.
The various applications have many similarities, but have differences in buisiness rules. For example, the DoD has business rules to make sure that the items in the cart are "compatible" with each other. For instance, rules like if you're got a weapons system in your cart, then you can't also put combat boots in the cart, but you can put aircrapt canopies in the cart. Or if you're adding a propeller to your cart, you better only have propellers already in it (or empty). Another customer has wildly different rules such as if you're adding an X to the cart, then automatically add three Ys for every X to the cart. etc. etc.
So the rules don't *change* during runtime, but they are dependent on application configuration and therefore aren't *known* until runtime. If have my controller layer use a factory to produce instances of model objects, than it can produce them of an "enhanced" version of the class, that has the additional logic that needs to run during the various method calls on the objects (such as on Cart.addLineItem()).
The reason enhancement is important rather than using just proxies is that some of the objects have re-entrant methods. For example, if I were to call Cart.doX() on a proxy, the proxy could run the business rule, and then run the underlying doX() if there is no exception. But if the doX() on the real object calls doY() on the object, then the rule that should be enforced when doY() is called is circumvented, because the object didn't call doY() on the proxy. Thus enhancement is the choice over proxies.... but that leads to the issues described in this thread's original message. (of course, using proxies would solve some of the persistence issues, but not all, or at least not elegantly, as you noted - and would have the problems I just pointed out as far as business rules are concerned).
So then you might ask: why not have a biz delegate class in the controller layer of the app have an "addLineItem()" method on it, and have it enforce the rule, and then manipulate the model objects? The simplest answer is that we're trying to adopt the principles of
Streamlined Object Modeling - which stresses the importance of keeping model objects responsible for enforcing the rules that are related to them - so the encapsulation is more tightly enforced - keeping the object solely responsible for its own state, rather than puting logic in other objects than manipulate its state. Or, in other words, have a business model (set of objects) that know have to govern themselves, rather than a set of object models that are just data structures (which is what is done in most Java apps - by architects (myself included) having made "manager" type objects that directly manipulate the model objects (setX(), etc.), rather than calling business methods on the model objects (doX(), etc.)).
Anyway, this is our first whole-hearted "go" at trying to apply the advice/techniques of the Streamlined Object Modeling approach, and there have been a number of stumbling blocks trying to get the principles (which sound good on paper) applied into a clean/reasonable implementation, which includes code re-use..
Advice appreciated...
james