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

Reply via email to