39

I am maintaining a public API and have to deprecate a method.

Is there a general rule on how many months/years/versions before the deletion I should deprecate a method?

Justin
  • 176
  • 9
deviDave
  • 2,933
  • 5
  • 26
  • 30
  • 27
    The general rule is "keep it around for as long as you and/or your customers need it." – Robert Harvey Nov 20 '18 at 15:58
  • Well the point is to allow for a graceful way to change needs. – candied_orange Nov 20 '18 at 16:24
  • 15
    Define "public". Free, open source software, with the usual "use at your own risk" disclaimer? Or sold software where a contract exists? – Doc Brown Nov 20 '18 at 16:58
  • 11
    This very much depends on what market your users are in and whether or not they are paying you money for the API. – 17 of 26 Nov 20 '18 at 17:46
  • 3
    And how quickly they are willing to adjust to change. If this is a SaaS API (as opposed to a packaged library), then you should definitely be keeping metrics on how much each of your endpoints is used. – chrylis -cautiouslyoptimistic- Nov 20 '18 at 20:01
  • 10
    It also depends on why you "have" to depreciate it; is the old way a security risk? Did you just now find a reason why the old way is fundamentally and unfixably unstable due to an unfortunate design decision? Is the old way far slower now than it used to be? Are you running out of memory on your target system (e.g., an embedded system) and you literally cannot fit both APIs on it? Or did you just find a "better" way and you just want to clean out the old code to reduce your maintenance overhead? – jrh Nov 20 '18 at 20:49
  • 8
    `java.io.StringBufferInputStream` deprecated since JDK 1.1 (1997?). There's no good or wrong answer to this question. It depends on your needs to provide backward compatibility. – Laiv Nov 21 '18 at 07:41
  • @DocBrown The later one. Public one with paid customers. – deviDave Nov 21 '18 at 09:15
  • @deviDave: then you have to be very careful when making things deprecated. Your customers may complain you are going to strip functionality they have paid for. And if there was an API documentation at the time when the contract was signed, a lawyer could interpret that API documentation as part of the contract, so without asking for permission of all your customers, you may run into trouble. Better you make rukes for deprecation and non-backwards compatibility of newer versions an explicit section in your license terms or individual contract. – Doc Brown Nov 21 '18 at 12:26
  • Google often gives 1 year left of life when deciding to remove a feature: so the deprecation period for Google products is often exactly 1 year. – Cœur Nov 21 '18 at 14:23
  • 3
    I would add increasingly verbose warnings in each minor version before removing it. – Chloe Nov 21 '18 at 17:29
  • 1
    If this is for paying customers, then the deprecation period is whatever you agreed with them when they bought your service. – Jörg W Mittag Nov 21 '18 at 21:53

8 Answers8

53

At minimum, you should keep deprecated methods in one version before removing them which seems kind of obvious when I write it out. I don't think there is a maximum time but if you never actually remove them, deprecation becomes a little pointless.

Major version releases are a good time to remove deprecated methods. Minor releases should typically not contain breaking changes. As cHao has noted in the comments, deprecation doesn't necessarily imply that there will be an eventual removal so if you plan to remove things after deprecation, you should explicitly note that and provide some guidance on the timeline.

