getter/setter facade (was: Re: O->R Mapping (Was: findByAnd(Map) ws findList(EntityCondition)))

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

getter/setter facade (was: Re: O->R Mapping (Was: findByAnd(Map) ws findList(EntityCondition)))

Marc Morin
Now it's pretty obvious that many are reading the incorrectly renamed O->R mapping subject and saying it's counter to OFBiz entity model, core philosophy, discussed before... go away you Object lovin' Java developer... ;-)

I don't want to repeat the topic, but it is a getter/setter decorator around the Entity/Delegator API that you all love.  Not hibernate, not OO persistence...

I don't know how anyone can say that the following code is "nicer", "safer", easier to maintain

    GenericValue order = delegator.findOne("OrderHeader", UtilMisc.toList("orderId", orderId), true);
    Timestamp entryDate = order.getTimestamp("entryDate");
    List<GenericValue> orderItems = order.getRelated("OrderItem");

vs (evil Object facade, what a Java developer would expect to see, IDE auto-completion, type safety)

    OrderHeader order = OrderHeader.findOne(delegator,orderId);
    Timestamp entryDate = order.getEntryDate();
    List<OrderItem> orderItems = order.getOrderItemList();

My point is, there is a simple facade we can present on all the goodness of the GenericValue, delegator, dispatcher, transactions, that makes the Java purest feel better about OFBiz.  (been easier to find Java developers than OFBiz ones...)

