Factory vs Executor, as well as class naming

82 views
Skip to first unread message

Christopher Deckers

unread,
Mar 31, 2013, 4:39:24 PM3/31/13
to jooq...@googlegroups.com
Hi Lukas,

I have a(nother?) silly question.

Quoting you:
"While Factory is all static, Executor initialises objects with a Configuration. In fact, Executor and Factory share a lot of API, even if informally by convention. This leads to things like executor.fetch(Factory.select()) being the same as executor.select().fetch()".

Why confuse users with this artificial distinction (static vs contextual) between Factory and Executor? Why not put all the static methods of Factory in the Executor class and get rid of Factory (and static import Executor)?

Also, I don't think Executor is a good name. It is the starting point of creating a query and that should be obvious from the name. Moreover, the query that Executor allows to build will eventually be transformed to a String (getSQL()): it is not necessarily executed, it is more like a factory. I think the name "Factory" is way better than "Executor" (no matter whether you consider the context-aware methods or static ones, that I just suggested to merge in one single class).
I also personaly don't like names like "Factory", "Executor", etc. While I reckon they are short, they are too broad/generic and in a complex application do not immediately make the link to jOOQ. They also don't help auto imports, code navigation, Google searches (there are many generic classes with the same name), etc. In my view, a name like JOOQFactory would be unambiguous: we would know what it creates just from the name and there would be no name collisions.

Please let me know what you think!

-Christopher

Simone Giacomelli

unread,
Apr 1, 2013, 12:23:44 PM4/1/13
to jooq...@googlegroups.com
Hi Christopher, Lukas, guys,

>Why confuse users with this artificial distinction (static vs contextual) between Factory and Executor? [...]

I agree. It confuses me too. 

> I also personaly don't like names like "Factory", "Executor", etc. While I reckon they are short, 
> they are too broad/generic and in a complex application do not immediately make the link 
> to jOOQ. They also don't help auto imports, code navigation, Google searches (there are many 
> generic classes with the same name), etc. In my view, a name like JOOQFactory [...]

Here, my opinion is different: for me one or another is quite ok. Java packages are also for this purpose.
If I look how many "Configurations" class I have in the class path: at least 14 (derby,javax.security,testng,jooq,spring,etc...)

I like how Eclipse Jetty name the web server component class: "Server" :) 
In opposition to tomcat where the web server is actually called "Tomcat". It is ok. too.

My 2 cents.

greetings
Simone


Lukas Eder

unread,
Apr 1, 2013, 1:56:09 PM4/1/13
to jooq...@googlegroups.com
Hi Christopher,

> Hi Lukas,
>
> I have a(nother?) silly question.

Not so silly!
Thanks for bringing up these things. It was about time someone
challenged my API decisions - luckily before I have released jOOQ 3.0
GA :-)

OK, so there are three topics in this discussion. We can split the
thread in the near future, if things start getting unrelated.

Topic #1: Static vs. contextual Factory methods
===============================================

> Quoting you:
> "While Factory is all static, Executor initialises objects with a
> Configuration. In fact, Executor and Factory share a lot of API, even if
> informally by convention. This leads to things like
> executor.fetch(Factory.select()) being the same as
> executor.select().fetch()".
>
> Why confuse users with this artificial distinction (static vs contextual)
> between Factory and Executor? Why not put all the static methods of Factory
> in the Executor class and get rid of Factory (and static import Executor)?

OK, let's establish terms for this discussion. I like your wording:

1. static - QueryParts are created through static methods from the Factory
2. contextual - QueryParts are created with a Configuration
"attached", through the Executor

Things used to be the way you proposed in jOOQ 2.x. I.e. static and
contextual methods were mixed in a single Factory. The problem this
cause was an essential problem for a fluent API. Because in Java,
static and instance methods occupy the same namespace, Query factory
methods were restricted to being contextual. This is a bit annoying
for two secondary use-cases:

1. Subqueries. Subqueries do not need to be created contextually.
Things would get more readable, if you can just write "select()"
instead of "create.select()"
2. Batch execution. When putting several queries in a batch-style
method, you again had to create queries contextually, even if the
context was not needed.

So, there is a relevant use-case for duplicating the API for query
construction into a static and a contextual part. I think we can agree
on that (?), so let's discuss whether the current solution is good
enough (see topic #2)

Topic #2: "Executor" as a name
==============================

> Also, I don't think Executor is a good name. It is the starting point of
> creating a query and that should be obvious from the name. Moreover, the
> query that Executor allows to build will eventually be transformed to a
> String (getSQL()): it is not necessarily executed, it is more like a
> factory. I think the name "Factory" is way better than "Executor" (no matter
> whether you consider the context-aware methods or static ones, that I just
> suggested to merge in one single class).

Yes, I don't really like the term "Executor" either. It was an obvious
choice in the first refactoring steps of jOOQ 3.0. Meanwhile, the
greater picture is more clear, and it becomes evident that the type
shouldn't be called Executor. On a side-note, it is a bit ironic that
you bring this up just shortly after I've posted this article here
about regular APIs :-)
http://blog.jooq.org/2013/03/30/how-to-design-a-good-regular-api

I think what is really confusing is the fact that users have to make a
conscious decision whether to use the Executor or the Factory as the
entry point for the jOOQ DSL and/or for QueryPart construction. In
other words, the purely technical reason for this distinction (cannot
overload static / non-static) doesn't pull the weight of the added
Executor type.

