About API breaking changes

In 2006 I wrote a draft API Change Policy for ITK. The Background section, repeated here, discusses many of the issues raised here. I argued that the time and money our customers invest in our open-source software is not insignificant. We don’t know the extent of our customer base. It’s ironic, that Paraview, a customer of VTK, is being affected by API changes in VTK. My document was not accepted, and many argued that customers should accept progress or stick with a version of the code that does not break the API.


One of the major criticisms of open-source software is that new revisions are not compatible with old revisions. Breaking compatibility impedes the acceptance and utility of open-source software. On the other hand, strict backward compatibility policies can impede innovation in software. The tension between these two viewpoints is not easily resolved.

As projects mature and the customer base grows, backward compatibility becomes more important. Commercial hardware and software products call this customer base, the installed base. Commercial products usually have a known customer base consisting of those who have purchased or licensed the software. Also, commercial systems seldom expose internal AP I’s. Open source projects rarely know the identities of their customers.
And, since the source is open, customers have access to all public and protected classes, methods and data in the code. For open-source software, it is almost impossible to determine how the customer base is using the software.

When a project hits a certain point in its life cycle, the unpleasant issue of
backward compatibility begins to rear its ugly head. All of a sudden the changes introduced in a new release of the software have a dark side to them; they hold hidden possibilities that will break something one of your users depends on.
This is true in both open and closed source projects, but in the open-source
world it seems that the community has spent less time worrying about it than in the closed source world. “Preserving Backward Compatibility,” Garrett Rooney.

The Dark Side of Extreme Programming: The nightly test/build was so effective in empowering programmers to make changes, that API changes occurred too frequently without the necessary buy-in from the user community.
From “Inside Insight,” Bill Lorensen

Some argue that open-source software should be used at your own risk. But even using open-source software requires an investment in time, energy, and funds. Also, the reputation of the development community is at risk.
…consider your user base. If you have only a dozen highly technical users,
jumping through hoops to maintain backward compatibility may be more trouble than it’s worth.
On the other hand, if you have hundreds or thousands of nontechnical users who cannot deal with manual upgrade steps, you need to spend a lot of time worrying about those kinds of issues. Otherwise, the first time you break compatibility, you’ll quickly burn through all the goodwill you built up with your users by providing them with a useful program. It’s remarkable how easily people forget the good things from a program as soon as they encounter the first real problem.
From “Preserving Backward Compatibility,” Garrett Rooney.

These investments are made by customers that include developers, users, and sponsors.

Here is the original proposal.
APIChangePolicy.pdf (44.7 KB)

A good document, but I have reservations about certain points.

those changes should never cause user code to fail to compile

Too extreme imo. Deprecated code can be removed at some point.

At run-time, deprecated API’s report how to change code from the old API to the new API.

It may refer to documentation instead.

I think the simple way to solve that without significant effort is to try to deprecate changed apis, comment in the header how to migrate to the new api, and remove this deprecated api after the next release.
It’s not always possible to keep the functionality, but we should at least try to not break the build of VTK customer when updating a minor version without previous deprecation warning.
That being said, having a builbot testing at least the build of ParaView would be awesome :slight_smile:

1 Like

My thoughts at that time (13 years ago), were a bit extreme. In the heavily templated ITK, single compile error could go on for pages… Today’s compilers often give good suggestions on how to fix the code.

Den ons 17 juli 2019 09:56Mathieu Westphal (Kitware) via VTK noreply@discourse.vtk.org skrev:

A good document, but I have reservations about certain points.

those changes should never cause user code to fail to compile

Too extreme imo. Deprecated code can be removed at some point.

As a user of VTK I think it would be nice if VTK followed an ABI/API compat and deprecation policy similar to Qt’s. That is, maintain compat across minor versions, but allow breaks across major ones, and have deprecation macros so that use of deprecated APIs show up as warnings for at least one minor version before being dropped in a major one.

It is of course up to you folks what kind of commitment you’re willing to make, and I understand if this would be a too big ask.

