convenience methods
Lukas Eder
lukas.eder at gmail.com
Wed Nov 22 17:26:34 UTC 2017
2017-11-22 18:24 GMT+01:00 Douglas Surber <douglas.surber at oracle.com>:
> Lukas,
>
> Thanks for your reply and encouragement. I’m not going to undertake
> changes to JDBC. My plate is full with ADBA. If you contribute specific
> JDBC convenience methods to this list the EG may consider them for a future
> release. The less work the EG and the Spec Lead have to do the more likely
> your contributions are to be adopted. I would recommend providing the
> complete method source including the JavaDoc so that all the Spec Lead has
> to do is paste it into the appropriate source file. That’s not to say such
> contributions would necessarily be adopted verbatim or even at all, but it
> does increase the chances of getting something.
>
Makes sense. I'll look into this during the coming weeks.
The same recommendation applies to ADBA convenience methods. The more
> complete your contribution the easier it is for us to adopt them. Even just
> a list of desired convenience method signatures would be useful for ADBA
> though. We can’t think of everything.
>
Will do as well.
Thanks,
Lukas
2017-11-22 18:24 GMT+01:00 Douglas Surber <douglas.surber at oracle.com>:
> Lukas,
>
> Thanks for your reply and encouragement. I’m not going to undertake
> changes to JDBC. My plate is full with ADBA. If you contribute specific
> JDBC convenience methods to this list the EG may consider them for a future
> release. The less work the EG and the Spec Lead have to do the more likely
> your contributions are to be adopted. I would recommend providing the
> complete method source including the JavaDoc so that all the Spec Lead has
> to do is paste it into the appropriate source file. That’s not to say such
> contributions would necessarily be adopted verbatim or even at all, but it
> does increase the chances of getting something.
>
> The same recommendation applies to ADBA convenience methods. The more
> complete your contribution the easier it is for us to adopt them. Even just
> a list of desired convenience method signatures would be useful for ADBA
> though. We can’t think of everything.
>
> Douglas
>
>
> On Nov 22, 2017, at 3:28 AM, Lukas Eder <lukas.eder at gmail.com> wrote:
>
> Hi Douglas,
>
> I think that convenience methods are really very very helpful. jOOQ has
> tons of them, for instance, because that really greatly reduces boiler
> plate code on the call site and makes using the API much more effective and
> fun. This also helps increase adoption.
>
> One of the main reasons why Spring's JdbcTemplate, or Apache DbUtils, or
> the simpler parts of the jOOQ API exists is the fact that the (synchronous)
> JDBC API doesn't have any such methods. For instance, it would make total
> sense to have
>
> public interface Connection {
> default PreparedStatement prepareStatement(String sql, Object...
> bindings) {
> PreparedStatement s = prepareStatement(sql);
> for (int i = 0; i < bindings.length; i++)
> s.setObject(i + 1, bindings[i]);
> }
>
> default int executeUpdate(String sql, Object... bindings) {
> try (PreparedStatement s = prepareStatement(sql, bindings)) {
> return s.executeUpdate();
> }
> }
> }
>
> I mean, who really enjoys counting bind indexes manually and sending a
> very simple static INSERT statement with 10 values to the server by setting
> each bind variable individually?
>
> This convenience stuff has been dearly missing from the very first version
> of JDBC :) (granted, it would have been difficult to add, without default
> methods). There are many other possible convenience methods, including:
>
> public interface ResultSet {
> default Object[] get() {
> Object[] result = new Object[getMetaData().getColumnCount()];
>
> for (int i = 0; i < result.length; i++)
> result[i] = getObject(i);
>
> return result;
> }
>
> default void forEach(Consumer<Object[]> consumer) {
> while (next())
> consumer.accept(get());
> }
> }
>
> I could go on and on, if you're interested. In fact, consider this a
> feature request! :)
>
> Further comments inline:
>
> 2017-11-16 17:25 GMT+01:00 Douglas Surber <douglas.surber at oracle.com>:
>
>> As default methods these are all implemented by calling other interface
>> methods. Clearly they aren’t necessary as the app can make the same
>> sequence of calls. On the other hand their use will result in more compact
>> and more readable code. Also, some of them handle some not so obvious
>> behavior so that the programmer doesn’t have to think about it in the
>> common use case. Again DataSource.getConnection is a good example;
>
>
> Yes, a very good example. No one wants to type that builder() stuff all
> the time even if it is useful for the special case. The convenience API
> should be there for the more general case.
>
>
>> look at Connection.connect. A third benefit and honestly the original
>> motivation for many of them is as documentation, how to use the API.
>>
>
> That's an interesting way to look at it - it never occurred to me but
> you're absolutely right. It's a nice way to document lower level API parts.
>
>
>> As a general notion, do these methods carry their weight? Are the
>> benefits they provide worth whatever additional complexity they add?
>>
>
> Absolutely! Again, one of the biggest flaws of the classic JDBC API is the
> verbosity it generates in client code. Now many people argue that verbosity
> is Java's strength, but that's nonsense when it comes to infrastructure
> logic that never changes. E.g. try-with-resources is "convenience API" that
> really really helped JDBC, because the proper approach to closing all of
> Connection, Statement, ResultSet in the right order and with the right
> exception handling really doesn't add any value to anyone's business - au
> contraire, it's too easy to get them wrong.
>
> Languages like Kotlin don't have the try-with-resources statement, but
> extension methods that can be attached to any (Auto)Closeable, which is the
> same thing as *external* convenience API. Without extension methods, that's
> not possible in Java, so it is the API maintainer's burden to implement
> default methods.
>
> Also, you're not alone. Stream has Stream.collect(supplier, accumulator,
> combiner), which is convenience for many cases of Stream.collect(Collector).
>
> JDK 9's Optional has Optional.stream(), which really wasn't "necessary",
> but so cool as it allows for flatmapping Stream<Optional<T>> to Stream<T>
> through
>
> stream.flatMap(Optional::stream)
>
> instead of
>
> stream.filter(Optional::isPresent).map(Optional::get)
>
> Just two examples. There are many other convenience APIs in the JDK, even
> trivial ones like the ArrayList constructors. The only one that is strictly
> necessary is the one that accepts a capacity. The others are there for
> convenience and improved performance.
>
> Should we add executeAsTransaction? What about other convenience methods?
>> Suggestions welcome.
>>
>
> Well, since you've added collect(Collector) (still very excited about
> that), how about also adding collect(supplier, accumulator, combiner) as a
> convenience?
>
> If you're positive that you're moving forward with convenience methods,
> I'd be happy to look for more opportunities to contribute both in ADBA and
> in JDBC (if that's something you might consider)
>
> Thanks,
> Lukas
>
> 2017-11-16 17:25 GMT+01:00 Douglas Surber <douglas.surber at oracle.com>:
>
>> ADBA includes a fair number of convenience methods. These are methods
>> that encapsulate common code patterns into default methods.
>> DataSource.getConnection() is an obvious example.
>>
>> As default methods these are all implemented by calling other interface
>> methods. Clearly they aren’t necessary as the app can make the same
>> sequence of calls. On the other hand their use will result in more compact
>> and more readable code. Also, some of them handle some not so obvious
>> behavior so that the programmer doesn’t have to think about it in the
>> common use case. Again DataSource.getConnection is a good example; look at
>> Connection.connect. A third benefit and honestly the original motivation
>> for many of them is as documentation, how to use the API.
>>
>> As a general notion, do these methods carry their weight? Are the
>> benefits they provide worth whatever additional complexity they add?
>>
>> Here is a concrete example to consider. This is a method in Connection.
>>
>> public default CompletionStage<TransactionOutcome>
>> executeAsTransaction(BiConsumer<OperationGroup, Transaction>
>> action) {
>> OperationGroup grp = this.operationGroup();
>> Transaction tran = this.transaction();
>> action.accept(grp, tran);
>> grp.submit();
>> return this.commitMaybeRollback(tran); *
>> }
>>
>> Clearly this method is not strictly necessary. It is implemented entirely
>> by calling other methods present in ADBA. Any application or framework can
>> do exactly the same. On the other hand most applications and frameworks
>> would make exactly the same sequence of calls so including this pattern in
>> ADBA would be convenient. Finally, this provides an example of how to use
>> ADBA to execute a transaction. This is actually the original motivation for
>> creating this method.
>>
>> ADBA is based on some relatively primitive concepts. In some cases there
>> is quite a conceptual distance between those primitive concepts and what an
>> application wants to do. It is easier to specify, understand, and implement
>> just the primitive concepts but that leaves a conceptual gap to what the
>> app needs; how to compose the primitives into useful actions. The various
>> convenience methods bridge this gap without adding any specification or
>> implementation complexity. IMO these convenience methods actually reduce
>> the complexity by adding an executable specification of how the primitives
>> work together to support a higher level abstraction.
>>
>> Should we add executeAsTransaction? What about other convenience methods?
>> Suggestions welcome.
>>
>> Douglas
>>
>>
>> * Note: commitMaybeRollback has been corrected to return
>> CompletionStage<TransactionOutcome> which is clearly what it should do.
>>
>>
>>
>
>
More information about the jdbc-spec-discuss
mailing list