It would be much better if the single entry point to the jOOQ API was
the Factory, but not in the way you suggest (as this is not possible
in Java). An alternative solution to this problem would be to add a
static "with" keyword to the Factory, with which an "Executor" could
be created (let's keep calling it Executor and rename it later). So
this would be how you'd create "static" subqueries:

select().from(TABLE)
.where(conditions)
.orderBy(ID);

Here's how you'd create "contextual", and thus executable queries:

with(configuration)
.select()
.from(TABLE)
.orderBy(ID)
.fetch();

Here's how you'd use batch queries:

with(connection, dialect) // Alternatively to with(configuration)
.batch(
insertInto(TABLE_A).values(1, 2, 3),
insertInto(TABLE_B).values(4, 5, 6)
)
.execute();

So instead of establishing an Executor instance and letting users know
of it, there would be several overloaded "with()" methods that would
return an Executor instance. They would reflect today's Executor
constructors. (The need for overloading Executor(Configuration) with
Executor(Connection, SQLDialect) and other constructors is being
discussed in another thread).

This would allow for keeping the required distinction between static
and contextual QueryPart construction, but it would seem like the API
was more unified, and users only need to remember Factory as an entry
point.

Now the object returned by "with()" doesn't need to be called
Executor. Neither do we need to use the term "with()", as that might
cause confusion in the future, once jOOQ supports common table
expressions. But you get the idea. What would you think of this
alternative route?

Topic #3: Factory and Executor as short names in general
========================================================

> I also personaly don't like names like "Factory", "Executor", etc. While I
> reckon they are short, they are too broad/generic and in a complex
> application do not immediately make the link to jOOQ. They also don't help
> auto imports, code navigation, Google searches (there are many generic
> classes with the same name), etc. In my view, a name like JOOQFactory would
> be unambiguous: we would know what it creates just from the name and there
> would be no name collisions.

Factory is qualified with org.jooq.impl. Packages do a good job of
disambiguating things, in my opinion. If you're using jOOQ, you will
be using it in a narrow context, i.e. within a DAO. The likelyhood of
ambiguities is slim. Even then, you'll probably static-import
org.jooq.impl.Factory.*;

Also, I don't see a point to prefixing the Factory but not all the
other 100 API types. According to your argument, these types might
need renaming too:

- Field (as in java.lang.reflect.Field)
- Record (dozens of ambiguous occurrences)
- Table (Swing, probably?)
- Schema (XSD, etc)
- You name it

We could discuss a rename from Factory to JOOQ or something like that,
of course. But I will need very compelling reasons to re-write the
whole manual and explain to everyone that the Factory has been
beautified :-)

Cheers
Lukas

PS: Thanks again for bringing these things up!

Christopher Deckers

unread,
Apr 1, 2013, 2:27:21 PM4/1/13
to jooq...@googlegroups.com
Hi Lukas,

Topic #1: Static vs. contextual Factory methods
===============================================
 
Things used to be the way you proposed in jOOQ 2.x. I.e. static and

contextual methods were mixed in a single Factory. The problem this
cause was an essential problem for a fluent API. Because in Java,
static and instance methods occupy the same namespace, Query factory
methods were restricted to being contextual.

I was wondering if the same method could be both contextual and static, but I am not sure whether there are so many cases that justify it. Since it used to be that way (2.x) you have more practical experience so I can't really argue.


So, there is a relevant use-case for duplicating the API for query
construction into a static and a contextual part.

I wonder then: could the query creation be fully static (like a capture of the user's declarations) and only its rendering/execution be contextual? Or are there cases where to represent the query you need context? And in that latter case, can't this just be postponed to execution/rendering time?
Because maybe you should just have everything in the (current) Factory and create the Executor (whatever the name is) without fluent call, only a QueryPart parameter and 2 methods:

Executor executor = new Executor(<context_params>, QueryPart);
executor.getSQL()
or
executor.execute()
 
 
Topic #2: "Executor" as a name
==============================

An alternative solution to this problem would be to add a
static "with" keyword to the Factory, with which an "Executor" could
be created (let's keep calling it Executor and rename it later).

If my suggestion above has counter arguments, then this could be a possible fallback. But I would prefer to have some feedback on my suggestion before elaborating on that one :)

 
Topic #3: Factory and Executor as short names in general
========================================================
 
Even then, you'll probably static-import
org.jooq.impl.Factory.*;

Yes, this is the rule that probably makes your argument more valid.
My experience is that everytime I use a "List" and I ctrl+shift+o and Eclipse asks me whether I mean "java.util.List" or the deprecated/outdated/irrelevant "java.awt.List" instead of auto importing irritates me.

 
- Table (Swing, probably?)

Bad choice, all Swing components start with J, and most libraries that ship Swing components kepts that convention. JTable, JCheckBox, even JWebBrowser ;)
Also try in your Eclipse workspace ctrl+T and then "javax.swing.*Factory": none are just "Factory".

 
We could discuss a rename from Factory to JOOQ or something like that,
of course. But I will need very compelling reasons to re-write the
whole manual and explain to everyone that the Factory has been
beautified :-)

Honestly, if the API only has such naming issues (whether we agree or not), then the goal of having a solid API is reached :)

Cheers,
-Christopher

Lukas Eder

unread,
Apr 1, 2013, 2:49:50 PM4/1/13
to jooq...@googlegroups.com
Hi Christopher,

