On Friday, Oct 3, 2003, at 22:15 Europe/Rome, Andrus Adamchik wrote:
>> Given all my comments (please, comment on them), if we managed to
>> agree on my position that separating data from logic (like in the
>> Expression, ExpressionEval, QueryTranslator case) is a bad think, I
>> would propose the following path:
>>
>> - create a new cayenne.qualifiers (can you see how much I am biased?!
>> :-] );
>> - add all relevant methods to DataContext to be able to use
>> qualifiers, still keeping Expressions working;
>> - if everything works fine, we could start deprecating Expressions,
>> with all the related classes and methods, and move up for a 2.0
>> release!! ;-]
>>
>> This path seems long, but I don't think it will take too much. All
>> other Cayenne features should be easily update where needed to use
>> the new package.
>>
>> Needless to say, I will be pleased to start writing this new package,
>> even if I will need much help in understanding how to integrate will
>> all other Cayenne classes.
>>
>> Does this make any sense?
>
>
> I am not taking any offense at constructive criticism. I can produce
> badly designed stuff just like the guy next to me :-) In fact the
> original Expressions design was done by another Cayenne committer,
> Andriy (who is also the author of arguably most complicated piece in
> Cayenne - graph sorting of database operations on commit - we are way
> ahead of EOF here). Anyway, this original design had a nested class
> hierarchy for expressions (operations vs. conditions vs...). It was an
> explosion of inner classes, and after some time I replaced it with the
> current package, for simplicity sake. He might have been on the right
> track, not me .... so lets continue this discussion.
>
> I take the point that having expressions defined as data structures
> with no behavior is bad for further extending. I most definitely agree
> that ExpressionEval must be merged into expressions, making this part
> of expression's behavior. But you still have to convince me that
> translation to SQL must be done. My argument is that there must be a
> horizontal layer separation, so there is a need of some sort of
> external translation mechanism...
I don't think we need a completely external translation mechanism, but
let's try to list the feature we want to achieve and try to sort out
the best arrangement to implement that.
> E.g. take a look at DB2QualifierTranslator. SQL generated for the LIKE
> expression is quiet different from any other database. At the same
> time, like EOF, Cayenne would support parallel work with multiple
> databases... So the user creating an expression in his code should be
> able to run the same query against DB2 and Oracle without rebuilding
> the expression....
Point taken.
> So whatever design we come up with should address the issue of
> customizing SQL generation per RDBMS flavor, given a generic
> db-independent expression.
>
>> As you can see yourself, with this arrangement you are forced of
>> thinking about all possible cases upfront. To me this is a relevant
>> sign of bad design.
>
> If we are to start rewriting expressions package from scratch, I'd
> still vote for having an upfront design of such package presented on
> this list, before we start an XP-style coding of it ;-).
Absolutely! We must take all current feature request, and also how they
have grown up, in order to find the best arrangement that could have
allowed the easiest introduction of later requests.
> Also, there are quiet a few existing expression packages (e.g. OGNL:
> http://www.ognl.org/ )... I wonder if we can integrate one of those.
> This is just something that came to my mind recently... I don't know
> if this is a viable idea.
I never give a deep look at OGNL but, for what I read, it was really
useful. The main area where I head of its usage, was to extend the WOD
syntax (in WebObjects components), in order to allow a greater number
of feature available without having to code some extra methods in the
class of the component.
I don't know exactly how this could be used for Cayenne (trying to
define expressions with a much richer semantic?), but I would take into
consideration any concreate suggestion.
Now, let's try to list the points that have been raised during this
discussion, to find out which could be the best arrangement to
implement this.
- separating data from login is (usually) a bad choice;
- it should be easy to add expressions with new semantic and patch
existing expressions for errors or for compatibility with new RDBMS;
- the SQL generated for each expression should be easily customized for
each RDBMS in order to take advantage of every custom SQL syntax,
keeping the code written using Cayenne DB independent. The coice of the
RDBMS syntax to use should be a run-time decision taken from the
deployment configuration in place.
I have though about this during the weekend, and here the outcome of my
delirium:
- ExpressionEvaluation: an interface that expressions that can be
evaluate in memory should implement; basically I think the only method
defined here should be
public boolean evalWithDataObject(org.objectstyle.cayenne.DataObject
anObject);
- SQLExpression: an interface to be implemented by expressions that can
be evaluated as SQL statements; the method defined in this interface
should be something like:
public org.objectstyle.cayenne.query.SelectQuery
queryWithAdapter(org.objectstyle.cayenne.dba.DbAdapter aDbAdapter);
- Expression: an abstract class that could be used as superclass of the
real expressions, and that could implement many common methods useful
for the creation of the SQL;
With this arrangement, every expression could be derived by Expression
and should implement both the ExpressionEvaluation and the
SQLExpression interfaces. This will allow for expression that could be
only evaluated in memory and also for expressions that could be only
evaluated on DB (for example expressions that translates to query using
special syntax like the INTERMEDIA one, available with Oracle, that are
not easily emulated in memory).
The method "queryWithAdapter" should use the given adapter to customize
the SQL generation for any given RDBMS supported; I have not figured
out exactly how, however. I am not sure even if this method should
return a SelectQuery or something else entirely, as the processes of
creating the whole SQL string is not yet cristal clear to me, yet.
Anyway, this is still the most troubled point also for other reasons:
it is easy to factor into DbAdapter (and implement them into the
subclasses) the differences of SQL syntax for the known situations, but
it's quite hard to add something afterwards.
What I am missing here is the Objective-C category concept, that will
allow some methods to be added to a given class, also by an external
package. :-[
I have not found a solution I am proud of (yet?!?), but I am posting
this message anyway, to let you comment on my current feeling
immediately. I will follow up as soon as I have new thoughts on this
topic.
Does this make any sense?
Giulio Cesare
This archive was generated by hypermail 2.0.0 : Mon Oct 06 2003 - 04:53:02 EDT