We have been using this exact decorator pattern in our OFBiz application for over 2 years, it feels natural when writing Java code (ie. when in Rome act like a Roman), haven't heard any developers say they don't want to use it in favor of the "String" way, once exposed to it and writing new code.  When modifying existing code, they want to change all GenericValues to their appropriate object decorator. (we aren't doing this in app/framework so we can merge easier, but would love to do see it done/do it)

Well, looks like we'll continue on our own marry way on this one, keep our forked technology to ourselves....  I can feel the rope pushing that I mentioned previously. ;-)



Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Adam Heath-2
Marc Morin wrote:

> Now it's pretty obvious that many are reading the incorrectly renamed O->R mapping subject and saying it's counter to OFBiz entity model, core philosophy, discussed before... go away you Object lovin' Java developer... ;-)
>
> I don't want to repeat the topic, but it is a getter/setter decorator around the Entity/Delegator API that you all love.  Not hibernate, not OO persistence...
>
> I don't know how anyone can say that the following code is "nicer", "safer", easier to maintain
>
>     GenericValue order = delegator.findOne("OrderHeader", UtilMisc.toList("orderId", orderId), true);
>     Timestamp entryDate = order.getTimestamp("entryDate");
>     List<GenericValue> orderItems = order.getRelated("OrderItem");
>
> vs (evil Object facade, what a Java developer would expect to see, IDE auto-completion, type safety)
>
>     OrderHeader order = OrderHeader.findOne(delegator,orderId);
>     Timestamp entryDate = order.getEntryDate();
>     List<OrderItem> orderItems = order.getOrderItemList();

Only one suggestion on the api.  getOrderItemList should not have a
list suffix on the method.  The type return is defined by the entity
definition(in this case, 'many').  Plus, once removing the list
suffix, OrderItem could conflict by name with a field named the same.
 So, in such cases, remove the get prefix.  order.OrderItem().

Have you extended the base-line non-typed get() method to support
relation fetching?  So, in groovy, I could do order.entryDate(which is
possible now), or order.OrderItem(because the first char is capital,
it would do a relation fetch).

As for those of us that have been resisting, I don't want to be one of
those.  Ofbiz is for a community, and if people want this, then we
shouldn't really say no.  I have moved back and forth several times
over the years about this.

The interface wouldn't be hard to write.  At build type, something
similar to javacc/jjtree would be run, that would auto-generate a java
class, based on any entity.

Er, oops, I just found a problem with your idea.  How do you handle
<extend-entity>?
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

BJ Freeman
In reply to this post by Marc Morin
when you use a Class it is an object.
getter and setter are methods by another name.
if you instantiate a class all the methods are carried with it whether
they are used or not.
so regardless of your argument it is OO.

if you are familar with c then create a hello world function and compile
then create a class hello world. not the difference in size and look at
the stack for a call to both.

the last time I did this the function compiled to 1K the class compile
was 10K with no methods in the class.

then put getter and setter in the hellow world and watch the size and
the stack when using the class.

this will give you an idea of what is being talked about.



=========================
BJ Freeman
Strategic Power Office with Supplier Automation  <http://www.businessesnetwork.com/automation/viewforum.php?f=52>
Specialtymarket.com  <http://www.specialtymarket.com/>
Systems Integrator-- Glad to Assist

Chat  Y! messenger: bjfr33man

Marc Morin sent the following on 12/11/2010 12:40 PM:


> Now it's pretty obvious that many are reading the incorrectly renamed O->R mapping subject and saying it's counter to OFBiz entity model, core philosophy, discussed before... go away you Object lovin' Java developer... ;-)
>
> I don't want to repeat the topic, but it is a getter/setter decorator around the Entity/Delegator API that you all love.  Not hibernate, not OO persistence...
>
> I don't know how anyone can say that the following code is "nicer", "safer", easier to maintain
>
>      GenericValue order = delegator.findOne("OrderHeader", UtilMisc.toList("orderId", orderId), true);
>      Timestamp entryDate = order.getTimestamp("entryDate");
>      List<GenericValue>  orderItems = order.getRelated("OrderItem");
>
> vs (evil Object facade, what a Java developer would expect to see, IDE auto-completion, type safety)
>
>      OrderHeader order = OrderHeader.findOne(delegator,orderId);
>      Timestamp entryDate = order.getEntryDate();
>      List<OrderItem>  orderItems = order.getOrderItemList();
>
> My point is, there is a simple facade we can present on all the goodness of the GenericValue, delegator, dispatcher, transactions, that makes the Java purest feel better about OFBiz.  (been easier to find Java developers than OFBiz ones...)
>
> We have been using this exact decorator pattern in our OFBiz application for over 2 years, it feels natural when writing Java code (ie. when in Rome act like a Roman), haven't heard any developers say they don't want to use it in favor of the "String" way, once exposed to it and writing new code.  When modifying existing code, they want to change all GenericValues to their appropriate object decorator. (we aren't doing this in app/framework so we can merge easier, but would love to do see it done/do it)
>
> Well, looks like we'll continue on our own marry way on this one, keep our forked technology to ourselves....  I can feel the rope pushing that I mentioned previously. ;-)
>
>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Marc Morin
We statically generate all the classes during build as you mentioned.  We have a new ant target 'entity-gen' that runs after framework base util entity have been compiled.  It is a custom container that reads the entity model, puts stuff into a context, then uses an ftl for the template of each the classes.

This generates two artifacts:

- a class for each entity and view-entity in the system.
- a .properties file used by GenericValue.create() to instantiate the correct class for the entity.  

Since our current implementation runs after the entity is loaded, all extending is done already. Anticipating the next question, as it reads the entire model and all extends and relations, it will generate a single global map and linking for entities.  (Entity model is global to all applications)

We just use List as a convention, debated just using 's' (like order.getOrderItems()) which feels normal.  We don't worry about the namespace collision of field X and relation to entity X using the same getX() gettor, haven't observed it.

So, if you create entity X in your hot-deploy application, it will see X and generate it along with the base entities... any relations to and from X to base entities will result in regenerating X and the base entities (not a good thing).

You'd really like to generate the decorator in each application area where the entities are defined....  so application X would see a class X with getter/setters and relations as it was defined.

Application Y extends entity X, means that it should see Y's version...  likely could be done with a classpath search order, but behind the scenes, you can only create a single class X for entity named "X", no matter what application is using it!

We've side stepped this issue by living with the global generation issue.

NB. Extending means entity-extend AND adding a relation to/from that entity since gettors will be generated for the getRelated.

Marc Morin
Emforium Group Inc.
ALL-IN Software
519-772-6824 ext 201
[hidden email]

----- Original Message -----

> Marc Morin wrote:
> > Now it's pretty obvious that many are reading the incorrectly
> > renamed O->R mapping subject and saying it's counter to OFBiz entity
> > model, core philosophy, discussed before... go away you Object
> > lovin' Java developer... ;-)
> >
> > I don't want to repeat the topic, but it is a getter/setter
> > decorator around the Entity/Delegator API that you all love. Not
> > hibernate, not OO persistence...
> >
> > I don't know how anyone can say that the following code is "nicer",
> > "safer", easier to maintain
> >
> >     GenericValue order = delegator.findOne("OrderHeader",
> >     UtilMisc.toList("orderId", orderId), true);
> >     Timestamp entryDate = order.getTimestamp("entryDate");
> >     List<GenericValue> orderItems = order.getRelated("OrderItem");
> >
> > vs (evil Object facade, what a Java developer would expect to see,
> > IDE auto-completion, type safety)
> >
> >     OrderHeader order = OrderHeader.findOne(delegator,orderId);
> >     Timestamp entryDate = order.getEntryDate();
> >     List<OrderItem> orderItems = order.getOrderItemList();
>
> Only one suggestion on the api. getOrderItemList should not have a
> list suffix on the method. The type return is defined by the entity
> definition(in this case, 'many'). Plus, once removing the list
> suffix, OrderItem could conflict by name with a field named the same.
> So, in such cases, remove the get prefix. order.OrderItem().
>
> Have you extended the base-line non-typed get() method to support
> relation fetching? So, in groovy, I could do order.entryDate(which is
> possible now), or order.OrderItem(because the first char is capital,
> it would do a relation fetch).
>
> As for those of us that have been resisting, I don't want to be one of
> those. Ofbiz is for a community, and if people want this, then we
> shouldn't really say no. I have moved back and forth several times
> over the years about this.
>
> The interface wouldn't be hard to write. At build type, something
> similar to javacc/jjtree would be run, that would auto-generate a java
> class, based on any entity.
>
> Er, oops, I just found a problem with your idea. How do you handle
> <extend-entity>?
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Marc Morin
In reply to this post by BJ Freeman
Well the good old GenericValue is an object as well. ;-)


Marc Morin
Emforium Group Inc.
ALL-IN Software
519-772-6824 ext 201
[hidden email]

----- Original Message -----

> when you use a Class it is an object.
> getter and setter are methods by another name.
> if you instantiate a class all the methods are carried with it whether
> they are used or not.
> so regardless of your argument it is OO.
>
> if you are familar with c then create a hello world function and
> compile then create a class hello world. not the difference in size
> and look at
> the stack for a call to both.
>
> the last time I did this the function compiled to 1K the class compile
> was 10K with no methods in the class.
>
> then put getter and setter in the hellow world and watch the size and
> the stack when using the class.
>
> this will give you an idea of what is being talked about.
>
>
>
> =========================
> BJ Freeman
> Strategic Power Office with Supplier Automation
> <http://www.businessesnetwork.com/automation/viewforum.php?f=52>
> Specialtymarket.com <http://www.specialtymarket.com/>
> Systems Integrator-- Glad to Assist
>
> Chat Y! messenger: bjfr33man
>
> Marc Morin sent the following on 12/11/2010 12:40 PM:
>
>
> > Now it's pretty obvious that many are reading the incorrectly
> > renamed O->R mapping subject and saying it's counter to OFBiz entity
> > model, core philosophy, discussed before... go away you Object
> > lovin' Java developer... ;-)
> >
> > I don't want to repeat the topic, but it is a getter/setter
> > decorator around the Entity/Delegator API that you all love. Not
> > hibernate, not OO persistence...
> >
> > I don't know how anyone can say that the following code is "nicer",
> > "safer", easier to maintain
> >
> >      GenericValue order = delegator.findOne("OrderHeader",
> >      UtilMisc.toList("orderId", orderId), true);
> >      Timestamp entryDate = order.getTimestamp("entryDate");
> >      List<GenericValue> orderItems = order.getRelated("OrderItem");
> >
> > vs (evil Object facade, what a Java developer would expect to see,
> > IDE auto-completion, type safety)
> >
> >      OrderHeader order = OrderHeader.findOne(delegator,orderId);
> >      Timestamp entryDate = order.getEntryDate();
> >      List<OrderItem> orderItems = order.getOrderItemList();
> >
> > My point is, there is a simple facade we can present on all the
> > goodness of the GenericValue, delegator, dispatcher, transactions,
> > that makes the Java purest feel better about OFBiz. (been easier to
> > find Java developers than OFBiz ones...)
> >
> > We have been using this exact decorator pattern in our OFBiz
> > application for over 2 years, it feels natural when writing Java
> > code (ie. when in Rome act like a Roman), haven't heard any
> > developers say they don't want to use it in favor of the "String"
> > way, once exposed to it and writing new code. When modifying
> > existing code, they want to change all GenericValues to their
> > appropriate object decorator. (we aren't doing this in app/framework
> > so we can merge easier, but would love to do see it done/do it)
> >
> > Well, looks like we'll continue on our own marry way on this one,
> > keep our forked technology to ourselves.... I can feel the rope
> > pushing that I mentioned previously. ;-)
> >
> >
> >
> >
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Marc Morin
In reply to this post by Adam Heath-2