2013/4/1 Christopher Deckers <chr...@gmail.com>:
> Hi Lukas,
>
>> Topic #1: Static vs. contextual Factory methods
>> ===============================================
>>
>> Things used to be the way you proposed in jOOQ 2.x. I.e. static and
>>
>> contextual methods were mixed in a single Factory. The problem this
>> cause was an essential problem for a fluent API. Because in Java,
>> static and instance methods occupy the same namespace, Query factory
>> methods were restricted to being contextual.
>
> I was wondering if the same method could be both contextual and static, but
> I am not sure whether there are so many cases that justify it. Since it used
> to be that way (2.x) you have more practical experience so I can't really
> argue.

I'm not sure how the same method could be both contextual and static.
You can't do this in Java:

class X {
static void x() {}
void x() {}
}

Of course, it would be possible to make the "static version" take the
context as an argument, but that would result in an awkward DSL entry
point:

class X {
static void x(Configuration c) {}
void x() {}
}

>> So, there is a relevant use-case for duplicating the API for query
>> construction into a static and a contextual part.
>
>
> I wonder then: could the query creation be fully static (like a capture of
> the user's declarations) and only its rendering/execution be contextual? Or
> are there cases where to represent the query you need context? And in that
> latter case, can't this just be postponed to execution/rendering time?
> Because maybe you should just have everything in the (current) Factory and
> create the Executor (whatever the name is) without fluent call, only a
> QueryPart parameter and 2 methods:
>
> Executor executor = new Executor(<context_params>, QueryPart);
> executor.getSQL()
> or
> executor.execute()

I would really really regret losing the ability to just append
".fetch()", ".execute()", and all the other many methods to a Query /
ResultQuery in a fluent style. I had given this much thought at the
beginning of jOOQ 3.0, because it would be the easiest solution to
this problem. But it would be a huge loss of functionality and fluency
for jOOQ. So there must be a way to construct Query / ResultQuery
objects in a contextual way.

Other APIs (such as QueryDSL in Java, SLICK in Scala, LINQ in .NET)
put less weight into this argument. Their APIs are more "polluted"
with host language elements, such as the "new" keyword. One of jOOQ's
key features is to make users really feel as if typesafe inline SQL
was possible in Java.

Of course, these arguments don't exclude alternative ways to execute
things. Already today, you can do:

Executor executor = new Executor(<context_params>);
executor.execute(query);
executor.fetch(resultQuery);
executor.batch(query1, query2).execute();

But as I said, you can also do:

executor.select().from(...).where(...).fetch();

Which I find really nice...

>> Topic #2: "Executor" as a name
>> ==============================
>> An alternative solution to this problem would be to add a
>> static "with" keyword to the Factory, with which an "Executor" could
>> be created (let's keep calling it Executor and rename it later).
>
>
> If my suggestion above has counter arguments, then this could be a possible
> fallback. But I would prefer to have some feedback on my suggestion before
> elaborating on that one :)

It has. Strong and emotional ones :-) So I'm looking forward to your
elaboration.

>>
>> Topic #3: Factory and Executor as short names in general
>> ========================================================
>>
>> Even then, you'll probably static-import
>> org.jooq.impl.Factory.*;
>
>
> Yes, this is the rule that probably makes your argument more valid.
> My experience is that everytime I use a "List" and I ctrl+shift+o and
> Eclipse asks me whether I mean "java.util.List" or the
> deprecated/outdated/irrelevant "java.awt.List" instead of auto importing
> irritates me.

I know. I hate the java.awt.List as much as you do.

>>
>> - Table (Swing, probably?)
>
>
> Bad choice, all Swing components start with J, and most libraries that ship
> Swing components kepts that convention. JTable, JCheckBox, even JWebBrowser
> ;)

"J" ... true, I forgot. Well, ok, I have these "Table" types on my classpath:
- ch.epfl.lamp.compiler.msil.util.Table
- com.google.common.collect.Table
- javax.persistence.Table
- liquibase.database.structure.Table
- org.apache.batik.svggen.font.table.Table
- org.apache.fop.fo.flow.table.Table
- org.h2.table.Table
- org.hsqldb.Table

And many others

> Also try in your Eclipse workspace ctrl+T and then "javax.swing.*Factory":
> none are just "Factory".

I have:

- net.sf.cglib.proxy.Factory
- org.apache.derby.iapi.db.Factory
- org.hamcrest.Factory
- sun.org.mozilla.javascript.internal.xml.XMLLib.Factory

And if I'm not mistaken, Apache XMLBeans generates a Factory class for
every XSD type. So I think people can live with another
org.jooq.impl.Factory :-)

>> We could discuss a rename from Factory to JOOQ or something like that,
>> of course. But I will need very compelling reasons to re-write the
>> whole manual and explain to everyone that the Factory has been
>> beautified :-)
>
> Honestly, if the API only has such naming issues (whether we agree or not),
> then the goal of having a solid API is reached :)

Thanks. I take that as an "I give up (on the Factory name discussion)" :-)

Cheers
Lukas

Christopher Deckers

unread,
Apr 1, 2013, 3:20:12 PM4/1/13
to jooq...@googlegroups.com
Hi Lukas,
 
> I was wondering if the same method could be both contextual and static, but
> I am not sure whether there are so many cases that justify it. Since it used
> to be that way (2.x) you have more practical experience so I can't really
> argue.

I think I was not clear with what I was trying to say: do we really need both contextual and static methods with different intent whether contextual and static?
 
 
I would really really regret losing the ability to just append
".fetch()", ".execute()", and all the other many methods to a Query /
ResultQuery in a fluent style.

