Bug 106862 - API design guidelines give ambiguous advice about coping with old versions
Summary: API design guidelines give ambiguous advice about coping with old versions
Status: RESOLVED MOVED
Alias: None
Product: dbus
Classification: Unclassified
Component: core (show other bugs)
Version: git master
Hardware: Other All
: medium normal
Assignee: Philip Withnall
QA Contact: D-Bus Maintainers
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-06-08 12:26 UTC by Simon McVittie
Modified: 2018-10-12 21:34 UTC (History)
0 users

See Also:
i915 platform:
i915 features:


Attachments

Description Simon McVittie 2018-06-08 12:26:02 UTC
https://dbus.freedesktop.org/doc/dbus-api-design.html#api-versioning says:

> New API can be added to a D-Bus interface without incrementing the version
> number, as such additions are still backwards-compatible. However, clients
> should gracefully handle the org.freedesktop.DBus.Error.UnknownMethod error
> reply from all D-Bus method calls if they want to run against older versions
> of the service which don’t implement new methods. (This also prevents use of
> generated bindings; any method which a client wants to gracefully fall back
> from should be called using a generic D-Bus method invocation rather than a
> specific generated binding.)

I'm not sure why it says that? Code generated by, for example, gdbus-codegen or (ugh) dbus-binding-tool from a local copy of some API v1.23 should interoperate fine with a service implementing some API v1.0 (assume semantic versioning here). The generated methods will raise UnknownMethod as usual.

The uses of generated bindings that *would* be a problem are those where the generated binding is external to the client, or where the binding is generated from interface definitions that are external to the client. Philip, are those situations the ones you had in mind? I think we should clarify this.

Let's say a client calls methods on a service that implements an API, and ideally it wants to call DoThingsWithOptions() (introduced in com.example.Something1 v1.23), falling back to DoThings() if DoThingsWithOptions() isn't implemented. Assume that service v1.x implements com.example.Something1 v1.x, and assume GDBus (the same considerations would apply to dbus-glib or QtDBus, with appropriate relabelling). There are several ways the client could call the method:

(A) Service ships a library containing gdbus-codegen-generated bindings for
    its version of com.example.Something1. Client calls methods from that
    library.

    - Client needs to be compiled against library v1.23 or later
    - Client has a strong dependency on library v1.23 or later at
      runtime, unless statically linked (if the library is not present,
      the client won't even start)
    - Client has a weak dependency on service v1.0 or later at runtime
      (if the service is not present, the relevant feature won't work
      but the client will still run)

(B) Service ships com.example.Something1.xml in /usr/share/dbus-1/interfaces.
    Client runs gdbus-codegen to generate private bindings which are
    built into the client.

    - Client needs to be compiled against library v1.23 or later
    - Client only needs service v1.0 or later at runtime

(C) Client ships a private copy of com.example.Something1.xml and uses
    it to generate private bindings which are built into the client.

    - No build-time dependency
    - Client has a weak dependency on service v1.0 or later at runtime

(D) Client uses g_dbus_connection_call() or equivalent to call at least
    DoThingsWithOptions(), and perhaps both methods.

    - No build-time dependency
    - Client has a weak dependency on service v1.0 or later at runtime

For tightly-coupled components where it's OK for a new client to get a hard dependency on a new service, like xdg-desktop-portal-gtk depending on xdg-desktop-portal, cases (A) or (B) are fine.

For loosely-coupled components where graceful fallbacks and backwards compatibility are needed, I would personally recommend (C) if the interface is of a significant size, or (D) if the interface is small and simple.

Note that it is not OK to expose the generated bindings in case (B) as part of a library, because their API would change unpredictably, depending on the precise version of the service that the client is compiled against. It would be OK to expose the generated bindings in case (C) as part of a library.
Comment 1 Philip Withnall 2018-06-09 00:22:38 UTC
(In reply to Simon McVittie from comment #0)
> https://dbus.freedesktop.org/doc/dbus-api-design.html#api-versioning says:
> 
> > New API can be added to a D-Bus interface without incrementing the version
> > number, as such additions are still backwards-compatible. However, clients
> > should gracefully handle the org.freedesktop.DBus.Error.UnknownMethod error
> > reply from all D-Bus method calls if they want to run against older versions
> > of the service which don’t implement new methods. (This also prevents use of
> > generated bindings; any method which a client wants to gracefully fall back
> > from should be called using a generic D-Bus method invocation rather than a
> > specific generated binding.)
> 
> I'm not sure why it says that? Code generated by, for example, gdbus-codegen
> or (ugh) dbus-binding-tool from a local copy of some API v1.23 should
> interoperate fine with a service implementing some API v1.0 (assume semantic
> versioning here). The generated methods will raise UnknownMethod as usual.
> 
> The uses of generated bindings that *would* be a problem are those where the
> generated binding is external to the client, or where the binding is
> generated from interface definitions that are external to the client.
> Philip, are those situations the ones you had in mind? I think we should
> clarify this.

It’s hard to remember, but I suspect those are the situations I had in mind. Specifically, avoiding a dependency on a C symbol from an external library, which will exist at runtime only if running on a system where that external library is new enough (or which will exist only if generated from a new enough introspection XML file).

This definitely should be clarified. If you put a patch together I’m happy to review. If you want me to put a patch together it might take me a little while (everything is on fire).
Comment 2 GitLab Migration User 2018-10-12 21:34:58 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/dbus/dbus/issues/212.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.