> Have you extended the base-line non-typed get() method to support
> relation fetching? So, in groovy, I could do order.entryDate(which is
> possible now), or order.OrderItem(because the first char is capital,
> it would do a relation fetch).
>

So we haven't but that is something that should be done in GenericValue.get(fieldName). Good idea.
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Adam Heath-2
In reply to this post by Marc Morin
Marc Morin wrote:
> We statically generate all the classes during build as you
> mentioned.  We have a new ant target 'entity-gen' that runs
> after framework base util entity have been compiled.  It is
> a custom container that reads the entity model, puts stuff
> into a context, then uses an ftl for the template of each
> the classes.

container isn't needed.  Use xslt, that reads all
ofbiz-component.xml+component-load.xml, recursively, then all entity
models(again, recursively), to output java.

I've done something like this to generate makefiles that convert
entitymodel to sql stmts(CREATE TABLE (field type), CREATE VIEW AS
SELECT).  I then used that to verify that my new enhanced sql reader
could read all the same model that the standard classes could.

The xslt method would run faster, then launching a quicky ofbiz
instance, and your special container.

> This generates two artifacts:
>
> - a class for each entity and view-entity in the system.
> - a .properties file used by GenericValue.create() to instantiate
> the correct class for the entity.

I wouldn't generate a properties file.  I would generate each java
file, compile it, store it into it's own .jar(in build/lib in the
component), and then add a META-INF/services file that lists each entity.