So, all this complexity comes from the fact that you want fluency in crafting the query AND running it, from the same chain.

Let's think of an alternative fluent-like way that expresses query definition (static) and it's contextual usage.

Assume "import static org.jooq.impl.Factory.*", and I will also use your "with" approach :)

with(connection, dialect).define(
    batch(

        insertInto(TABLE_A).values(1, 2, 3),
        insertInto(TABLE_B).values(4, 5, 6)
    )
).execute();

 
>> Topic #2: "Executor" as a name
>> ==============================

It has. Strong and emotional ones :-) So I'm looking forward to your
elaboration.

I still want to clear topic #1 first :)
 

I know. I hate the java.awt.List as much as you do.

Thanks. I take that as a "you have a point, somehow" :)
 
Thanks. I take that as an "I give up (on the Factory name discussion)" :-)

Well, whatever!

Cheers,
-Christopher

Durchholz, Joachim

unread,
Apr 2, 2013, 6:13:40 AM4/2/13
to jooq...@googlegroups.com
> I also personaly don't like names like "Factory",
> "Executor", etc. While I reckon they are short,
> they are too broad/generic and in a complex
> application do not immediately make the link to
> jOOQ. They also don't help auto imports, code
> navigation, Google searches (there are many
> generic classes with the same name), etc.

+1

Choosing a nongeneric name also helps fight feature bloat in the class. With a precise name, it's easy to decide whether a new function belongs to it or not; with a generic name, adding a function that doesn't quite fit rings no alarm bells.
Coming up with a good class name can be hard and take much time though. *looks at his own code...*

Peter Cooner

unread,
Apr 2, 2013, 11:58:45 AM4/2/13
to jooq...@googlegroups.com
On Mon, Apr 1, 2013 at 1:56 PM, Lukas Eder <lukas...@gmail.com> wrote:

Topic #1: Static vs. contextual Factory methods
===============================================


I really liked the separating of the contextual / static query functions in JOOQ 3 - it just feels right - like real SQL. The guys I'm working with found it liberating.
 

Topic #2: "Executor" as a name
==============================

    select().from(TABLE)
            .where(conditions)
            .orderBy(ID);

Here's how you'd create "contextual", and thus executable queries:

    with(configuration)
            .select()
            .from(TABLE)
            .orderBy(ID)
           .fetch();

Here's how you'd use batch queries:

    with(connection, dialect) // Alternatively to with(configuration)
    .batch(
        insertInto(TABLE_A).values(1, 2, 3),
        insertInto(TABLE_B).values(4, 5, 6)
    )
    .execute();

Now the object returned by "with()" doesn't need to be called
Executor. Neither do we need to use the term "with()", as that might
cause confusion in the future, once jOOQ supports common table
expressions. But you get the idea. What would you think of this
alternative route?


I really like the idea of with(connection, dialect) - how would you attach the schema mappings? (they already use a similar .withMapping() function style (sort of).

Though I'm a little worried about the fact that right now I have to extend Executor myself for use in Google Guice Injection. This might not play well with that.


 
Topic #3: Factory and Executor as short names in general
========================================================


For myself, I've found static importing "Factory" a little strange - maybe it could be renamed to something like Queries or what if they were broken out into different classes named for the section they are from such as Selects, Froms, Joins, Conditions (or Wheres) etc... 

This is how I've token to implementing extensions to JOOQ - creating static functions in a class which is then static imported. I could give examples, if people are interested but I thought that might be off topic. :-)

Pete



Lukas Eder

unread,
Apr 2, 2013, 3:14:56 PM4/2/13
to jooq...@googlegroups.com
Hi Christopher,

>> > I was wondering if the same method could be both contextual and static, but
>> > I am not sure whether there are so many cases that justify it. Since it used
>> > to be that way (2.x) you have more practical experience so I can't really
>> > argue.
>
> I think I was not clear with what I was trying to say: do we really need both contextual and static methods with different intent whether contextual and static?

So I guess I didn't understand you here. And probably still don't.
What do you mean by the above?

>> I would really really regret losing the ability to just append
>> ".fetch()", ".execute()", and all the other many methods to a Query /
>> ResultQuery in a fluent style.
>
> So, all this complexity comes from the fact that you want fluency in crafting the query AND running it, from the same chain.

If you want to call it "complexity". Yes, that's the reason why the
API entry points are duplicated as of now. Many users like the way
things are - except for the confusion about the Executor.

> Let's think of an alternative fluent-like way that expresses query definition (static) and it's contextual usage.
>
> Assume "import static org.jooq.impl.Factory.*", and I will also use your "with" approach :)
>
> with(connection, dialect).define(
>
> batch(
> insertInto(TABLE_A).values(1, 2, 3),
> insertInto(TABLE_B).values(4, 5, 6)
> )
> ).execute();

That's not much different from the following, which you can already do today:

new Executor(connection, dialect).batch(
insertInto(TABLE_A).values(1, 2, 3),
insertInto(TABLE_B).values(4, 5, 6)
).execute();

If I introduce Factory.with() methods, this can be phrased alternatively:

with(connection, dialect).batch(
insertInto(TABLE_A).values(1, 2, 3),
insertInto(TABLE_B).values(4, 5, 6)
).execute();

I don't think there is any need for an additional "define" keyword in the DSL.

>> >> Topic #2: "Executor" as a name
>> >> ==============================
>>
>> It has. Strong and emotional ones :-) So I'm looking forward to your
>> elaboration.
>
> I still want to clear topic #1 first :)

