dado2003 wrote:
First of all this shows two things:
- first of I jumped to conclusions to soon
- you weren't very clear with the explanation first time
( lets split the guit :) )
;-)
dado2003 wrote:
OK, so i get it that the union process+entity is in fact and "object" in the domain model and not the entity by itself...
Part of my first answer was because I use the terms process in a slightly different context (internal framework habits).
But doesn't this introduce just too much classes? My approach is similar to yours on this but it struggle to make the entities be smarter so "code less but develop more".
Yes, it does introduce a lot of classes. In our previous project, we used a horizontal layering (with datasets). We basically had 3 objects per information area (comprised of many, many datasets): data, proces and service layer.
There we saw an incredible amount of methods on each object which really works against you (not to mention being the opposite of OO).
So time will tell if we don't get too many classes with this new approach and that that will bite us just as much. At the very least we will have good encapsulation though ;-) Until now we don't consider this to be a problem though.
To help in constructing these objects, we use a container (castle). This does help as well.
dado2003 wrote:
I have read very carefull you answer and the not lazy was not mentioned and also I figured that the entities expose more logic. But IMHO lazyiness is a too good feature to ignore and such a model (that uses lazy) cannot be exposed in presentation. Question: if you don't use lazy this means that you map fk's as values or as entities? If they are entities that are not lazy doesn't this trigger just too much joins/selects?
I'm fully using lazy and fetch styles to create a default behavior of the model and than override them if necessary in queries to shape the resultset to best DB performance.
Indeed, I was a bit short in my first explaination.
Basically, what we do is this: we map the way we want (using lazy and everything). So we can query and use our objects on the server, just like you can. For us, lazyness is also a feature too good to ignore, so we make great use of it. (I should mention the focus of the application is on long business processes on the server).
When it is time to get data to the client, we use the (de-)serialization capabilities of Indigo (as opposed to remoting, like we have done in previous projects). We simply check if a collection is lazy loaded, and if so, we will not serialize it: thereby not triggering lazy loading when we are at the client.
On the client we automatically build up the domainobjects again with empty collections, where the non-initialized proxies used to be.
The only problem we have here is with building up collections on the server again, when we return there. So we keep track of deleted entities, and manually do a session.delete on them.
What I am really missing in nhibernate at this moment, is a good way to manipulate the nhibernate.bag etc.
Still working on a better solution for this.
dado2003 wrote:
Sorry for that, didn't mean to...
For me keeping entities in domain model and DTO for sending/receiving data is better because I can shape results (cut/add properties, collections etc). Another reason to use custom DTOs is also because we mapp a full graph (almost all collections are mapped and *all* reference of many-to-one). This gives me the liberty to do everything on the middle tier(s) and exchange only specific, dumb (somethimes very dumb) data to presentation.
This is a trade-off.
I'm guessing using custom dto's (per UI screen possibly?) could be easier.
I'm thinking of going for a loadstrategy enum per root-aggregation object that will be called. The loadstrategy will map 1-1 on named queries, filling exactly the right amount of the graph.
dado2003 wrote:
The discussion was not specifically about how the presentation is build, rather about how much does presentation know about "internal affairs" and if a method in the presentation ussualy does more than validating some input and making 1-2 calls to middle tier.
Okay, I misunderstood then. There is a possibility I still do actually ;-)
Our client is mostly about editing data and saving. The validation is pretty lightweight, but that will not always be the case.
The way I connect validation to properties on the datamodel is by metadata. ( I used to have attributes, but that was a bit chaotic, now I use the same pattern that microsoft does and that is to query the object for validation rules and letting him spit it out). If I come across specific validation rules that I do not want to perform on the client, I will most likely create two classes of validation rules, client and server side. The server would validate both the client rules as the server rules.
dado2003 wrote:
It was not about the time to fill DTO with data but about the time to code DTOs (create classes/structs, properties, maintain them). This is what I want to tackle. Also, for me there are enough cases where edditing/viewing is done on a graph involving 3-4 classes so that exposing such a graph is harder to use/maintain than some simple views with just needed data.
Okay, I can see the use of that. It was a major consideration for me as well. I have big object graphs as well, but per screen I do not perse want to be bothered with large parts of those graphs.
I can recall there is a transformation tool for DO <-> DTO. It was being built by the ppl behind NPersist. But I can't find a link for it right now.
But I have the feeling you are about to present such a tool yourself soon.. ? :-)
dado2003 wrote:
- I seems to much to code in order to encapsulate each entity within a process and I guess that if Order has collection of Lines than OrderProc has collection of LinesProc...again, (if it is so) isn't it error prone if not very carrefull with theese?
Yep ;-)
It's not an automatic process btw. So I will just create a lineProc object when I'm in orderproc and need to do something on an line.
It's been an interesting discussion. I'm off on vacation tomorrow, will be back on tuesday.
I wish there were more best practices and design-considerations like these written down...