It might be nice to extend your system to handle the
Party/Person/PartyGroup pattern as well(delegator would need to be
enhanced to load the base values).

Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Marc Morin
We have talked and lamented on handling in the framework the "Entity sub-classing" *Type entities with the hasTable and *TypeId hierarchy....

both on loading and the "is A" operator on entities and their types...

Marc Morin
Emforium Group Inc.
ALL-IN Software
519-772-6824 ext 201
[hidden email]

----- Original Message -----

> Marc Morin wrote:
> > We statically generate all the classes during build as you
> > mentioned. We have a new ant target 'entity-gen' that runs
> > after framework base util entity have been compiled. It is
> > a custom container that reads the entity model, puts stuff
> > into a context, then uses an ftl for the template of each
> > the classes.
>
> container isn't needed. Use xslt, that reads all
> ofbiz-component.xml+component-load.xml, recursively, then all entity
> models(again, recursively), to output java.
>
> I've done something like this to generate makefiles that convert
> entitymodel to sql stmts(CREATE TABLE (field type), CREATE VIEW AS
> SELECT). I then used that to verify that my new enhanced sql reader
> could read all the same model that the standard classes could.
>
> The xslt method would run faster, then launching a quicky ofbiz
> instance, and your special container.
>
> > This generates two artifacts:
> >
> > - a class for each entity and view-entity in the system.
> > - a .properties file used by GenericValue.create() to instantiate
> > the correct class for the entity.
>
> I wouldn't generate a properties file. I would generate each java
> file, compile it, store it into it's own .jar(in build/lib in the
> component), and then add a META-INF/services file that lists each
> entity.
>
> It might be nice to extend your system to handle the
> Party/Person/PartyGroup pattern as well(delegator would need to be
> enhanced to load the base values).
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

BJ Freeman
In reply to this post by Marc Morin
most of the frame works are objects.
so how would you implement your object in simple-methods
like GenericValue?

=========================

BJ Freeman
Strategic Power Office with Supplier Automation  <http://www.businessesnetwork.com/automation/viewforum.php?f=52>
Specialtymarket.com  <http://www.specialtymarket.com/>
Systems Integrator-- Glad to Assist

