This page is currently for discussion of how to make experimental APIs available
See also: "How We Plan Releases" in the Roadmap
Docs [NEEDS UPDATE]: "Release numbering, compatibility, and deprecation" in the Community Guide
Rules for Experimental APIs (TBD)
- Experimental APIs are distinguished in code by:
- double-underscore namespace (names starting with "svn_ _" or "svn_LIB_ _") 2
- Doxygen annotation "@warning EXPERIMENTAL"
- Function annotation "SVN_EXPERIMENTAL" (where applicable – that is, for C functions)
- being in a separate header 1
- New experimental APIs MAY be introduced in the .0 patch release of any minor release series (regular or LTS)
- and MUST NOT be introduced in a patch release other than .0
- Compatibility: throughout a minor release series, an experimental API:
- MUST be backward- and forward-compatible at the ABI level, so that a caller will not crash;
- MAY change its functionality in any way, up to and including doing nothing or returning an error indication such as "unsupported feature".
- In any minor release, an experimental API MAY be incompatible in any way with experimental APIs in the previous minor release, or MAY be removed.
- When an experimental API is considered stable enough:
- it SHOULD be promoted to a stable API in the next minor release.
- We SHOULD continue to provide the last experimental version of this API as well, for one minor release, if we can make it compatible. (Compatible means the same as when a stable API is changed.)
1 see 'Packaging and Linking' and 'Distinguishing Experimental APIs' below
2 see 'Private APIs' below
Rules for downstream developers:
- a packaged app that uses experimental APIs should declare a dependency on a single minor version of the svn libs
- (TODO: mention this in the release notes)
Experimental APIs: Rationale
From now on, we will be making some experimental APIs available without a guarantee of forward compatibility. An application that uses experimental features is a new and wanted possibility, in order that developers and users get the opportunity to try out new features earlier in their development.
There is a concern around whether this will violate some long-held expectations. A Subversion application that uses only the stable API will have the same compatibility as before. An application that uses an experimental API will not be compatible with a later minor version of separately installed svn libraries, but this need not lead to a surprise breakages – see Packaging and Linking below.
LTS Releases and Experimental APIs
TBD. Should be thinking in terms of experimental features, not just APIs. How will we manage an experimental client-server feature?
Packaging and Linking
An application that uses an experimental API is promised to be compatible with exactly one minor version of the svn libraries. For an app distributed through a package management system, the package metadata needs to state the single-version dependency, and then the package manager will detect any attempt to update the libs to an incompatible version. (The user can then choose whether to also upgrade the app, or disable the app, or cancel the upgrade of the libs.)
Some Subversion apps do not link to separately-installed svn libs but include their own build. TortoiseSVN is one. Such apps have no run-time constraint, and it continues to be their developer's job to update them when they wish, no matter whether they use experimental APIs.
It would be nice if we can help packagers of the svn libs to have some flexibility over how they package experimental APIs. For example, they might want to put the libs in a package "svn" that only provides access to the stable APIs by itself, and enable the experimental APIs only when a separate package "svn-x" is also installed. For static libs that is perhaps most easily done by packaging the experimental API headers separately.
- What approach is useful for dynamic libs?
What is a Private (inter-library) API? It provides access to library functionality that is useful for a Subversion application, but the functionality and/or the interface to it is not stable and supported. An experimental API and a private API are effectively the same thing.
In previous releases, we have designated an API as private when we think the functionality and/or the interface works but it is ugly, and we hope one day to replace it with something better. Or it is incomplete and we hope one day to complete it.
In the meantime, we don't want anybody else to use it. We need to use this interface to build our Subversion application but we try to hide it from other developers who might want to build a Subversion application. At least this applies to a developer who expects to link to a packaged version of the libraries in which the "private" API is not exposed. (A developer who uses the Subversion source code directly is not subject to this restriction and then the so-called "private" API is fully accessible.)
Shouldn't a developer be able to ship an alternative "svn" client that is a slightly tweaked variant of the standard one? If we let our own code use APIs which we hide from others, so that cannot be done, I think that is Wrong.
At the same time, we have not committed to completing and publishing these APIs. That's a matter of mind-set, no doubt encouraged by the idea that nobody else cares about them, but not a destiny that is good for those APIs nor unique to them. We might equally find ourselves abandoning the development of any API that we designate as experimental.
- we SHOULD make the existing "private" APIs available to developers on the same basis as upcoming "experimental" APIs;
- we SHOULD use the same distinguishing marks (namespace, function annotations, etc.) for both;
- we MAY choose to start exposing the upcoming "experimental" APIs first and the existing "private" APIs later.
Distinguishing Experimental APIs
Distinctions are possible by:
- doc comments – e.g. "@warning EXPERIMENTAL"
- function annotation causing compiler warning – e.g. "SVN_EXPERIMENTAL"
- namespace – e.g. "svn__"
- a separate header file – e.g. "include/internal/svn_foo_internal.h"
While all of these methods help to inform the downstream developer, it will be more useful to facilitate programmatic separation of the experimental API or detection of its use, including:
- packaging the experimental API separately;
- distinguishing the experimental API in generated language bindings.
For this, the use of a separate namespace and a separate header file will both be helpful.
Promotion to Stable
An experimental API should be promoted to a stable, public API in some minor version.
A developer who has been using the experimental API necessarily expects to adapt their source code to each minor release. They should never expect their app to link without changes against the next minor release of the Subversion libraries, and should have expressed this in their package dependency info if applicable.
When an experimental API is maturing, during the last release or two before being declared stable, it is likely that the API in fact changed little enough that no change was required in some apps using it. After that, it seems perverse to force every app to be changed immediately when the API is promoted, just to accommodate the namespace change.
Therefore, if the stable and last experimental versions of an API are compatible, we SHOULD provide a transitional release which provides both the stable and the last experimental version of the API.
(Perhaps this suggests that moving to a different namespace is not the ultimately the best way to handle versioning and promoting an API.)