On 12 Mar 2010, at 05:45, Jeff Schnitzer wrote:
How, in Twig, do you rename a field?
I'm glad you brought this up. I've found simple renames are better
handled at the low level - no need to rehydrate them into instances
just to rename a property.
But for typesafe changes large or small Twig supports data migration
in a much safer, more flexible way than Objectify. Read on for details.
Objectify lets you import data from a variety of historical formats;
as you load and save data it will naturally be transformed in format:
class Person {
@Id Long id;
int age;
@AlsoLoad("name") String fullName;
}
Cool, the @AlsoLoad is quite a neat feature. Although very limited to
simple naming changes and nothing structural. All this is based on a
dangerous assumption that you can modify "live" data in place. Hardly
bullet proof.
The Twig solution is to create a new version of the type (v2) and
process your changes while leaving the live data completely isolated
and safe. Then after you have tested your changes you bump up the
version number of your live app.
So basically:
1 - Create your new class PersonNew and set its version to 2
@Version(2)
class PersonNew {
int age;
String fullName;
}
2 - Configure the "Kind name" to be the same e.g. "P" (short kind
names save DS space)
3 - Load your old Person instances and for each store a new PersonNew
instance.
Your data is now upgraded.
4 - Now you can just replace Person with PersonNew in your code and
deploy a new version.
5 - Test the version. This crucial step is not possible with
Objectifies solution.
6 - Only when you are happy your changes are correct make the new
version live. The new data version will be used and you can delete
your old data when you want.
So you see the Twig method of data migration is much safer than
Objectifies. It has the following advantages:
1 - You don't eve have a "half-updated" schema
2 - Tt works for major structural changes rather than just trivial
field renames.
3 - You can test the new data structure before going live
4 - You can revert back to you old data structure
The versions remain completely separate. Modifying live data in place
gives me heart pains.
Now, assume that the user has queries like:
Query<Person> q = ofy.query(Person.class).filter("age >", 65);
Does this query still work in your system? If so: After a few
renames, how many queries will you be running? Can you do batch gets
on their ids? I mean, after you implement batch gets, of course
What is with your obsession with batch gets? I understand they are
central in Objectify because you are always loading keys. As I said
already - even though this is not as essential in Twig it will be
added to a new load command.
Versions are an ugly solution to this problem and they make a giant
mess out of the datastore.
I certainly wouldn't feel comfortable re-factoring my live data
without testing it. Having a new version in the datastore is a lot
safer than modifying "in place"
How, in Twig, do you make an entity cached? If it's in your docs, it
is not easy to find. The Objectify version:
Oops I didn't post the CookBook page in the end. Rest assured it is a
trivial addition and I'll update the docs.
It is also often better to cache above the data layer - hardly the
killer feature you claim.
Maybe you're right, and we'll see a giant land rush for OR support.
Except that Twig has supported OR queries for quite some time, and it
still hasn't been getting traction.
No, ORs were just added last week :)
Again, it is not my intention to say this feature is inherently wrong
or bad - but that it's not the great revolution that you make it out
to be. It comes with a cost which the Objectify developers are not
currently willing to pay.
I don't blame you. It was a lot of effort to get right and it works
very elegantly without the need for bytecode enhancement or dynamic
proxies.
You seem to have an odd definition of Plain Old Java Object. POJOs
can be copied, created, cloned, whatever. You can have two of them in
memory with the same id.
Of course, but a POJO is not something that comes with a list of
requirements. I guess the level of "plainess" can vary :)
This is actually pretty core to the philosophy of Objectify: We hate
magic. We're pretty resistant to features that are not transparent,
and when we do implement features that are magical (like @Embedded),
we document the hell out of it.
I think you hit the nail on the head there Jeff. This is the key
difference in philosophies I think. Objectify prefers to keep itself
simple even if the developer needs to do more work. Twig prefers to
move complexity into the framework - at the cost of making the
framework more complex internally (the API remains simple).
A example of this is Twigs feature:
command.ensureUniqueKey()
Which does a check for an existing natural key before possibly
clobbering data.
I assume this would be against the Objectify philosophy because it can
be coded manually. I believe that the framework should encapsulate
these best practices and make them as easy as possible
Although I do appreciate Objectifies simplicity, really.
Hollow, stateful entities with lifecycles are pretty magical.
Cascading loads and saves are pretty magical. POJOs and Keys are
simple.
There really is nothing magical about an uninitialised instance.
Sounds like you are just on a witch hunt.
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.