Chat  Y! messenger: bjfr33man

Marc Morin sent the following on 12/11/2010 2:07 PM:

> Well the good old GenericValue is an object as well. ;-)
>
>
> Marc Morin
> Emforium Group Inc.
> ALL-IN Software
> 519-772-6824 ext 201
> [hidden email]
>
> ----- Original Message -----
>> when you use a Class it is an object.
>> getter and setter are methods by another name.
>> if you instantiate a class all the methods are carried with it whether
>> they are used or not.
>> so regardless of your argument it is OO.
>>
>> if you are familar with c then create a hello world function and
>> compile then create a class hello world. not the difference in size
>> and look at
>> the stack for a call to both.
>>
>> the last time I did this the function compiled to 1K the class compile
>> was 10K with no methods in the class.
>>
>> then put getter and setter in the hellow world and watch the size and
>> the stack when using the class.
>>
>> this will give you an idea of what is being talked about.
>>
>>
>>
>> =========================
>> BJ Freeman
>> Strategic Power Office with Supplier Automation
>> <http://www.businessesnetwork.com/automation/viewforum.php?f=52>
>> Specialtymarket.com<http://www.specialtymarket.com/>
>> Systems Integrator-- Glad to Assist
>>
>> Chat Y! messenger: bjfr33man
>>
>> Marc Morin sent the following on 12/11/2010 12:40 PM:
>>
>>
>>> Now it's pretty obvious that many are reading the incorrectly
>>> renamed O->R mapping subject and saying it's counter to OFBiz entity
>>> model, core philosophy, discussed before... go away you Object
>>> lovin' Java developer... ;-)
>>>
>>> I don't want to repeat the topic, but it is a getter/setter
>>> decorator around the Entity/Delegator API that you all love. Not
>>> hibernate, not OO persistence...
>>>
>>> I don't know how anyone can say that the following code is "nicer",
>>> "safer", easier to maintain
>>>
>>>       GenericValue order = delegator.findOne("OrderHeader",
>>>       UtilMisc.toList("orderId", orderId), true);
>>>       Timestamp entryDate = order.getTimestamp("entryDate");
>>>       List<GenericValue>  orderItems = order.getRelated("OrderItem");
>>>
>>> vs (evil Object facade, what a Java developer would expect to see,
>>> IDE auto-completion, type safety)
>>>
>>>       OrderHeader order = OrderHeader.findOne(delegator,orderId);
>>>       Timestamp entryDate = order.getEntryDate();
>>>       List<OrderItem>  orderItems = order.getOrderItemList();
>>>
>>> My point is, there is a simple facade we can present on all the
>>> goodness of the GenericValue, delegator, dispatcher, transactions,
>>> that makes the Java purest feel better about OFBiz. (been easier to
>>> find Java developers than OFBiz ones...)
>>>
>>> We have been using this exact decorator pattern in our OFBiz
>>> application for over 2 years, it feels natural when writing Java
>>> code (ie. when in Rome act like a Roman), haven't heard any
>>> developers say they don't want to use it in favor of the "String"
>>> way, once exposed to it and writing new code. When modifying
>>> existing code, they want to change all GenericValues to their
>>> appropriate object decorator. (we aren't doing this in app/framework
>>> so we can merge easier, but would love to do see it done/do it)
>>>
>>> Well, looks like we'll continue on our own marry way on this one,
>>> keep our forked technology to ourselves.... I can feel the rope
>>> pushing that I mentioned previously. ;-)
>>>
>>>
>>>
>>>
>
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Adam Heath-2
BJ Freeman wrote:
> most of the frame works are objects.
> so how would you implement your object in simple-methods
> like GenericValue?

These new classes are still GenericValue, while also being more specific.

class Party extends GenericValue {}
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

BJ Freeman
I have always wondered why they were used instead of simple methods
seem a lot less maintenance.
I have avoided classes.


=========================
BJ Freeman
Strategic Power Office with Supplier Automation  <http://www.businessesnetwork.com/automation/viewforum.php?f=52>
Specialtymarket.com  <http://www.specialtymarket.com/>
Systems Integrator-- Glad to Assist

Chat  Y! messenger: bjfr33man


