So ... continuing on from the foundation for the discussion: 1. Using ViewModel object as a "standin" domain model object is just not right for several reasons: a. It's a ViewModel object - it has only one role. b. To be part of a domain object graph it would most likely be referred to by a domain object and therefore there is now a dependency from the PD (domain) package to the UI (viewmodel) package. c. Any subsequent developer looking at the code would be confused. d. It's "overloading" the use of View Model and hence muddying the separation of concerns.
2. Rolling your own datastore in DataNucleus would be difficult I think - every integration will require yet another custom datastore added to DataNucleus. And now there is a dependency on DataNucleus that is not at the standards based JDO API level but at the DataNucleus specific API level. There is only one logical outcome from this discussion: ISIS must allow me to create a domain object that has no "local" persistence but still enjoys all the other benefits of ISIS domain object and allows me to inject dependency (either by ISIS domain service or some other DI library). I should be able to choose what data attribute (or composite of data atributes) acts as the "oid" by annotation or naming pattern. Regards, David. On Friday, 21 March 2014 9:31 AM, David Tildesley <[email protected]> wrote: Hi Dan, Lets get back to a basic foundation for the discussion. I would like to use the terminology from the FDD (1) guys because it is clear and a very handy shortcut. to quote Paul Szego from (1) " ... The DM layer we tend not to talk about much anymore as we buy a persistence solution here rather than build our own. Thus, we're really only focusing this article on UI, PD and SI. .... UI-->| PD |<-- SI (this is what we want)" All we need to understand here is that the only thing worth protecting as an enduring business asset is the Problem Domain (PD) layer and it must be independent of all other layers and be a rich domain (as understood by Martin Fowler's discussion on the Anemic Domain anti-pattern). In fact it needs to be independent from frameworks like ISIS. When "View Model" arrived in ISIS, I understood exactly the intention - it was to allow us to create a more user friendly human oriented UI and as a bonus it allowed us to create a "coarse-grained" service oriented UI generated automatically by the RO viewer. The "View Model" allowed us to aggregate information from the PD layer (from the a domain object graph) but it should never cause business logic to bled out of the the PD layer. I will acknowledge here and now there are some very exceptional circumstances where you would allow the UI layer to bypass the PD layer. But they are exceptional and irrelevant to this discussion. I have been involved in projects taking the UI-->PD<--SI layer approach (happened to use the Struts MVC in the UI layer but that's irrelevant, where none of the PD objects were "locally persisted" In fact the entire information set either came from users via the UI or from interaction with a mainframe over JMS via the SI layer. This was at a Bank and the applications were very significant (not trivial). We used color domain modelling techniques (the first step in FDD) in workshops to produce the just-enough domain model that the developers then implemented. David. [1] http://www.featuredrivendevelopment.com/node/582 On Friday, 21 March 2014 5:00 AM, Dan Haywood <[email protected]> wrote: David said: Some more thoughts/assumptions on transient domain objects: > 1. oid - annotate an attribute or use attribute naming pattern > 2. Restful remoting mean client maintains required state - client doesn't > care whether domain object is transient or not. > 3. Restful remoting means the server trashes the domain object instance > after the response. However domain behaviour is not transferred and > everytime a behaviour is invoked on a domain object graph, the domain graph > has to re-instantiated at the server - big performance hit unless > developer uses a cache (ehcache or similar). > Am I wide of the mark with any of the above? Jeroen said: I do agree with David that there are plenty of use cases to think of where > having a transient domain object on the server can be useful. I am > wondering how comparable architectures deal with transient objects, perhaps > an analogy with a Stateful Session Bean can be made? [1]. This would make a > good topic of conversation on the IsisCon conference too. > [1] http://www.jguru.com/faq/view.jsp?EID=917 And on 19 March 2014 21:29, David Tildesley <[email protected]> also said: > Maybe "transient" is misleading in my side of the discussion. Essentially > a viewer should be able to instantiate an ISIS domain object that has no > connection to DataNucleus, repository as such but can still have a domain > service implementation fetch and put data from an external source (via, > web-service, jms, whatever) and inject into the domain object. That keeps > my domain layer intact and doesn't result in bleeding any domain behaviour > out to other layers (e.g. view objects which are logically in the UI layer). > > > However as Dan points out, this doesn't sit well with RESTful style. In a > traditional app, UI layer (usually using a MVC model) will make several > invocations on domain object graph behaviour (fine grained method level > calls) with state being maintained in the session for as long as needed > over a series of client requests. This is not the case with RESTful style. > Client is responsible for maintaining state with the server having no > obligations in this regard. This does not sit well with a fine-grained > method invocation on the domain layer - you would normally go for those big > coarse grained calls and end up re-implementing a domain layer in the > client that replicates domain behaviour. This is where the RESTful model > falls into a heap (in my opinion) as the tradeoff is very significant. To > retain the "finegrained" domain layer invocation on the server side in the > RESTful style would necessitate rebuilding the relevant domain object graph > with every call > and trashing it afterwards. This rebuilding "hit" could be mitigated by > careful use of caching on the domain service layer, however the lifecycle > of the domain object graph has to be completed on every RESTful invocation. > > There's quite a few subtle points here to discuss. One thing to say first off, perhaps "view model" also is not the right term for what we have in Isis; it suggests that the object is only for presentation purposes, but in fact it could be used as an entity that is managed externally too. In fact, over in Ireland on the "sister" .NET project, we are doing something very similar to this with the equivalent functionality provided by NO MVC. Anyway... I understand the objection loud and clear about not having to be forced to use DataNucleus to obtain entities. And I also hear what you are saying about REST and it moving all the state management client-side into the viewer. Obviously this isn't the intention; we want the domain logic to be expressed only in one place, namely in Isis. This is non-negotiable, we're not trying to build something like EmberJS. To answer the REST point briefly: the standard pattern is to have some sort of (server-side) resource that represents the conversation/transaction. This is analogous to Jeroen's point about stateful session beans. I'll come back to this in a moment. Let me get back to the main point about using Isis for domain objects whose persistence is managed by some other mechanism. I think that our (perhaps misnamed) ViewModel mechanism will actually work quite well here; the viewModelMemento() method / viewModelInit(String) methods provide a simple mechanism by which the view model provide/gets a handle to the external object. (The memento is basically the Oid, as I've said). And so, for example, it'd be trivial to implement stateful session beans using this mechanism: - we have a domain service that wraps the HttpSession interface. - a view model is created and generates a GUID as its memento. It uses this GUID to store its state into the HttpSession through the domain service. - when the view model is recreated and init'd with that same GUID, it uses the GUID to fetch its state from the domain service. At the end of the interaction, it flushes any changes back to the domain service. One thing to note is that a view models OID is immutable. However, all that means is that the GUID it uses to fetch from the externally-managed resource (eg HttpSession) doesn't change; the state keyed by that GUID *could* change. I'm pretty sure that the same general design can work for any other externally-managed entity; so long as we have a unique identifier to it, this can be the memento given to the view model. Logically speaking this view model is acting like an entity to the rest of the domain objects in the Isis app; its just a wrapper around that externally-managed entity. As I say, ViewModel is probably the wrong name/gives the wrong impression. (Unless one consider it to be the view not of the Isis app but of the external system, which I suppose is true.... a sort of anti-corruption layer). All the above notwithstanding, it is worth noting that by ignoring DataNucleus there are a few things that one would not get: - dirty tracking, and automatic saving/persistence - lazy loading - querying - auditing and object publishing (both of which leverages DataNucleus' dirty tracking). So I still think it'd be worth considering wrapping up a domain service as a DN StoreManager impl. I imagine that a lot of the boilerplate could be factored out. Just looking at the datanucleus-json implementation of StoreManager [1], for example, it doesn't look *too* threatening. I also noticed that DataNucleus has a FederatedStoreManager, so there could be a number of companion store managers for managing entities from these external systems, operating alongside any entities that Isis itself manages in the regular JDO ObjectStore. To summarize: - objects that implement Isis' ViewModel interface can be considered to be entities if they are basically proxies to externally-managed entities - but doing it this way means that a lot of the features of the ORM must be re-implemented by hand. Let's keep talking on this thread, it's useful and fundamental stuff Dan [1] https://github.com/datanucleus/datanucleus-json/tree/master/src/java/org/datanucleus/store/json