What's left to clear? I think you're putting too much weight into the
Executor. While it sounds like an important API element, it's just
another "XXXStep" class. With an unfortunate name. It has absolutely
no meaning / lifecycle / weight, except maybe some historic one, which
I'm about to remove. E.g. in 3.0-RC3, Executor will no longer
implement Configuration, but contain one (although, I'm not even sure
about that...)

>> I know. I hate the java.awt.List as much as you do.
>
> Thanks. I take that as a "you have a point, somehow" :)
>
>> Thanks. I take that as an "I give up (on the Factory name discussion)" :-)
>
> Well, whatever!

You know, I was just kidding. We're clear about "Executor", which I'll
work into the DSL API. But I'll create a new thread on the user group
to collect compelling alternatives to "Factory". I won't put much
effort into finding one myself, but maybe someone has an inspiration.

Cheers
Lukas

Lukas Eder

unread,
Apr 2, 2013, 3:28:11 PM4/2/13
to jooq...@googlegroups.com
Hi Christopher,

>>> I know. I hate the java.awt.List as much as you do.
>>
>> Thanks. I take that as a "you have a point, somehow" :)
>>
>>> Thanks. I take that as an "I give up (on the Factory name discussion)" :-)
>>
>> Well, whatever!
>
> You know, I was just kidding. We're clear about "Executor", which I'll
> work into the DSL API. But I'll create a new thread on the user group
> to collect compelling alternatives to "Factory". I won't put much
> effort into finding one myself, but maybe someone has an inspiration.

The new thread is here:
https://groups.google.com/forum/?fromgroups=#!topic/jooq-user/U4i33PL_-8Y

Lukas Eder

unread,
Apr 2, 2013, 3:31:25 PM4/2/13
to jooq...@googlegroups.com
Hi Joachim,

2013/4/2 Durchholz, Joachim <Joachim....@hennig-fahrzeugteile.de>:
>> I also personaly don't like names like "Factory",
>> "Executor", etc. While I reckon they are short,
>> they are too broad/generic and in a complex
>> application do not immediately make the link to
>> jOOQ. They also don't help auto imports, code
>> navigation, Google searches (there are many
>> generic classes with the same name), etc.
>
> +1
>
> Choosing a nongeneric name also helps fight feature bloat in the class.
> With a precise name, it's easy to decide whether a new function belongs to it or not; with a generic name, adding a function that doesn't quite fit rings no alarm bells.

That is true in general, although not for the "Factory". Its intent is
clearly to provide an entry point to the jOOQ DSL and to allow for
creating QueryParts. Two types of creation operations that deserve to
be put into a "factory". I agree with you as far as the Executor is
concerned. Note that the Executor is being reworked before jOOQ 3.0 is
released. See the various ongoing discussions on the group related to
this.

> Coming up with a good class name can be hard and take much time though. *looks at his own code...*

I know. Factory seemed like a "good enough" fit for the job, so far.
Feel free to provide suggestions in this thread here, though:
https://groups.google.com/forum/?fromgroups=#!topic/jooq-user/U4i33PL_-8Y

Cheers
Lukas

Lukas Eder

unread,
Apr 2, 2013, 3:38:17 PM4/2/13
to jooq...@googlegroups.com
2013/4/2 Peter Cooner <petr...@gmail.com>:
>
> On Mon, Apr 1, 2013 at 1:56 PM, Lukas Eder <lukas...@gmail.com> wrote:
>>
>>
>> Topic #1: Static vs. contextual Factory methods
>> ===============================================
>>
>
> I really liked the separating of the contextual / static query functions in
> JOOQ 3 - it just feels right - like real SQL. The guys I'm working with
> found it liberating.

Thanks Peter. I'm glad you've mentioned it. I remember that Sergey
Epik also expressed his liking for the "contextual" API
"with()" itself would be overloaded several times, just like today's
jOOQ 3.0-RC2 Executor constructors:
http://www.jooq.org/javadoc/latest/org/jooq/impl/Executor.html

Besides, I could imagine that you could call with() several times in a
row, kind of like:

with(connection)
.with(dialect)
.with(settings)
.select(...)
.from(...)
.fetch();

As I said before, "with()" is not a final decision. I have to assess
whether "with()" will cause conflicts with a future support for common
table expressions

> Though I'm a little worried about the fact that right now I have to extend
> Executor myself for use in Google Guice Injection. This might not play well
> with that.

Feel free to elaborate on that (possibly in another thread if not
quite on-topic?). Note though, that I might keep a public default
constructor around in the type returned by "with()". This would allow
for keeping things the way they are today:

new TheTypeFormerlyKnownAsExecutor()
.with(connection)
.with(dialect)
...

>>
>> Topic #3: Factory and Executor as short names in general
>> ========================================================
>>
>
> For myself, I've found static importing "Factory" a little strange - maybe
> it could be renamed to something like Queries or what if they were broken
> out into different classes named for the section they are from such as
> Selects, Froms, Joins, Conditions (or Wheres) etc...

Please suggest your ideas on this thread here:
https://groups.google.com/forum/?fromgroups=#!topic/jooq-user/U4i33PL_-8Y

> This is how I've token to implementing extensions to JOOQ - creating static
> functions in a class which is then static imported. I could give examples,
> if people are interested but I thought that might be off topic. :-)

Yes, sure! Success stories, experiences, etc are always welcome. Maybe
in another thread, though...

Cheers
Lukas

Lukas Eder