JimmyJames
  • 24,682
  • 2
  • 50
  • 92
  • 59
    Deprecation isn't necessarily about eventual removal, so deprecation without removal isn't pointless (and is often the right thing if backward compatibility is important). Often the point is nothing more than "we have a better way now, so you shouldn't do it this way anymore". – cHao Nov 20 '18 at 19:41
  • 9
    @cHao If something is deprecated, you should not expect it to continue to be there. I suppose if you want to make a special statement in your project that states you will not remove deprecated functionality, that's fine but otherwise, yes it is implied that there will be eventual removal. The point I am making is that if you don't maintain some sort of rigor around this, people may come to believe that it won't ever happen. This has come up with recent versions of Java where functionality that has been deprecated for a decade or more is now being removed. – JimmyJames Nov 20 '18 at 20:24
  • 6
    @cHao I'd rather a project remove its deprecated functionality. Not only is there the benefit of users actually being motivated to switch, but it also prevents the deprecated interface from interfering with other improvements. – jpmc26 Nov 20 '18 at 21:19
  • Those who value backward compatibility will argue that the removals shouldn't have happened. And from that point of view, they are correct. Removal of functionality is a breaking change, and frankly, shouldn't be done without a clear policy in place. Not because new code should be able to do the old and busted things, but because *old code already does*. Deprecation in those cases is a tool to let old code do its thing while discouraging new code from doing it too, not a warning of future removal. – cHao Nov 20 '18 at 21:19
  • 2
    @cHao Users who need the old interface can stick with the old versions until they're ready to upgrade. Typically, when something is deprecated, the new interface is already available in the old version. This allows users to switch at a more regulated pace. – jpmc26 Nov 20 '18 at 21:20
  • 2
    @jpmc26: I don't see users being motivated to switch. I see them being motivated to stay with old and busted versions because newer versions don't run their software. Unless you mean the developers using the API, who have already been using the new functionality for their new code, but don't (and frankly, shouldn't have to) make gratuitous changes to their old code to keep it on the treadmill. – cHao Nov 20 '18 at 21:23
  • 2
    @cHao I see users (or pointy-haired bosses) motivated to not switch because switching is a visible cost and staying is an invisible cost that's much harder to measure, but it's generally not free. If sticking with the old one was a good idea (free), then you wouldn't be deprecating it. Removing it presents a visible cost for consideration: you won't be able to continue upgrading. Or if the library you're using is deprecating stuff just for the sake of change and not actual improvement (a "treadmill," as you put it), I say the time is better spent finding a better library. – jpmc26 Nov 20 '18 at 21:26
  • 9
    @cHao It's a context sensitive thing. In my experience the policy of deprecation is clear. It's clearly stated that deprecated functionality will be removed at some point in the future. Often deprecated functionality has issues making it problematic for use and it's not simply a matter of whether you value backward compatibility or not. – JimmyJames Nov 20 '18 at 21:31
  • 1
    @JimmyJames: If the policy is explicit, that's OK. But deprecation doesn't imply future removal; you have to mention it. The problem with Java is less that stuff got removed, and more that the removal broke the compatibility that was Java's single biggest selling point for a pretty long time. Partly because they implied their policy rather than stating it. – cHao Nov 20 '18 at 21:37
  • 6
    I'm going to chime in to agree with @JimmyJames that deprecation clearly implies impending removal. The deprecation period exists as a way of providing temporary backwards compatibility so the consumers can migrate to the newer functionality. There should be absolutely no expectation that the deprecated functionality will remain indefinitely. If the old functionality is going to remain, there's no reason to deprecate it. – Eric King Nov 20 '18 at 23:09
  • 2
    @cHao If the policy isn't explicit, then get to work with whomever you need to work with to come up with an explicit policy, publish that policy, and start following it. Keeping things around indefinitely is sometimes necessary but it's an asinine default. – Iron Gremlin Nov 20 '18 at 23:45
  • 6
    @EricKing: Of course there is a reason, and it becomes obvious when you stop trying to conflate deprecation with warning about removal. My first comment gave a reason, and my second clarified it. Deprecation is guidance for new code. Old code quite obviously can't account for it. You can guide new code to use the better way without breaking old code. – cHao Nov 21 '18 at 00:21
  • 1
    I don't understand why there's an argument here. A public API is a *contract* with your users. Deprecation says "you can use this still, but don't be surprised if your code breaks at some random date as I am no longer promising this will be there". There's no onus to remove deprecated content, you've just removed the implied continuity. If they want to run the risk that is and should be their choice to do so. – Jared Smith Nov 21 '18 at 12:41
  • 3
    This conversation is exactly why Java (and the Java community at large) shouldn’t have waited a decade or more to remove deprecated functions. If you deprecate, but never remove, people will continue to rely on old, and possibly broken, functionality. – RubberDuck Nov 21 '18 at 13:44
  • Yes, exactly. Deprecation means "Stop using this. You have been warned. It may be removed in any future version." And @cHao, I disagree with your reason. When you say "removal of functionality is a breaking change", I agree with that, with the exception of _deprecated_ functionality. Removal of deprecated functionality is _not_ a breaking change. – Eric King Nov 21 '18 at 15:20
  • @EricKing I looked at the actual description of the deprecated annotation in Java and cHao's point is correct (at least for Java.) It doesn't say anything about removal. Typically there is a comment that goes with it that says it will be removed. – JimmyJames Nov 21 '18 at 15:30
  • @cHao After considering your point more, I have to agree with you and have updated the answer to reflect that. – JimmyJames Nov 21 '18 at 15:33
  • 3
    I dunno. [According to Java documentation](https://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/deprecation/deprecation.html) (emphasis mine): "**What "Deprecated" Means** You may have heard the term, "self-deprecating humor," or humor that minimizes the speaker's importance. A deprecated class or method is like that. It is no longer important. It is so unimportant, in fact, that you should no longer use it, since it has been superseded **and may cease to exist in the future**." – Eric King Nov 21 '18 at 15:44
  • 3
    Also [here](https://docs.oracle.com/javase/8/docs/technotes/guides/javadoc/deprecation/index.html). "A deprecated API is one that you are no longer recommended to use, due to changes in the API. While deprecated classes, methods, and fields are still implemented, **they may be removed in future implementations**, so you should not use them in new code, and if possible rewrite old code not to use them." – Eric King Nov 21 '18 at 15:48
  • 3
    Hence why the original question isn't "should a deprecated method be removed?" but "how long should we wait before removing deprecated method?". The impending removal is implicit. – Eric King Nov 21 '18 at 15:52
  • @EricKing I agree with you that you should not expect deprecated methods to exist in new versions. But it's also true that the documentation for [Deprecated](https://docs.oracle.com/javase/7/docs/api/java/lang/Deprecated.html) doesn't say anything about removal. So the upshot for me is: as a user, assume they will be removed and as an author be explicit about your plans. It's somewhat like the adage "be liberal in what you accept and conservative in what you provide". – JimmyJames Nov 21 '18 at 16:08
  • 1
    @JimmyJames That users of a deprecated method should "assume they will be removed" is exactly the point I was trying to make. Not sure why it's in the least controversial. It's been that way, even in Java, for a very long time. – Eric King Nov 21 '18 at 16:40
  • @EricKing: removal of functionality, even deprecated functionality, can cause existing, working software to fail -- and thus *is* a breaking change, by definition. You don't get to ignore that just because it's only old software that breaks. Deprecation doesn't imply that you're going to break anything; in fact, the entire point is to allow old code to work while steering new code toward the better way. – cHao Nov 21 '18 at 18:43
  • **[There are two meanings for the word "deprecated."](https://unix.stackexchange.com/a/126928/135943)** One directly implies future removal, the other does not. Trying to pretend that *all* uses of the word must mean the same thing is just ignoring the nuances and multivariable aspects of the English language. Sorry, fellas: English is not a context-free grammar, words can have several meanings, and ambiguous statements are extremely common. – Wildcard Nov 21 '18 at 19:26
  • 1
    @Wildcard Luckily, there is no lack of context in this case. – Eric King Nov 21 '18 at 20:24
16

This depends solely on what kind of stability guarantees you gave to your users, and how much pain you want to cause for your users.

Ideally, your API uses semver so that any breaking change causes the major version number to be incremented. In practice, it is desirable to do this almost never. If your API is installed via some package manager, you may want to create a new package name after a breaking change so that a simple upgrade doesn't cause conflicts (e.g. myapi2 v2.123.4 vs myapi3 v3.2.1). That may be unnecessary if your package manager supports tighter version dependencies (e.g. a dependency specification like ~v2.120 that does not include v3.*), but different package names have the advantage that incompatible versions can be used side by side very easily. Even when using semver, it can be sensible to have a deprecation period.

Semver is not always applicable. Then it is more important to communicate a clear stability policy. For example:

  • Experimental features may be removed without notice.
  • Features may be removed for security reasons at any time.
  • Other features will only be removed
    • … after having been deprecated in a released version
    • … where that version is at least three months old
    • … and will be marked by a bump in the major version.

Such policies work particularly well when you have regular releases so that there is a clear deprecation period, e.g. one year.

Aside from marking any parts of the API as deprecated, you should make the deprecation widely known. For example:

  • Have a section in your changelog about future directions and deprecations.
  • Broadcast your intention to deprecate before you perform the deprecation, and listen into the community to see if there are substantial objections.
  • Communicate what benefits will come from these changes. Depending on your user base, newsletters, presentations, blog posts, or press releases might be appropriate media. Having a spin “we are creating an awesome new feature! (which requires this widely used old feature to be removed)” is a bit less frustrating than removing a feature without context.

As for the exact deprecation period to choose, first look whether you have to honor any support contracts with your users. Such contracts may require you to maintain compatibility for some period. If not, consider any downstream impact. Try to change less rapidly than downstream users so that they can go through a deprecation cycle of their own. Downstream users will take some time to adapt to your changes, so you should never have a deprecation period shorter than a month.

amon
  • 132,749
  • 27
  • 279
  • 375
  • 3
    Downvoted because of this: `Ideally, your API uses semver so that any breaking change causes the major version number to be incremented. In practice, it is desirable to do this almost never.` What is the point of using semver to indicate breaking changes if you're following that by saying you should never introduce a new major version? – mrsmn Nov 21 '18 at 10:24
  • 6
    Is it really a good idea to rename the package if there is a major change? That's what version numbers are for. I hate when they also rename them, it really messes up Maven dependency management. – AJPerez Nov 21 '18 at 10:36
  • @AJPerez I understand that's not ideal, but it can prevent conflicts in large dependency graphs with transitive dependencies: I depend on libfoo which depends on libconflict v1.2.3, and I also depend on libbar which depends on libconflict v2.3.4. Then, I cannot select any libconflict version that satisfies all dependencies – unless libconflict and libconflict2 are distinct packages. Specifically for Java, such renaming is annoying b/c I have to change all imports. Fortunately, Java 9 (modules) supports using conflicting versions. – amon Nov 21 '18 at 11:53
  • 1
    @mrsmn Breaking changes are annoying however you package or name them. Semver only addresses a small part of this problem: being able to tell whether an upgrade will break anything. But once you have a breaking change, you still have to expend effort to accommodate this change. Therefore, it's better if APIs try very hard to be as stable as possible. Ideally they are designed in a way so that they can be extended without breaking backwards compatibility. – amon Nov 21 '18 at 11:58
  • @AJPerez yes. Yes it is good. People screw up the versioning all the time. Bug fixes (presumed x.x.x++) often are breaking (presumed x++.x.x). As amon points out you (and I do mean *you* as the user of the dependency) have a problem that you have to fix. I *know* my code works with foo 3.2.1, it *may* work with foo 3.3.0. I *know* my code works with foo, it *may* work with foo-2. I use semver because popularity and it doesn't hurt per se, but it really isn't clear to me that it buys you all that much. – Jared Smith Nov 21 '18 at 12:48
  • @AJPerez No, it's a terrible idea that makes finding the latest version of your package much harder. Even if your package manager handles it well enough, it just breeds confusion. – jpmc26 Nov 21 '18 at 22:23
15

Ideally, you would want to wait until no one is using the deprecated method anymore. Considering you're using a public API, that's easy to track, but you might end up waiting a very long time.

in 2015, Google had a similar issue with the stlport API on their Android OS. They had deprecated it and wanted to remove it, but tons of apps were still using it. They found a clever solution:

enter image description here

Essentially, they added an 8 second sleep() during the bootup of any app which still used the API with an appropriate log message for the developers. A month later, they doubled it to 16 seconds. then another month later, they could safely remove the API interface because no one was left using it.

This can be a very effective way of doing this. The only real issue is if your API is very old and has actively used consumers that are no longer actively supported. Unfortunately, you probably won't be able to fix such consumers yourself, but at that point you can't really do much more than delete the method and break the consumer.

Nzall
  • 1,326
  • 9
  • 15
9

The minimum time for providing deprecated methods depends on the development cycles of programs using your API. As a ballpark figure, 1 year should be enough.

As for the maximum time before you have to remove deprecated methods, I'd argue that there is no such thing. No matter how long you wait, removing a deprecated method will always break something. Some programs using your deprecated API are not actively maintained, and breaking compatibility will mean the end of life for such programs.

I suggest you remove deprecated methods when you gain something from the removal:

  • a bug is detected that affects deprecated methods specifically
  • you're about to refactor the code and maintaining deprecated methods would require significant effort
  • you're optimizing the internal structure of your library, and deprecated methods don't fit in anymore.

Removing deprecated methods just because they were deprecated for X months/years or because you're releasing a new version amounts to arbitrarily harming compatibility with no good reason.

Dmitry Grigoryev
  • 494
  • 2
  • 13
7

First you should consider whether you want deprecated or obsolete.

Deprecated should be used for methods that are in some way harmful: security, performance, incorrect results. You want to get rid of them relatively quickly, no more than 2 major version and gone by the 3rd. For significant enough problems, deprecated may be deleted in the next minor version.

Obsolete is for things that are less useful for some reason, for instance returns less information or doesn’t work as well, doesn’t include as many options and so forth. These can hang around indefinitely, but should at a minimum be present in the next major version.

jmoreno
  • 10,640
  • 1
  • 31
  • 48
  • I'd say a method giving incorrect results or harming security should be either disabled immediately, or fixed. A method with bad performance can hang around indefinitely, so long as its performance is acceptable for some users. – Dmitry Grigoryev Nov 22 '18 at 13:25
  • @DmitryGrigoryev: a single minor version is pretty close to immediately. – jmoreno Nov 22 '18 at 17:14
4

The answer depends on what sort of service you are giving to your customers.

On one end of the extreme, there are mistakes in Windows.h from the Win 3.1 era that propagated for two decades because Microsoft believed very strongly in backwards compatibility.

On the other end of the spectrum, many web-apps remove features without even providing a deprecation warning.

How much your clients are paying for your software often matters, as does their line of work. Research scientists are typically more willing to accept deprecation as part of the march of progress than, say, bankers or the FAA.

I worked for a company developing software for internal use. I supported many groups over the years. One group had a "never remove any feature" mentality. They needed the ability to go back to files 5-10 years ago and do analysis on them on timescales too fast to get developers to put features back in. One group's attitude was "make sure all the deprecations are in the patch notes, so we can find them later." In the middle, we had one group whose rule was "Features must be deprecated for at least 1 version with a printed warning if they are used before removing them." That group had a test suite that covered the features they needed. Whenever we released a new version, they quick ran their test suite against it to see if any of the deprecations gave them trouble.

Cort Ammon
  • 10,840
  • 3
  • 23
  • 32
4

I am maintaining a public API and have to deprecate a method.

Why do you need to do this? Is it because there’s a new shiny way to do things, so the old method is now discouraged, but still works fine? Or does the old method actually need to go because things have fundamentally changed?

  • If the old method isn’t causing any actual problems, and can stick around, then it may as well. If ain’t broke, don’t fix it. Do you really need to remove it? Maybe mark it as obsolete, and include a note in the documentation that another method might be more efficient, or whatever, but it’s probably fine to leave it in place.

  • If the old method really does need to go, because it’s causing you maintenance headaches, or because it simply no longer makes any sense due to other changes, then monitor its usage and communicate the deprecation clearly to clients. Give them a clear date after which the method will be removed. (Ideally, don’t actually remove it immediately on this date: wait until no one is still using it before actually removing it. It may need to go sooner, if it’s really causing problems, but at least wait for the usage to drop a little.)

  • If the old method is causing security problems, you may need to move faster than that, possibly even removing it without warning, but you should document this change somewhere very visible, and also return sensible messages to clients which attempt to use the old method.

(The second and third bullet points are well covered in other answers, but I think the first one is new.)

TRiG
  • 1,170
  • 1
  • 11
  • 21
1

For a public project, only remove it if and only if you need to.

When you do unnecessary API removal, you're costing money for companies and contractors in such a way that you can't even calculate due to costly churn.

Want companies and independent programmers to stop using your project? Break their stuff enough times when you're not essential and you'll be in that boat in no time.

deprecation != eventual_removal. If an API is dangerous, you remove it. If it's just old, leave it and document its replacement.