We’re one of those Kitware-external users who, unlike e.g. ParaView, do not track VTK master. But we try to follow each minor release. It would be nice if, like with Qt, we could be guaranteed an essentially painless upgrade when moving between minor versions.

Cheers,

Elvis

We would need to fix VTK_LEGACY_REMOVE to work as a versioned check rather than be a global on/off switch. This would allow deprecations to be marked with VTK_LEGACY_API(8, 90, 0, 20190723) where ParaView could then set VTK_COMPAT_API=VTK_COMPAT_VERSION(8, 90, 0, 20190722) (or something) to say it is OK with API removals up until the 22nd and hides anything with a removal older than that and warns for anything deprecated since then.

3 Likes

@ben.boeckel : That would indeed be a very nice to implement that. I think not only ParaView would benefit but other VTK dependant software as well.

In the meantime, actually deprecating public API instead of removing it altogether would already be a nice touch.

I’m 100% OK with such a change. I do not have time to implement, test, and document, but I can help with the review.

As for the API guidelines, I suggest notifying those who do this via the MRs that break it and tell/ask them not to do it anymore. I don’t know how many read this board.

Issue created :
https://gitlab.kitware.com/vtk/vtk/issues/17649

I’ve also created an issue for the buildbot as well :
https://gitlab.kitware.com/vtk/vtk/issues/17650

And use actual deprecation instead !

I’m trying deprecate a method cleanly right now. I’m only trying to add a another argument to a virtual method.

It is doable but definitely not easy nor trivial.

Also, I couldn’t find a way to inform a potential VTK users that he is inheriting from a deprecated method at compilation time.

They’ll get -Woverload-virtual warnings because their override is shadowing the other overload they’re not using.

with VTK_LEGACY_REMOVE=ON indeed, but not with VTK_LEGACY_REMOVE=OFF.

They’ll actually get errors in that case. Their override on the method will say “you’re not overriding anything”. And they’ll get the -Woverload-virtual warning.

Not sure to follow. With VTK_LEGACY_REMOVE=OFF, there should be no errors and the results should be the same. There should be warnings though.

If they are not overriding, then results can’t be the same.

If you want to take a look into the specifics of my implementation, it’s here https://gitlab.kitware.com/vtk/vtk/merge_requests/5915, especially 1a56e913efbf778c068eb3420ae8b82e8fb5a5c6

FYI : my “non-breaking-api” deprecation change have been merged. It was more complex then expected and may be of interest of people trying to achieve the same thing.
https://gitlab.kitware.com/vtk/vtk/commit/09e99a46df7ffb761abf0d7c5688ec70b476d4b1

For some explanation of the logic, see the discussions there :
https://gitlab.kitware.com/vtk/vtk/merge_requests/5915

Late followup, but seems like the most appropriate place to tag on my question.

Are there any general rules (does/doesn’t) when needing to change the header interface of particular classes?

Adding/removing member data will change the allocated size for the object, so ABI-breaking even if the API stays the same. So do you manage to track a state change of a toggle, without breaking that? Or are we allowed to do that at some particular time?
Presumably it’s OK though to add new methods - different name (not just a different signature) since that would not break things?

The major/minor version numbers are added to VTK’s library names by default, so minor versions already don’t have ABI compatibility. Between patch versions (e.g., x.y.0 -> x.y.1), ABI should be preserved. API should be preserved as much as possible otherwise (deprecation warnings allow for removal after they’ve been in a release).

1 Like

Adding things is usually fine. Removing them or changing signatures is the main concern.

1 Like

One would also need to consider the implication of a change. Changing the API of vtkDataSet has way more implication than changing the API the to vtkOpenFOAMReader, which has more implication than changing the API of the vtkLagrangianMatidaIntegrationModel (only examples here, but you get the point).

1 Like

This all sounds good and reasonable. If there are any API changes needed (in the OpenFOAM reader, for example), will flag ahead of time to see that it all slots in nicely.

Many thanks!
/mark