API breakages - file bugs / update HACKING.txt ?
John Arbash Meinel
john at arbash-meinel.com
Wed May 21 16:14:05 BST 2008
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Jelmer Vernooij wrote:
| In order to make life easier for myself as bzr-svn maintainer and for
| its various packagers, I would like to get rid of the (currently very
| strict) coupling of bzr-svn and Bazaar releases.
|
| bzr-svn only uses public Bazaar APIs but the ones it uses are not used
| by many other plugins and at least one breakage (without deprecation)
| happens each Bazaar release (Bazaar 1.2 being the only exception),
| despite HACKING.txt saying there is a commitment to 6 months API
| stability. Is this still the intention for all public APIs?
|
Actually, it isn't so much that it "uses" only public APIs, but it *implements*
them. So we might have a function Branch.foo(). We add an option parameter:
Branch.foo(bar=None). Now, callers that called Branch.foo() will still work.
However, some will be updated to pass Branch.foo(bar=XXX). As bzr-svn overrides
foo() it now has to support the (optional) parameter.
One way to get around it is to change all of the public Branch functions into
double-blind ones. So that you have an abstract base class with:
~ class Branch:
~ def foo(self):
~ return self._do_foo()
And then you would override the _do_foo() parameter and not 'foo()' directly.
That way if we add a new option parameter, we can do:
~ def foo(self, bar=None):
~ if self._supports_foo_bar:
~ return self._do_foo(bar=bar)
~ else:
~ # Work around whatever 'bar' does, possibly even giving a
~ # DeprecationWarning about 'bar' not being supported
~ return self._do_foo()
The other option is that you have to introduce a new function everytime you want
to add an optional paramter. So you end up with:
~ def foo2(self, bar=None):
~ if self.foo != Branch.foo:
~ # Custom override, workaround for 'bar'
~ return self.foo()
~ else:
~ # Do what we want to do with foo
You end up accumulating a lot of cruft. And the second form is the same as the
first, except you only create the thunk function when you actually need it,
rather than all the time. At the expense that now all callers actually need to
change what function they are calling, and your namespace gets polluted with
thunk functions.
I mentioned doing this a long time ago, but I think the consensus was that while
we would preserve compatibility for callers, we wouldn't go for the overhead of
doing so for implementers.
I realize this puts bzr-svn at a disadvantage.
OTOH, a newer bzr-svn should work with an older bzr. If bzr-svn has
"foo(bar=None)" then an older bzrlib that doesn't supply 'bar' shouldn't care.
As for compatibility, I know I have a plugin which hasn't been updated in 2
years, which still works (update-mirrors). It isn't very complex, though, so it
certainly doesn't touch a lot of internals.
| I realize that there is overhead in deprecating rather than directly
| removing APIs and so it makes not to deprecate when the API is not used
| by any plugins. I could file bugs (before bzr releases) whenever bzr-svn
| uses an API that wasn't properly deprecated so it can be fixed before
| the release.
I would certainly like to know what is breaking. If we are actually breaking
clients versus implementers, etc. And knowing what functions are broken should
certainly be documented.
|
| If HACKING.txt is outdated, what is the current policy wrt API breakage?
|
| Cheers,
|
| Jelmer
I could be wrong, but that has been my understanding.
I would also go one step further, in that we are pushing pretty hard to clean up
some of the internals, and we've come to a few places where maintaining
compatibility was too far on the cost versus reward balance.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkg0PD0ACgkQJdeBCYSNAANFEACfXs03ZFEmAs0DD8LoYDUWAq4H
zIUAn2Z2Ll3LDKJjJWERHuZa2GBR2Iib
=wwKF
-----END PGP SIGNATURE-----
More information about the bazaar
mailing list