Adam Heath sent the following on 12/11/2010 4:32 PM:
> BJ Freeman wrote:
>> most of the frame works are objects.
>> so how would you implement your object in simple-methods
>> like GenericValue?
>
> These new classes are still GenericValue, while also being more specific.
>
> class Party extends GenericValue {}
>

Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Marc Morin
In reply to this post by Adam Heath-2
We chose to use the full model reader when running the entity-gen since there are not trivial manipulations of the en*xml  files, such as extending, auto-relationships, auto-indexes, materialized views, view optimizations...

We don't entiy-gen on every build. Manually done. This is a bit of a pain, would be better if it was performed when needed.

----- Original Message -----

> Marc Morin wrote:
> > We statically generate all the classes during build as you
> > mentioned. We have a new ant target 'entity-gen' that runs
> > after framework base util entity have been compiled. It is
> > a custom container that reads the entity model, puts stuff
> > into a context, then uses an ftl for the template of each
> > the classes.
>
> container isn't needed. Use xslt, that reads all
> ofbiz-component.xml+component-load.xml, recursively, then all entity
> models(again, recursively), to output java.
>
> I've done something like this to generate makefiles that convert
> entitymodel to sql stmts(CREATE TABLE (field type), CREATE VIEW AS
> SELECT). I then used that to verify that my new enhanced sql reader
> could read all the same model that the standard classes could.
>
> The xslt method would run faster, then launching a quicky ofbiz
> instance, and your special container.
>
> > This generates two artifacts:
> >
> > - a class for each entity and view-entity in the system.
> > - a .properties file used by GenericValue.create() to instantiate
> > the correct class for the entity.
>
> I wouldn't generate a properties file. I would generate each java
> file, compile it, store it into it's own .jar(in build/lib in the
> component), and then add a META-INF/services file that lists each
> entity.
>
> It might be nice to extend your system to handle the
> Party/Person/PartyGroup pattern as well(delegator would need to be
> enhanced to load the base values).
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Adam Heath-2
Marc Morin wrote:
> We chose to use the full model reader when running the
> entity-gen since there are not trivial manipulations of the
> en*xml  files, such as extending, auto-relationships,
> auto-indexes, materialized views, view optimizations...
>
> We don't entiy-gen on every build. Manually done. This is a
> bit of a pain, would be better if it was performed when needed.

So, I have a stylesheet that does most of plain entity->java.  Handles
getRelated stuff(returning specific values, not GenericValue), and
static findOne/findList in each class.  This was mostly straight
forward to do.  It also handles view alias-all, alias, including
nested views.  Complex aliases, and extend-entity/relations aren't yet
handled(neither are overly complex to add to the xslt).

However, GenericPK/GenericValue use javolution object pools.  If there
is a separate class for each entity, the number of object pools grows
quite a bit.  Additionally, the instances stored in each pool can no
longer be shared(ie, a Party class instance can't be pooled with a
Person class instance; previously, they'd both be a GenericValue, so
might get recycled together).

Then, there is the requirement that javac needs to stay around on
production.  The entity classes must be generated close to a
production deployment; precompiling just the standard models in ofbiz
won't help, as end-user deployments will add new entities and/or
extend existing ones.  This modification could even be done on the
production instance itself.

So, I'm still torn on whether this is such a good idea.  I have no
problem at all with a tool like this being available in ofbiz, and
being used by end-user installs, but there are just too many issues
that I see with using it by default in normal ofbiz code.
Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade (was: Re: O->R Mapping (Was: findByAnd(Map) ws findList(EntityCondition)))

Jacopo Cappellato-4
In reply to this post by Marc Morin
Hi Marc,

On Dec 11, 2010, at 9:40 PM, Marc Morin wrote:

> Now it's pretty obvious that many are reading the incorrectly renamed O->R mapping subject and saying it's counter to OFBiz entity model, core philosophy, discussed before... go away you Object lovin' Java developer... ;-)
>
> I don't want to repeat the topic, but it is a getter/setter decorator around the Entity/Delegator API that you all love.  Not hibernate, not OO persistence...
>
> I don't know how anyone can say that the following code is "nicer", "safer", easier to maintain
>
>    GenericValue order = delegator.findOne("OrderHeader", UtilMisc.toList("orderId", orderId), true);
>    Timestamp entryDate = order.getTimestamp("entryDate");
>    List<GenericValue> orderItems = order.getRelated("OrderItem");
>
> vs (evil Object facade, what a Java developer would expect to see, IDE auto-completion, type safety)
>
>    OrderHeader order = OrderHeader.findOne(delegator,orderId);
>    Timestamp entryDate = order.getEntryDate();
>    List<OrderItem> orderItems = order.getOrderItemList();
>
> My point is, there is a simple facade we can present on all the goodness of the GenericValue, delegator, dispatcher, transactions, that makes the Java purest feel better about OFBiz.  (been easier to find Java developers than OFBiz ones...)

