On 26 Jan 2010, at 13:37, Jeff Schnitzer wrote:
I can't resist a conversation about framework design philosophy :-)
Oh go on then. Just a quickie.
This sort of binding (property of List<Photo>) can be convenient in
some applications, and as a longtime Hibernate user I got used to
working like this. But I don't like this abstraction in AppEngine.
Yes, for some apps you might be able to remove the "pollution" of
framework classes like Key (or OKey), but it comes with a price.
Twig and Objectify operate at very different levels of abstraction.
With Objectify you code at a lower level very aware of what is
happening at the datastore level. It involves more work but, as you
point out, if something goes wrong - it goes wrong in your own code
where you are in a better position to handle it.
With Twig you operate at a higher level that makes the persistence
layer almost completely transparent. One major advantage of this is
that you can change the way the data is stored (i.e. embedded or
separate entity) without changing your code. Making such a change
with Objectify means you need to rewrite your reference handling code
yourself.
A one-to-many relationship between Album and Photo has several
"standard" representations in AppEngine:
* The Photo could have a Key property pointing to Album
* The Photo could have a parent ancestor in its Key which points to
the Album
* The Album entity could have a List<Key> property pointing to its
Photos
Each choice has a dramatic impact on performance, what can be done in
a transaction, and how you do queries that simply cannot be glossed
over or abstracted away.
This is why you configure what type of relationship is used using:
@Embed, @Entity(PARENT), @Entity(CHILD) or @Entity(INDEPENDENT)
So you have the flexibility to choose configuration _without_
rewriting your code. Very important difference.
Currently the first type of representation is not an option. I do
want to add this as it makes very large collections that change often
much more efficient. When it is added you could reconfigure your data
schema by changing a single annotation. Such a change in Objectify
would require the developer to rewrite their entire data layer
Which does the List<Photo> represent?
Furthermore, is List<Photo> a proxy or did the photos get fetched
along with the Album? Can I serialize the Album or do I need to
detach it?
Yes instances are just normal POJOs so no problems serializing. I do
this myself with GWT.
Currently, lazy references are not supported... its a very important
feature on the TODO list.
Even worse, there are also two more possible representations:
* The Photo could have a Key property (or ancestor) pointing to an
Album that does not exist
An inconsistent datastore is a problem with any framework - including
Objectify. The trick is to use transactions where possible whenever
working on an entity group to avoid getting this situation in the
first place.
* The Album could have a List<Key> property, and some of the Keys
could point to Photos that do not exist
As above. An exception would be thrown saying which property on what
object could not be found.
Maybe these are degenerate cases, maybe not, but you'll never be able
to completely avoid them. RDBMSes have transactions and referential
integrity constraints that guarantee these later two cases can't
happen. Not so in AppEngine. You're just one
DatastoreTimeoutException away from having to deal with this situation
in your code.
If your data is inconsistent you have a problem - whether the
framework throws an exception (as in Twig) or if you receive a null
back from a finder method (as in Objectify) there is really not much
difference. You still have to clean up the mess.
This is the big mess that makes JDO on Appengine so complicated,
possibly even more complicated than it is on an RDBMS. On the other
hand... if you simply expose the Key (or OKey), the developer does a
little more work but doesn't have to figure out all the configuration.
Without proxies, all entities are serializable and GWT-able without
any special consideration.
I think that for simple cases and small data models working with Keys
and handling the references yourself is fine. When things get more
complicated it is easier to reconfigure how the data is actually
stored if you can simply change a configuration option in one place.
Actualy, JDO doesn't even offer all the necessary configuration
options, which is probably why you end up seeing Key a lot as
properties in JDO sample code.
So.... while it seems like you might be able to keep Key and other
framework classes out of your entities... for many applications I
don't think it's realistic, and for most, I don't think it's a good
idea.
IMHO, of course.
Obviously we agree to disagree on this point :) I much prefer letting
he framework handle repetitive boiler plate code with minimal
configuration.
Another feature only supported by Twig is embedded collections -
this allows
you to do a single query for Albums containing a particular photo for
example. In JDO, Objectify or any of the others this requires
multiple
queries. You configure it with a single Embed annotation like this:
We like this feature and are assimilating it now :-)
Nice one. It has honestly increased the performance of some queries
by a factor of 10 at least.
Jeff
John
--
You received this message because you are subscribed to the Google Groups "Google
App Engine for Java" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-appengine-java?hl=en.