unread,
Apr 2, 2013, 3:41:19 PM4/2/13
to jooq...@googlegroups.com
Hi Simone

2013/4/1 Simone Giacomelli <simone.g...@gmail.com>:
> Hi Christopher, Lukas, guys,
>
>>Why confuse users with this artificial distinction (static vs contextual)
>> between Factory and Executor? [...]
>
> I agree. It confuses me too.

Yes, this point has been well received.

>> I also personaly don't like names like "Factory", "Executor", etc. While I
>> reckon they are short,
>> they are too broad/generic and in a complex application do not immediately
>> make the link
>> to jOOQ. They also don't help auto imports, code navigation, Google
>> searches (there are many
>> generic classes with the same name), etc. In my view, a name like
>> JOOQFactory [...]
>
> Here, my opinion is different: for me one or another is quite ok. Java
> packages are also for this purpose.
> If I look how many "Configurations" class I have in the class path: at least
> 14 (derby,javax.security,testng,jooq,spring,etc...)

Thanks for the feedback. Feel free to bring it up again on this thread here:
https://groups.google.com/forum/?fromgroups=#!topic/jooq-user/U4i33PL_-8Y

> I like how Eclipse Jetty name the web server component class: "Server" :)
> In opposition to tomcat where the web server is actually called "Tomcat". It
> is ok. too.

Yes, Server is quite ambiguous among libraries, as well. "Tomcat"
would be an argument in favour of renaming the Factory to "JOOQ" :-)

Cheers
Lukas

Christopher Deckers

unread,
Apr 5, 2013, 8:16:10 AM4/5/13
to jooq...@googlegroups.com
Hi Lukas,

I strongly think there should not be a duplication of Factory (JooqDsl) methods to the Executor type. I really think that separation of concern should prevail:
- One entry point to build a query, using a query building DSL.
- One entry point to rendering a query, using a query rendering DSL.

This would mean having 2 different factories (JooqDsl, JooqRenderingDsl) but this seems overkill so I think that having a "with" keyword on the JooqDsl that returns a JooqRenderingDsl instance is not that bad:

import jooq.org.JooqDsl.*

with(Connection, Dialect).bind(Query).fetch(); or .execute()

This would greatly simplify the API, by reducing the number of exposed methods, reducing the number of ways to do the same thing, and making a clear distinction between which part of the API does what.
Note that I don't think ".bind(Query)" breaks the DSL aspect of JOOQ. It is very similar to existing APIs such as ".select(Field...)".

Or am I missing something?

Cheers,
-Christopher

Lukas Eder

unread,
Apr 5, 2013, 11:05:48 AM4/5/13
to jooq...@googlegroups.com
Hi Christopher,

2013/4/5 Christopher Deckers <chr...@gmail.com>:
> Hi Lukas,
>
> I strongly think there should not be a duplication of Factory (JooqDsl)
> methods to the Executor type. I really think that separation of concern
> should prevail:
> - One entry point to build a query, using a query building DSL.
> - One entry point to rendering a query, using a query rendering DSL.
>
> This would mean having 2 different factories (JooqDsl, JooqRenderingDsl)
> [...]

Sheesh, these frequent changes of terms nowadays ;-)
To get on common grounds again (also for the passive readers of this thread):

- JooqDsl = org.jooq.impl.Factory = "static factory"
- JooqRenderingDsl = org.jooq.impl.Executor (and all its derived
objects, such as RenderContext, BindContext, etc.) = "contextual
factory"

The above terms are understood as of jOOQ 3.0-RC2

> [...] but
> this seems overkill so I think that having a "with" keyword on the JooqDsl
> that returns a JooqRenderingDsl instance is not that bad:
>
> import jooq.org.JooqDsl.*
>
> with(Connection, Dialect).bind(Query).fetch(); or .execute()

So, "bind(Query)" or "define(Query)", this is just a more verbose way
of directly executing the query:

with(Connection, Dialect).fetch(ResultQuery);
with(Connection, Dialect).execute(Query);

Which is just slightly different from today's (jOOQ 3.0-RC2):

new Executor(Connection, Dialect).fetch(ResultQuery);
new Executor(Connection, Dialect).execute(Query);

Or from the previous (jOOQ 2.6):

new Factory(Connection, Dialect).fetch(ResultQuery);
new Factory(Connection, Dialect).execute(Query);

Let's not focus on that aspect too much, as this is already in place
(more or less).

> This would greatly simplify the API, by reducing the number of exposed
> methods, reducing the number of ways to do the same thing, and making a
> clear distinction between which part of the API does what.
>
> Note that I don't think ".bind(Query)" breaks the DSL aspect of JOOQ. It is
> very similar to existing APIs such as ".select(Field...)".

OK, so when we disregard the "define()" / "bind()" sub-discussion,
then your suggestion comes down to removing the "org.jooq.Attachable"
aspect of "org.jooq.Query" in a way that a Query is a "dumb" AST,
which can be manipulated by something we used to call a contextual
factory. By manipulation, we understand things like:

- Rendering SQL to a StringBuilder
- Binding variables to a PreparedStatement
- Executing it

From this "dumbness" we could conclude that a contextual factory (with
its API partially duplicated from the static factory) would no longer
be needed, and thus, the confusion over the two types would be gone.
We'd be left with a simple type that can do only things like fetch(),
execute(), etc.

Right? If so, yes, you're correct, technically. This would simplify
some of jOOQ's API. I think that this idea first showed up in May 2012
on this user group:
https://groups.google.com/d/msg/jooq-user/hBceRSbufg8/PGn9f4NEt5IJ