I doubt that a good Java developer would have problems in learning the former.
Based on my experience, if developers are willing to learn and master OFBiz, they can get comfortable with some of the peculiarities of OFBiz in a few hours. And when they learn how to use the delegator API then, as an added value, they also understand how to deal with Minilang.
On the other hand, I know that there are development teams that tend to initially reject some of the tools used in OFBiz: this has something to do with a-critic conformism to commonly accepted practices or fashion, rather than real advantages.

Jacopo

>
> We have been using this exact decorator pattern in our OFBiz application for over 2 years, it feels natural when writing Java code (ie. when in Rome act like a Roman), haven't heard any developers say they don't want to use it in favor of the "String" way, once exposed to it and writing new code.  When modifying existing code, they want to change all GenericValues to their appropriate object decorator. (we aren't doing this in app/framework so we can merge easier, but would love to do see it done/do it)
>
> Well, looks like we'll continue on our own marry way on this one, keep our forked technology to ourselves....  I can feel the rope pushing that I mentioned previously. ;-)
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Malin Nicolas
In reply to this post by Adam Heath-2
Le 12/12/2010 01:32, Adam Heath a écrit :

> BJ Freeman wrote:
>    
>> most of the frame works are objects.
>> so how would you implement your object in simple-methods
>> like GenericValue?
>>      
> These new classes are still GenericValue, while also being more specific.
>
> class Party extends GenericValue {}
>    
This system already exist with neogia addons. If you install the
persistance layer with ofbiz-generator addons you have a "simulation"
ORM over entity engine. It's not a greate revolution, we use this only
for big customer project.

Nicolas


--
Nicolas MALIN
Consultant
Tél : 06.17.66.40.06
Site projet : http://www.neogia.org/
-------
Société LibrenBerry
Tél : 02.48.02.56.12
Site : http://www.librenberry.net/

Reply | Threaded
Open this post in threaded view
|

Re: getter/setter facade

Malin Nicolas
Le 13/12/2010 08:56, Nicolas Malin a écrit :

> Le 12/12/2010 01:32, Adam Heath a écrit :
>> BJ Freeman wrote:
>>> most of the frame works are objects.
>>> so how would you implement your object in simple-methods
>>> like GenericValue?
>> These new classes are still GenericValue, while also being more
>> specific.
>>
>> class Party extends GenericValue {}
> This system already exist with neogia addons. If you install the
> persistance layer with ofbiz-generator addons you have a "simulation"
> ORM over entity engine. It's not a greate revolution, we use this only
> for big customer project.
>
> Nicolas
Just an example from neogia accounting components :

         String transId = (String) context.get(AcctgTransaction.transId);
         AcctgTransaction acctgTransaction =
AcctgTransactionServices.findByPrimaryKey(delegator, transId);
         List<AcctgTransactionItem> listAcctgTransactionItems =
acctgTransaction.getAcctgTransactionItemsWC();

         if
(AcctgTransactionStatus.FINALIZED.equals(acctgTransaction.getStatusId())) {
             return
ServiceUtil.returnSuccess(UtilProperties.getMessage(resource,
"NaccountingAlreadyFinalized", locale));
         }

We also extend delegator interface :

List<AcctgTransaction> transactions =
delegator.findNList(AcctgTransaction.ENTITY_NAME,
                 
EntityExpr.makeCondition(UtilMisc.toMap(AcctgTransaction.statusId,
AcctgTransactionStatus.WIP)), null, null, null, false);

Nicolas

--
Nicolas MALIN
Consultant
Tél : 06.17.66.40.06
Site projet : http://www.neogia.org/
-------
Société LibrenBerry
Tél : 02.48.02.56.12
Site : http://www.librenberry.net/