As a practice exercise to see how the new API works on a real system, I
migrated an app completely over to the new syntax. There were about 150 queries
to change (it is a small app), and each one only took about a minute to
re-enter and visually check.
The new syntax is dramatically easier to read. I hope this will translate in
the long term to fewer bugs.
A couple of real world syntax issues raised themselves and I thought I'd bring
them up here for review. This is all real code in a real app.
1. Before
List<SupportPassword> oldPasswords = ObjectSelect.query(SupportPassword.class).
where(SupportPassword.EXPIRES_ON.lt(new Date())).
select(context);
The main lack of clarity here is "lt". Is it worth having an alias "before" for
"lt"?
where(SupportPassword.EXPIRES_ON.before(new Date())).
I don't know whether we need the clutter in the API, but in my brain that makes
it much easier to read.
2. Lots of AND
List<Contact> users = ObjectSelect.query(Contact.class).
where(Contact.EMAIL_ADDRESS.eq(email).
andExp(Contact.COLLEGE.eq(college)).
andExp(Contact.GIVEN_NAME.eq(firstName)).
andExp(Contact.LAST_NAME.eq(lastName))).
select(context);
You can easily get lost in all those brackets, especially for more complex
expressions than above. Would it make sense to write this:
List<Contact> users = ObjectSelect.query(Contact.class).
where(Contact.EMAIL_ADDRESS.eq(email).
where(Contact.COLLEGE.eq(college)).
where(Contact.GIVEN_NAME.eq(firstName)).
where(Contact.LAST_NAME.eq(lastName))).
select(context);
That would require this:
public ObjectSelect<T> where(Expression expression) {
if (this.where == null) {
this.where = expression;
} else {
this.where = this.where.andExp(expression);
}
return this;
}
If we look to Rails for ideas, they chain multiple "where" instructions with an
implied AND. That can be very convenient when you construct a query in one
place, and then add additional restrictive qualifiers onto it in other parts of
the code or in conditionals.
query = ObjectSelect.query(Contact.class).
where(Contact.EMAIL_ADDRESS.eq(email).
where(Contact.COLLEGE.eq(college));
if (firstName != null) {
query = query.where(Contact.GIVEN_NAME.eq(firstName)).
where(Contact.LAST_NAME.eq(lastName)));
}
List<Contact> users = query.select(context);
Also, and probably more importantly, ordering like this makes sense:
List<Contact> users =
query.order(Contact.GIVEN_NAME.asc()).order(Contact.LAST_NAME.asc()).select(context);
where we want to create two levels of sort. So, we don't always want
instructions to replace previous ones but to add onto them. Similarly we might
add several prefetches to a query which are additive.
Thoughts?
Ari
--
-------------------------->
Aristedes Maniatis
ish
http://www.ish.com.au
Level 1, 30 Wilson Street Newtown 2042 Australia
phone +61 2 9550 5001 fax +61 2 9550 4001
GPG fingerprint CBFB 84B4 738D 4E87 5E5C 5EFA EF6A 7D2E 3E49 102A