This is similar to what CriteriaQuery does in JPA. Some pseudo-code:

// jOOQ
with(...).bind(Query).fetch();
with(...).fetch(Query);

// JPA
em.createQuery(CriteriaQuery).getResultList();

In the early days of jOOQ 3.0, I had explored this possibility. But...

> Or am I missing something?

Yes. In my opinion, you're missing these things:

1. Many users seem to like the fact that queries can execute
themselves. So I want to address this, somehow.
2. This would be quite a bit of a change. Getting rid of "Attachable"
queries (i.e. self-executable queries) isn't simple.
3. It would break semantic versioning, as such big changes aren't
expected between release candidates. Similar to ConnectionProvider,
which had to wait for 3.0

Now, I'm not completely opposed to your idea, and I still haven't
decided for good. Obvious advantages of your approach are:

A. Clean separation of concerns (as recently mentioned also by Joachim)
B. Less (or even no) per-execution state in Query
C. Thus: Closing in on Query thread-safety and reusability
D. Probably many other advantages

But I think that 1), 2), and 3) are good reasons why we shouldn't
change anything substantial here, in jOOQ 3.x, keeping an open mind
for potential options for jOOQ 4.0. If we delve into the clean
separation of API concerns (also: model API vs. DSL API!), we can keep
ourselves busy easily until the end of 2013. I don't want to postpone
the release of row value expressions until then.

Can we agree that we keep discussing these interesting thoughts, but
consider them out of scope for jOOQ 3.0?

Cheers
Lukas

Christopher Deckers

unread,
Apr 5, 2013, 11:38:18 AM4/5/13
to jooq...@googlegroups.com
Hi Lukas,

Sarcasm mode: on
(yeah, I am trying to be nastier than last time!)
 

So, "bind(Query)" or "define(Query)", this is just a more verbose way
of directly executing the query:

    with(Connection, Dialect).fetch(ResultQuery);
    with(Connection, Dialect).execute(Query);

You are right, now I am coding all my applications in a single class. No more verbosity!

Also, I found that auto executing things in unrelated context is a wonderful idea, so I am suggesting Oracle to change:
SwingUtilities.invokeLater(Runnable)
to:
Runnable.invokeInSwing()

Yes, it is less verbose too.

 
Which is just slightly different from today's (jOOQ 3.0-RC2):

    new Executor(Connection, Dialect).fetch(ResultQuery);
    new Executor(Connection, Dialect).execute(Query);

Or from the previous (jOOQ 2.6):

    new Factory(Connection, Dialect).fetch(ResultQuery);
    new Factory(Connection, Dialect).execute(Query);

Just so I don't forget about it, there are many ways to do certain operations in the JDK. For example:
SwingUtilities.invokeLater(Runnable);
EventQueue.invokeLater(Runnable);
and whenever there is such duplication, people lose their time arguing which one is the best practice. You should try to prevent that.

 
OK, so when we disregard the "define()" / "bind()" sub-discussion,
then your suggestion comes down to removing the "org.jooq.Attachable"
aspect of "org.jooq.Query" in a way that a Query is a "dumb" AST,
which can be manipulated by something we used to call a contextual
factory. By manipulation, we understand things like:

- Rendering SQL to a StringBuilder
- Binding variables to a PreparedStatement
- Executing it

That is exactly my view.

 
1. Many users seem to like the fact that queries can execute
themselves. So I want to address this, somehow.

There is no difference between:
run(query)
and
query.run()

This is not a valid point, users wouldn't mind (unless they go on strike to save one character).

 
2. This would be quite a bit of a change. Getting rid of "Attachable"
queries (i.e. self-executable queries) isn't simple.

This is where your skills come into play :)

 
3. It would break semantic versioning, as such big changes aren't
expected between release candidates. Similar to ConnectionProvider,
which had to wait for 3.0

OK, let's assume "RC" meant "Release Confirmation". I confirm that there are a few changes that would be welcome before we reach Release Candidate.

I believe not many users moved to 3.0 RC. Most users would transition from 2.0 to 3.0 when it is final. After migrating all their code, they will see that 4.0 has another approach. My feeling is that as long as 3.0 is not official, things can change and should change. Further releases should be less painful if design is right from now on.
 
 
I don't want to postpone
the release of row value expressions until then.

This is already released, people can use RC 2 if they want it now ;)
 

Can we agree that we keep discussing these interesting thoughts, but
consider them out of scope for jOOQ 3.0?

I don't have to agree, you are the benevolent dictator and you have to take decisions! :)

Cheers,
-Christopher

Lukas Eder

unread,
Apr 5, 2013, 11:40:56 AM4/5/13
to jooq...@googlegroups.com
2013/4/5 Christopher Deckers <chr...@gmail.com>:
> Hi Lukas,
>
> Sarcasm mode: on
> (yeah, I am trying to be nastier than last time!)
>
>
>> So, "bind(Query)" or "define(Query)", this is just a more verbose way
>> of directly executing the query:
>>
>> with(Connection, Dialect).fetch(ResultQuery);
>> with(Connection, Dialect).execute(Query);
>
>
> You are right, now I am coding all my applications in a single class. No
> more verbosity!
>
> Also, I found that auto executing things in unrelated context is a wonderful
> idea, so I am suggesting Oracle to change:
> SwingUtilities.invokeLater(Runnable)
> to:
> Runnable.invokeInSwing()
>
> Yes, it is less verbose too.

Before I read on, a short note. How about:

