Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [rdf4j-dev] Backwards compatibility

And the reason why i'm bringing it up:

 - estimates and actuals in query plans are using no-op default methods in interfaces
 - support for retrieving the query plan is also changing some interfaces, again that will require more no-op default methods

These are very much features that users would expect to use regardless of underlying database. If the other databases don't want to implement all of them, that's very understandable, but it should be their explicit choice to do so and not a default option that we have chosen already.

Håvard

On Sat, Apr 18, 2020 at 10:27 AM Håvard Ottestad <hmottestad@xxxxxxxxx> wrote:
The Linux kernel takes backwards compatibility to a whole new level with treating many bugs as features. I say this to emphasise that there is no strict definition of semantic versioning and we can decide to exclude some things like we are currently excluding unintentional behaviour. 

I think we should go with keeping track of which interface changes we have made and remove default implementations when releasing major versions. If we split our methods into two categories: "nice to implement for performance" and "needs to be implemented for a feature" - then we can keep default implementations for performance methods but remove them for feature methods.

I've started to change my mind about the java 9 module system. No one at conferences seem to be using the module system themselves. There is some support in maven and junit, but it still seems like a big hassel. Essentially most people are just ignoring it as they upgrade past Java 8. 

Håard

On Fri, Apr 17, 2020 at 4:07 PM Jeen Broekstra <jeen.broekstra@xxxxxxxxx> wrote:


On Fri, Apr 17, 2020 at 8:31 PM Håvard Ottestad <hmottestad@xxxxxxxxx> wrote:
Hi,

Backwards compatibility is very important to the RDF4J project.

Currently we are very strict. Any change of method signature or return type is considered non backwards compatible. Any removal of a class, method or field is also not backwards compatible. Of course limited to public things.

We also don't allow for methods to be added to public interfaces.

This last point is something I would like to discuss a bit. 

What I have done currently is to add default methods to interfaces and then override them in our own code. This means that anyone who uses those interfaces will get default implementations, usually no-ops, and don't notice anything. Then when we release a major version we would remove these default implementations.

I'm not sure if I really like this, but I am thinking that we should look into how to formalise this so that we remember to remove the default implementations when it comes to for a major release.

Well, one thing we could do to keep track is log a general "clean up" issue for the next major release and add these new methods to a list there.

However: why bother? What do we gain by removing these default methods in a major release? They are typically just one or two lines (either a no-op or throwing an UnsupportedOperationException) and if they're not in anybody's way... To some extent that even holds for deprecated code, which is why we try to be conservative with removing that, too.

Also, for what it's worth: I've not found it necessary to extend existing interfaces very often. Usually there are alternative design choices that preserve compatibility better, such as a completely new interface, or a public utility class. That's not to say it never happens of course (the new getStatements in Model is a recent example), but it doesn't seem to me to be a very common thing.

Is there a specific example you have in mind that brought this up?

Another option would be to say that we do not extend semantic versioning to imply that public interfaces can not grow. We would then be able to add methods to interfaces in minor versions.

I think that's not something we can get away with. Whichever way you turn it, "backward compatibility" means that a new version works without having to adapt existing code, and excluding public interface extensions would break that. I also don't see the need as we can very easily keep compatibility by the methods we discussed above. I kind of see the argument of distinguishing between interfaces that are intended to be implemented by third parties vs interfaces that we only expose to use, but do not expect third parties to provide their own implementations of. Unfortunately, I don't think making that distinction is a common thing in the Java world, and I wouldn't know how to communicate in a way that wouldn't confuse the heck out of people.

Perhaps instead we should start looking at the Java 9 module mechanism again, to make it more explicit what interfaces and classes are in our public api, and which ones are internal. OF course, since we have to stay Java 8 compatible for now, we can't rely on automatic enforcement, but we could at least use it as a documenting feature, perhaps.

Jeen
_______________________________________________
rdf4j-dev mailing list
rdf4j-dev@xxxxxxxxxxx
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/rdf4j-dev

Back to the top