You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@geode.apache.org by Kirk Lund <kl...@apache.org> on 2020/05/08 16:49:51 UTC

Use of default methods in interfaces

I believe some of the Geode community has already decided that we shouldn't
overuse default methods in interfaces. Dan and others were the ones who
decided this and thus I can't really explain to folks in PRs why it's bad
to overuse default methods. Could some of the folks with strong
understanding of why we should avoid making every method default empty
please speak up here and/or in https://github.com/apache/geode/pull/5014?

My understanding is that default implementations should only be provided in
interfaces when it's important to do so for facilitating some sort of
deprecation and replacing a deprecated method.

Thanks,
Kirk

Re: Use of default methods in interfaces

Posted by John Blum <jb...@pivotal.io>.
> *appropriate when the new method can be defined in terms of other
existing methods in the interface*

This is what it means when a method employs the "template" design pattern.

Correction to my (earlier) example:

@FunctionalInterace
interface Sorter {

    default  Object[] sort(Object... array) {
        return *sort*(Arrays.asList(array)).toArray();
    }

    <T extends Iterable<?>> T *sort*(T collection);

}

-j

On Fri, May 8, 2020 at 1:03 PM Owen Nichols <on...@pivotal.io> wrote:

> Default interface methods are especially appropriate when the new method
> can be defined in terms of other existing methods in the interface.  For
> examples, when Collections added isEmpty(), it is basically just a
> shorthand for length()==0 [but certain subclasses might still be able to
> provide a more efficient implementation, for example a linked list might
> require traversing the entire list to get the length, while isEmpty could
> simply check the head].
>
> For public APIs, adding a new default interface method is safe (will not
> break source or binary compatibility), but for internal APIs, we don’t
> promise backward compatibility anyway.
>
> The pattern of adding a new default interface method with an empty
> implementation does concern me.  Perhaps a new interface that extends the
> original would be a more compile-time-verifiable way to express that new
> optional methods have been added that only some but not all implementations
> might implement?
>
>
> > On May 8, 2020, at 11:31 AM, John Blum <jb...@pivotal.io> wrote:
> >
> > Another way to think about this is:
> >
> > 1. First, default methods are not inherently bad. They are useful in many
> > situations and can be "overridden" on implementing classes, if necessary.
> > 2. A default method should be provided when the operation is not strictly
> > required or if the implementation (procedure/algorithm) is rather simple
> > (e.g. following the template pattern), for example...
> >
> > @FunctionalInterace {
> > interface Sorter {
> >
> >    default  Object[] sort(Object... array) {
> >        return convert(Arrays.asList(array)).toArray();
> >    }
> >
> >    <T extends Iterable<?>> T convert(T collection);
> >
> > }
> >
> > 3. If the interface footprint is small (as it should be) then it is
> > possible to use in *Lambda* expressions (and *Method References*), as
> > proper @FunctionalInterface as shown above, which is very useful when
> > composing *Streams*, etc.
> >
> > Food for thought.
> >
> > -j
> >
> >
> > On Fri, May 8, 2020 at 10:17 AM Jacob Barrett <jb...@pivotal.io>
> wrote:
> >
> >> As a general rule default implementations on an interface should only
> used
> >> when absolutely necessary because all the implementations are out of
> your
> >> control. For example, the collection interfaces in the JDK all gained
> new
> >> APIs but Java doesn’t implement every instance of them so a default is
> >> necessary for forward progress. However, if you own all instances you
> >> should not need to use default. So in this particular PR the use of
> default
> >> in the InternalCache in my opinion is wrong. We should control all
> internal
> >> interfaces and therefor can update them all with the correct
> >> implementation.
> >>
> >> -Jake
> >>
> >>> On May 8, 2020, at 9:49 AM, Kirk Lund <kl...@apache.org> wrote:
> >>>
> >>> I believe some of the Geode community has already decided that we
> >> shouldn't
> >>> overuse default methods in interfaces. Dan and others were the ones who
> >>> decided this and thus I can't really explain to folks in PRs why it's
> bad
> >>> to overuse default methods. Could some of the folks with strong
> >>> understanding of why we should avoid making every method default empty
> >>> please speak up here and/or in
> https://github.com/apache/geode/pull/5014
> >> ?
> >>>
> >>> My understanding is that default implementations should only be
> provided
> >> in
> >>> interfaces when it's important to do so for facilitating some sort of
> >>> deprecation and replacing a deprecated method.
> >>>
> >>> Thanks,
> >>> Kirk
> >>
> >>
> >
> > --
> > -John
> > Spring Data Team
>
>

-- 
-John
Spring Data Team

Re: Use of default methods in interfaces

Posted by Owen Nichols <on...@pivotal.io>.
Default interface methods are especially appropriate when the new method can be defined in terms of other existing methods in the interface.  For examples, when Collections added isEmpty(), it is basically just a shorthand for length()==0 [but certain subclasses might still be able to provide a more efficient implementation, for example a linked list might require traversing the entire list to get the length, while isEmpty could simply check the head].

For public APIs, adding a new default interface method is safe (will not break source or binary compatibility), but for internal APIs, we don’t promise backward compatibility anyway.

The pattern of adding a new default interface method with an empty implementation does concern me.  Perhaps a new interface that extends the original would be a more compile-time-verifiable way to express that new optional methods have been added that only some but not all implementations might implement?


> On May 8, 2020, at 11:31 AM, John Blum <jb...@pivotal.io> wrote:
> 
> Another way to think about this is:
> 
> 1. First, default methods are not inherently bad. They are useful in many
> situations and can be "overridden" on implementing classes, if necessary.
> 2. A default method should be provided when the operation is not strictly
> required or if the implementation (procedure/algorithm) is rather simple
> (e.g. following the template pattern), for example...
> 
> @FunctionalInterace {
> interface Sorter {
> 
>    default  Object[] sort(Object... array) {
>        return convert(Arrays.asList(array)).toArray();
>    }
> 
>    <T extends Iterable<?>> T convert(T collection);
> 
> }
> 
> 3. If the interface footprint is small (as it should be) then it is
> possible to use in *Lambda* expressions (and *Method References*), as
> proper @FunctionalInterface as shown above, which is very useful when
> composing *Streams*, etc.
> 
> Food for thought.
> 
> -j
> 
> 
> On Fri, May 8, 2020 at 10:17 AM Jacob Barrett <jb...@pivotal.io> wrote:
> 
>> As a general rule default implementations on an interface should only used
>> when absolutely necessary because all the implementations are out of your
>> control. For example, the collection interfaces in the JDK all gained new
>> APIs but Java doesn’t implement every instance of them so a default is
>> necessary for forward progress. However, if you own all instances you
>> should not need to use default. So in this particular PR the use of default
>> in the InternalCache in my opinion is wrong. We should control all internal
>> interfaces and therefor can update them all with the correct
>> implementation.
>> 
>> -Jake
>> 
>>> On May 8, 2020, at 9:49 AM, Kirk Lund <kl...@apache.org> wrote:
>>> 
>>> I believe some of the Geode community has already decided that we
>> shouldn't
>>> overuse default methods in interfaces. Dan and others were the ones who
>>> decided this and thus I can't really explain to folks in PRs why it's bad
>>> to overuse default methods. Could some of the folks with strong
>>> understanding of why we should avoid making every method default empty
>>> please speak up here and/or in https://github.com/apache/geode/pull/5014
>> ?
>>> 
>>> My understanding is that default implementations should only be provided
>> in
>>> interfaces when it's important to do so for facilitating some sort of
>>> deprecation and replacing a deprecated method.
>>> 
>>> Thanks,
>>> Kirk
>> 
>> 
> 
> -- 
> -John
> Spring Data Team


Re: Use of default methods in interfaces

Posted by Jacob Barrett <jb...@pivotal.io>.
> On May 8, 2020, at 1:11 PM, Kirk Lund <kl...@apache.org> wrote:
> 
> I want to avoid having Java Interfaces in which every method (or even many
> methods) has a default empty implementation. I think that's ok for callback
> interfaces like CacheListener, but it's horrible for interfaces like Cache,
> Region, InternalCache, InternalRegion. I don't think these non-callback
> interfaces should have any default empty implementations.
+1

Even for callbacks I would prefer interface without defaults until a new method is added. If you want to have a no-op implementation that is what an abstract class is for.

-Jake


Re: Use of default methods in interfaces

Posted by Kirk Lund <kl...@apache.org>.
I want to avoid having Java Interfaces in which every method (or even many
methods) has a default empty implementation. I think that's ok for callback
interfaces like CacheListener, but it's horrible for interfaces like Cache,
Region, InternalCache, InternalRegion. I don't think these non-callback
interfaces should have any default empty implementations.

On Fri, May 8, 2020 at 11:32 AM John Blum <jb...@pivotal.io> wrote:

> Another way to think about this is:
>
> 1. First, default methods are not inherently bad. They are useful in many
> situations and can be "overridden" on implementing classes, if necessary.
> 2. A default method should be provided when the operation is not strictly
> required or if the implementation (procedure/algorithm) is rather simple
> (e.g. following the template pattern), for example...
>
> @FunctionalInterace {
> interface Sorter {
>
>     default  Object[] sort(Object... array) {
>         return convert(Arrays.asList(array)).toArray();
>     }
>
>     <T extends Iterable<?>> T convert(T collection);
>
> }
>
> 3. If the interface footprint is small (as it should be) then it is
> possible to use in *Lambda* expressions (and *Method References*), as
> proper @FunctionalInterface as shown above, which is very useful when
> composing *Streams*, etc.
>
> Food for thought.
>
> -j
>
>
> On Fri, May 8, 2020 at 10:17 AM Jacob Barrett <jb...@pivotal.io> wrote:
>
> > As a general rule default implementations on an interface should only
> used
> > when absolutely necessary because all the implementations are out of your
> > control. For example, the collection interfaces in the JDK all gained new
> > APIs but Java doesn’t implement every instance of them so a default is
> > necessary for forward progress. However, if you own all instances you
> > should not need to use default. So in this particular PR the use of
> default
> > in the InternalCache in my opinion is wrong. We should control all
> internal
> > interfaces and therefor can update them all with the correct
> > implementation.
> >
> > -Jake
> >
> > > On May 8, 2020, at 9:49 AM, Kirk Lund <kl...@apache.org> wrote:
> > >
> > > I believe some of the Geode community has already decided that we
> > shouldn't
> > > overuse default methods in interfaces. Dan and others were the ones who
> > > decided this and thus I can't really explain to folks in PRs why it's
> bad
> > > to overuse default methods. Could some of the folks with strong
> > > understanding of why we should avoid making every method default empty
> > > please speak up here and/or in
> https://github.com/apache/geode/pull/5014
> > ?
> > >
> > > My understanding is that default implementations should only be
> provided
> > in
> > > interfaces when it's important to do so for facilitating some sort of
> > > deprecation and replacing a deprecated method.
> > >
> > > Thanks,
> > > Kirk
> >
> >
>
> --
> -John
> Spring Data Team
>

Re: Use of default methods in interfaces

Posted by John Blum <jb...@pivotal.io>.
Another way to think about this is:

1. First, default methods are not inherently bad. They are useful in many
situations and can be "overridden" on implementing classes, if necessary.
2. A default method should be provided when the operation is not strictly
required or if the implementation (procedure/algorithm) is rather simple
(e.g. following the template pattern), for example...

@FunctionalInterace {
interface Sorter {

    default  Object[] sort(Object... array) {
        return convert(Arrays.asList(array)).toArray();
    }

    <T extends Iterable<?>> T convert(T collection);

}

3. If the interface footprint is small (as it should be) then it is
possible to use in *Lambda* expressions (and *Method References*), as
proper @FunctionalInterface as shown above, which is very useful when
composing *Streams*, etc.

Food for thought.

-j


On Fri, May 8, 2020 at 10:17 AM Jacob Barrett <jb...@pivotal.io> wrote:

> As a general rule default implementations on an interface should only used
> when absolutely necessary because all the implementations are out of your
> control. For example, the collection interfaces in the JDK all gained new
> APIs but Java doesn’t implement every instance of them so a default is
> necessary for forward progress. However, if you own all instances you
> should not need to use default. So in this particular PR the use of default
> in the InternalCache in my opinion is wrong. We should control all internal
> interfaces and therefor can update them all with the correct
> implementation.
>
> -Jake
>
> > On May 8, 2020, at 9:49 AM, Kirk Lund <kl...@apache.org> wrote:
> >
> > I believe some of the Geode community has already decided that we
> shouldn't
> > overuse default methods in interfaces. Dan and others were the ones who
> > decided this and thus I can't really explain to folks in PRs why it's bad
> > to overuse default methods. Could some of the folks with strong
> > understanding of why we should avoid making every method default empty
> > please speak up here and/or in https://github.com/apache/geode/pull/5014
> ?
> >
> > My understanding is that default implementations should only be provided
> in
> > interfaces when it's important to do so for facilitating some sort of
> > deprecation and replacing a deprecated method.
> >
> > Thanks,
> > Kirk
>
>

-- 
-John
Spring Data Team

Re: Use of default methods in interfaces

Posted by Jacob Barrett <jb...@pivotal.io>.
As a general rule default implementations on an interface should only used when absolutely necessary because all the implementations are out of your control. For example, the collection interfaces in the JDK all gained new APIs but Java doesn’t implement every instance of them so a default is necessary for forward progress. However, if you own all instances you should not need to use default. So in this particular PR the use of default in the InternalCache in my opinion is wrong. We should control all internal interfaces and therefor can update them all with the correct implementation. 

-Jake

> On May 8, 2020, at 9:49 AM, Kirk Lund <kl...@apache.org> wrote:
> 
> I believe some of the Geode community has already decided that we shouldn't
> overuse default methods in interfaces. Dan and others were the ones who
> decided this and thus I can't really explain to folks in PRs why it's bad
> to overuse default methods. Could some of the folks with strong
> understanding of why we should avoid making every method default empty
> please speak up here and/or in https://github.com/apache/geode/pull/5014?
> 
> My understanding is that default implementations should only be provided in
> interfaces when it's important to do so for facilitating some sort of
> deprecation and replacing a deprecated method.
> 
> Thanks,
> Kirk