XML.toString(org.w3c.dom.Document)?

Nooo, we have

TransformerFactory.newInstance().newTransformer().transform(new
DOMSource(document), new StreamTarget(System.out));

Ehm... ;-)
> --
> You received this message because you are subscribed to the Google Groups
> "jOOQ User Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jooq-user+...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Lukas Eder

unread,
Apr 5, 2013, 12:11:49 PM4/5/13
to jooq...@googlegroups.com
2013/4/5 Christopher Deckers <chr...@gmail.com>:
> Hi Lukas,
>
> Sarcasm mode: on
> (yeah, I am trying to be nastier than last time!)
>
>
>> So, "bind(Query)" or "define(Query)", this is just a more verbose way
>> of directly executing the query:
>>
>> with(Connection, Dialect).fetch(ResultQuery);
>> with(Connection, Dialect).execute(Query);
>
>
> You are right, now I am coding all my applications in a single class. No
> more verbosity!
>
> Also, I found that auto executing things in unrelated context is a wonderful
> idea, so I am suggesting Oracle to change:
> SwingUtilities.invokeLater(Runnable)
> to:
> Runnable.invokeInSwing()
>
> Yes, it is less verbose too.

Actually, this example doesn't work, as Runnable is really not
supposed to know about Swing. The responsibilities are clearly
defined. Whereas adding a convenience method "fetch(ResultQuery)" to
the result of "with(...)" that internally calls something like
"this.bind(ResultQuery).fetch()" is really not such a bad idea. As a
matter of fact, jOOQ does that all the time. E.g.

select().from(T).join(U).on(...)

The join() here is nothing else than

select().from( T.join(U).on(...) )

>> Which is just slightly different from today's (jOOQ 3.0-RC2):
>>
>> new Executor(Connection, Dialect).fetch(ResultQuery);
>> new Executor(Connection, Dialect).execute(Query);
>>
>> Or from the previous (jOOQ 2.6):
>>
>> new Factory(Connection, Dialect).fetch(ResultQuery);
>> new Factory(Connection, Dialect).execute(Query);
>
>
> Just so I don't forget about it, there are many ways to do certain
> operations in the JDK. For example:
> SwingUtilities.invokeLater(Runnable);
> EventQueue.invokeLater(Runnable);
> and whenever there is such duplication, people lose their time arguing which
> one is the best practice. You should try to prevent that.

Let's leave this out. "define()" / "bind()" is really not the main topic, here.

>> OK, so when we disregard the "define()" / "bind()" sub-discussion,
>> then your suggestion comes down to removing the "org.jooq.Attachable"
>> aspect of "org.jooq.Query" in a way that a Query is a "dumb" AST,
>> which can be manipulated by something we used to call a contextual
>> factory. By manipulation, we understand things like:
>>
>> - Rendering SQL to a StringBuilder
>> - Binding variables to a PreparedStatement
>> - Executing it
>
>
> That is exactly my view.

At least we understand our points of view :-)

>> 1. Many users seem to like the fact that queries can execute
>> themselves. So I want to address this, somehow.
>
>
> There is no difference between:
> run(query)
> and
> query.run()

There's also no difference between

for (int i = 0; i < 10; i++);

and

int i = 0;
while (i < 10) i++;

Let's ask Oracle to remove the latter. And while we're add it, we
should remove the for-each loop too, and who needs the
try-with-resources construct? Or jOOQ, when we have JDBC? ;-)

> This is not a valid point, users wouldn't mind (unless they go on strike to
> save one character).

Have you actually asked the users? :-)
Some do mind. Some just don't agree.

>> 2. This would be quite a bit of a change. Getting rid of "Attachable"
>> queries (i.e. self-executable queries) isn't simple.
>
> This is where your skills come into play :)

Hah, yeah. :-) Easy for you to say.

>> 3. It would break semantic versioning, as such big changes aren't
>> expected between release candidates. Similar to ConnectionProvider,
>> which had to wait for 3.0
>
> OK, let's assume "RC" meant "Release Confirmation". I confirm that there are
> a few changes that would be welcome before we reach Release Candidate.

I had published many snapshots for review, the group was very quiet,
then. The group was also very quiet when I released RC1.

> I believe not many users moved to 3.0 RC. Most users would transition from
> 2.0 to 3.0 when it is final. After migrating all their code, they will see
> that 4.0 has another approach. My feeling is that as long as 3.0 is not
> official, things can change and should change. Further releases should be
> less painful if design is right from now on.

Yes, that's true. Things can change, but now they're simply not going
to change drastically any longer.

jOOQ's design isn't specified by a large EG in a JSR, it evolves
slowly. Be aware that even if you disagree with many concepts right
now, things are actually much better than they used to be in 2.x
(where contextual and static API was mixed in one class, and
everything was "attachable", etc, etc)

>> I don't want to postpone
>> the release of row value expressions until then.
>
> This is already released, people can use RC 2 if they want it now ;)
>
>> Can we agree that we keep discussing these interesting thoughts, but
>> consider them out of scope for jOOQ 3.0?
>
> I don't have to agree, you are the benevolent dictator and you have to take
> decisions! :)

Precisely! Hehe, the benevolent dictator... Do note that APIs that
evolve from large EG's aren't necessarily much better :-)

Anyway, as we're delving into sarcasm here, I'll call it a day,
re-iterate my thinking, and we'll see how long 3.0 should be
postponed, or if things can wait for 4.0.
Reply all
Reply to author
Forward
0 new messages