RQ1: Reaction Patterns to Deprecation
We manually analyze 380 usages of deprecated API artifacts across consumers of 50 APIs. Based on this analysis, we observed seven reaction patterns (RPs) to deprecation. We describe these patterns, following the same order in which we discovered them in the manual analysis:
- RP1:
No reaction – API consumers do not do anything with the reference to the deprecated feature in their code base. The reference remains in the source code till the latest available version of the consumer code.
- RP2:
Delete invocation – API consumers react by removing the invocation to the deprecated feature, without replacing it with the replacement recommended by the API producers or any other functionality.
- RP3:
Replace with recommended replacement – API consumers replace the deprecated API element with the alternative proposed by the API producers.
- RP4:
Replace with in-house replacement – API consumers remove the invocation made to a deprecated feature and replace it with a functionality that they themselves create.
- RP5:
Replace with Java replacement – API consumers replace the deprecated invocation with an equivalent functionality provided by the Java Development Kit (JDK).
- RP6:
Replace with other third-party API – API consumers choose to switch API and replace the deprecated invocation with a non-deprecated one from the API to which they switch.
- RP7:
Rollback version of the API – API consumers rollback the version being used such that the used feature is no longer marked as deprecated.
RQ2: Dealing with the Deprecation of a Feature
After having identified the possible reaction patterns (RPs), we investigate their occurrence among all the clients.
RQ2a: Version Upgrade Behavior
We begin our investigation by looking into how many of the API consumers in our dataset have changed the version of the library that they use.
We compute the percentage of consumers that upgrade the version of the dependency in our dataset. Overall in our dataset we see that not many consumers upgrade the version of the API. None of the APIs has more than 13% of its consumers upgrade their dependency version. For APIs such as ‘standard’ and ‘dom4j’ the percentage of consumers upgrading version is less than 5%. For the widely popular APIs such as ‘slf4j-api’ and ‘junit’, only 12% or less of the consumers upgrade.
To triangulate this unexpected finding with another source, we asked to our survey respondents (see Section 3.7) whether they upgrade the version of the API that they use. Among the respondents, 31% of the API consumers indicated that they always upgrade the version of the API being used, while a majority of 69% indicate that they only do this occasionally or never. We asked this 69% to rank (on a five point likert scale) the frequency with which one or more motivations behind not upgrading the version of the API has applied to them. These motivations are a result from previous work, literature on deprecation and documentation on deprecation. The results of this can be seen in Fig. 2.
The upgrade cost, in terms of time or money, is the most common reason (42% of consumer rating it as ‘almost always’ to ‘always’) for not having upgraded. A 41% of the consumers reported not having upgraded (‘almost always’ to ‘always’) when everything in the current version of the API worked just fine. This is in line with what Sawant et al. (2018b) found. Breaking changes in the new version only stopped 32% of consumers from upgrading; in fact, 48% of the API consumers are neutral about this. Conversely, deprecation is seen as an even smaller barrier to upgrading, with only 9.7% consumers indicating that it has stopped them from upgrading the version of the API. A 22% of the responding consumers indicate that they have a policy to freeze the version of the API that they use (52% of consumers actually indicate that they have no such policy).
API consumers also provided us with additional reasons to not upgrade. One consumer indicated that management in the company that he worked in did not allow for dependency upgrades. Additionally, when a project reached a stable point it was no longer needed to upgrade the dependency.
RQ2b: Frequency of Reaction Patterns
After having investigated the overall upgrading behavior of API consumers, we look into how API consumers react to deprecation by analyzing how frequently they adopt one or more of the reaction patterns that we found in RQ1.
For each RP, we present: (1) the results gathered during the manual analysis conducted to answer RQ1 (in terms of both RP occurrence and the qualitative description of clients’ behavior), (2) the dedicated heuristic we devised to automatically detect whether the RP takes place,Footnote 3 and (3) the number of overall occurrences and unique consumers of the RP across the 297,254 API consumers pertaining to the 50 considered Java APIs.
We test the validity and accuracy of our heuristics by running them on the source code files of the 380 samples that were manually analyzed in Section 4.1. Our heuristics are able to identify the correct reaction pattern in 100% of the cases. Moreover, this analysis also confirmed the exhaustiveness of the patterns created in RQ1: None of the analyzed cases let emerge new patterns.
We then analyze the fallibility of our heuristics to see whether they incorrectly classify a pattern (i.e., establish the false positive rate). We manually analyze 100 cases of the automated classification for each of RP1, RP2, RP4, RP6 and RP7. For RP3 and RP5, we analyze all the cases since there is a limited number. For RP1–3, RP5, and RP7 we do not see any false positives. In the case of RP4 we see 7 instances where the replacement of deprecated feature with an in-house replacement did not make sense as the functionality being replaced was not the same. In the case of RP6 we observed 18 instances where the third-party API replacement does something completely different to the original API. However, looking deeper at these 18 cases we found that in 4 of these cases the developers had made a conscious choice to change functionality hence a one to one mapping was not needed. For the other 14 cases we could not precisely establish a rationale.
Overall, over 297,254 API consumers, we see a total of 9,317 projects that are affected by deprecation and react in one of the ways we have found. Over these 9,317 projects, we see 165,216 usages of deprecated methods to which reactions take place. The occurrence of each reaction pattern is summarized in Fig. 3 and Table 1.
Table 1 Breakdown of number of reactions per reaction pattern - RP1:
No reaction
- Qualitative analysis:
Total occurrences: 290 (76%) Unique consumers: 221 (88%)In the manually analyzed sample set, not reacting to a deprecated functionality is the most popular reaction pattern. On the one hand, this behavior may be explained by the fact that the cause of deprecation was not severe (we inspected the cause and there were no security or performance issues); on the other hand, this behavior is also unexpected, since all the deprecated entities that were not reacted to had recommended replacements and were well documented.
- Detection heuristic::
We look at the first version of a file that contains a deprecated feature and then the last version of the file, we see if the references to deprecated features have been removed in the last version. In the event that these have not been removed, we mark it as a ‘non reaction’.
- Quantitative analysis::
Total occurrences: 146,076 (88%) Unique consumers: 8,910 (95%)Also in the large scale analysis, we found that the most frequent pattern is to not react to deprecation (88% of the time, for the majority of the projects–8,910 out of 9,317). This is despite the fact that the APIs that we consider are all popular and well documented mainstream Java APIs. Looking deeper at these non-reactions we notice that in 55% of the cases the files containing invocations to deprecated features not being reacted to do not change. This might be due to the fact that the file is already stable and requires no more changes. We cannot ascertain whether this code is being executed currently, however, given the active nature of the projects selected we do expect that the code is still being used in some manner. Due to this behavior, consumers simply might not notice that they are using a deprecated feature.
- RP2:
Delete invocation
- Qualitative analysis:
Total occurrences: 23 (6%) Unique consumers: 4 (1.5%)Deleting a deprecated invocation occurs frequently among the API consumers, in the manually analyzed dataset. We investigated the deprecated methods that have been removed: In two cases the deprecated feature was supposed to be removed, since its usage was no longer needed; in the rest, the feature has a recommended replacement, however, the consumers delete the reference. In none of the cases do developers give any rationale behind the deletion.
- Detection heuristic::
When going through the different versions of a file containing a reference to a deprecated feature, if the number of references to deprecated features reduces and no new invocation is added in the same location in its place either from the same API or any third-party API, we mark it as a ‘deleted invocation’ with no replacement.
- Quantitative analysis::
Total occurrences: 1,015 (0.6%) Unique consumers: 218 (2%)Deleting and not replacing the invocation is also seen in over 1,000 cases in the large scale analysis. Some of these deletions with no cause might stem from the fact that the API required the deprecated method to be handled in that manner (as we have seen in the qualitative analysis), however, it is reasonable to expect that this might not always be true (as we have also seen in the qualitative analysis).
- RP3:
Replace with recommended replacement
- Qualitative analysis:
Total occurrences: 12 (3%) Unique consumers: 2 (0.8%)Replacing a deprecated invocation with its recommended replacement is unpopular amongst API consumers. In our manually analyzed sample set, all the deprecated methods are documented and provide clear instructions as to how the deprecation should be handled. This makes it all the more surprising that we see very few reactions of this nature. Looking at the commit message for those API consumers that have actually replaced the deprecated invocation with the recommended replacement, they simply state that some changes were made due to the upgrade in the API version being used. In fact, in many cases, the reaction to deprecation was performed at the same time as the upgrade to the version of the library. Some API consumers react to deprecation immediately after noticing the deprecation.
- Detection heuristic::
For the API in question, we create a set of package names in the API over the entire history of the API, to verify whether an invocation added to a file belongs to one of these packages. In a version of a file in which a deprecated feature is removed, we check whether a new invocation is added to the same API in its place. If there is a new invocation made to the same API, we mark it as a ‘replacement’.
- Quantitative analysis::
Total occurrences: 36 (0.02%) Unique consumers: 7 (0.07%)Replacing a feature with its recommended replacement is the second least frequent way in which API consumers reacts. In practice, only 7 API consumers choose to react in this manner. These 7 API consumers have replaced the deprecated feature in 36 (0.02%) cases and they do not react in any other manner to deprecation; furthermore, they replace all invocations being made to deprecated features. Thus, similarly to the qualitative analysis, we observe that consumers that do react to deprecation “as intended” tend to be systematic about it.
- RP4:
Replace with in-house replacement
- Qualitative analysis:
Total occurrences: 2 (0.5%) Unique consumers: 1 (0.4%)In two cases, the deprecated invocation is replaced by some functionality developed by the API consumer itself. Both cases belong to the Hibernate API. The API consumers have in each case replaced a database mapping invocation with their own wrapper around the database. The reason we found evidence for is that the Hibernate API was changing too much and it was not deemed worth keeping up with the changing API.
- Detection heuristic::
We start by looking at all the files and packages in a given project and create a set of package names that the project itself has defined, this is the list of packages from which a feature can be imported. When in a version of a file we see that a deprecated feature is removed, we look to see if it has been replaced by a feature pertaining to one of these in-house packages.
- Quantitative analysis::
Total occurrences: 702 (0.4%) Unique consumers: 31 (0.3%)Replacing with in-house functionality is done in 702 cases. Thus, in a non-negligible number of cases, API consumers have taken the effort to implement functionality that has been provided, yet deprecated by an external API.
- RP5:
Replace with Java replacement
- Qualitative analysis:
Total occurrences: 6 (1.5%) Unique consumers: 1 (0.4%)In our sample set, many of the APIs extend the functionalities of the Java API or provide alternatives to existing Java libraries. These are seen in the case of the Guava API’s consumers. The consumer replaced references to the Guava Map class with those to the Java Map class. There was no reasoning given by the API consumer in the commit or in any pull request as to why the change was made. We speculate that using functionality from the Java API was deemed to be easier and safer than using deprecated features from the Guava API.
- Detection heuristic::
Java libraries start with one of three prefixes: java, sun and javax. If we see a deprecated feature is removed and—in its place—we see a new invocation being made to a method which belongs to a class whose package name starts with one of the prefixes, we infer that this reference to a deprecated feature has been replaced by a feature from Java and mark it as such.
- Quantitative analysis::
Total occurrences: 17 (0.01%) Unique consumers: 3 (0.03%)The least frequent way (17 cases or 0.01% of the time) for an API consumer to react is to replace the deprecated functionality with an invocation to a Java API feature. This could be explained by the fact that all third-party APIs seek to offer functionalities beyond the Java API building on top of it.
- RP6:
Replace with other third-party API
- Qualitative analysis:
Total occurrences: 28 (7%) Unique consumers: 13 (5%)More than one API may provide the same functionality. For example, Easymock and Mockito are both libraries that allow developers to mock objects in test cases. We see in 5 cases, all of which pertain to consumers of commons-collections API, deprecated features are replaced by functionality from the Guava API. The primary reason is that the commons-collections API had become obsolete, while Guava is more modern and provides more updated functionality.
- Detection heuristic::
There is no way to determine a list of package names for third-party replacement APIs as it is hard to understand which APIs can replace a certain API, thus making a complete list of replacement packages a non-trivial endeavor. Instead, we rely on data we have collected for all the aforementioned replacement based reaction patterns as for each pattern we create lists of packages to which a replacement method could belong to. When a replacement method does not belong to a class from any of those packages, we infer that it belongs to another third-party API.
- Quantitative analysis::
Total occurrences: 15,236 (9%) Unique consumers: 641 (7%)The second most frequent way (7%) in which API consumers (641 consumers out of 9,317) react to deprecation is by replacing a reference to a deprecated feature with a third-party API feature. This behavior might be prevalent for the consumers of some APIs as opposed to others as not all APIs have competitors.
- RP7:
Rollback version of the API
- Qualitative analysis:
Total occurrences: 19 (5%) Unique consumers: 8 (3%)Deprecations in an API are visible to API consumers when they upgrade the version of the API being used. At this point, a consumer can choose to stick with this version or rollback to the previous version. In one case (consumer of JUnit) in our sample set, we see this to be the case. The reasoning was that the new version had deprecated certain features being used. Needless to say, this defeats the purpose of deprecation.
- Detection heuristic::
When going through various versions of a file containing a reference to a deprecated feature ordered chronologically, if the file no longer contains deprecated features, we check whether the API consumer has rolled back the version of the API. We also ensure that the method invocation has not been removed from the source code. If both conditions are met, we mark it as a rollback.
- Quantitative analysis::
Total occurrences: 2,134 (1%) Unique consumers: 193 (2%)Rolling back the version of the API being used is also seen 1.2% of the time. This may indicate that several API consumers do not wish to take the effort to adapt to a new version of an API, but prefer to stick with an older version.
To challenge our aforementioned findings concerning frequency of reaction patterns, we ask in our survey (which targets API consumers from a different setting) which one of these reaction patterns they have most frequently adopted. Figure 4 reports the results.
69% of API consumers in our survey reported to always react by replacing the deprecated invocation with the recommended replacement from the API. This is in direct contradiction of the trends seen in GitHub data. While only 20% of consumers indicate that they do no react to a deprecated entity, in fact, 44% actually indicate that not reacting to deprecation is something that they would not consider as acceptable behavior. This again contradicts the behavior observed on GitHub. However, this could be explained by our survey respondents answer our questions to conform with what they perceive as acceptable behavior (known as social desirability bias Fisher 1993).
The other 5 reaction patterns all receive less than 17% of support from consumers. In all the cases, the majority of consumers indicate that they do not react in such a manner. We see that rolling back the version of the API and deleting a deprecated call with no replacement are by far the most negatively viewed reaction patterns with 80% and 75% of consumers indicating that they would never adopt such a pattern.
RQ3: Variance of Reaction Patterns Across APIs
By answering RQ2, we have analyzed the distribution of reaction patterns across all the consumer projects considered in our dataset, regardless of the API producer. Now we move our attention to investigating whether the distribution of reaction patterns varies across the consumers of different APIs. We differentiate between those APIs that affect several consumers vs. those that do not.
In Fig. 5 we see the percentage of consumers affected by deprecation. We define thresholds to create logical groupings of APIs based on what proportion of consumers are affected by deprecation. We define the thresholds for specific categorization by manually analyzing the graphs,Footnote 4 which is similar to the elbow method utilized when determining clusters (Bholowalia and Kumar 2014). We choose such a methodology over using quartiles as it allows us to take into account large changes in values and assign appropriate buckets to these values as opposed to lumping all values within a quartile in the same bucket.
-
Unaffecting consumers:
:
-
0% of consumers are affected by deprecations done by the API
-
Minimally affecting consumers:
:
-
< 2% of consumers are affected by deprecations
-
Marginally affecting consumers:
:
-
between 2% and 7% of consumers are affected by deprecations
-
Largely affecting consumers:
:
-
> 7% of consumers are affected by deprecated features
Figure 6 shows a breakdown of the percentage of API producers belonging to each of these categories. Predominantly APIs do not affect their consumers, with 20 (40%) APIs never affecting any consumer and 18 (36%) APIs affecting less than 2%. Six (12%) APIs affect between 2% and 7% consumers and a further six (12%) affect more than 7% of the consumers.
-
Unaffecting consumers:
:
-
For 20 APIs (40%), we observe that no consumer is affected by deprecation, because our sampled API consumers do not use any of the deprecated features. For the other 30 APIs, consumers are affected to various degrees.
-
Minimally affecting consumers:
:
-
Considering the distribution of reaction patterns across the 18 APIs that minimally affect their consumers (< 2%), consumers of 12 of these APIs predominantly do not react to deprecation. For other 3 APIs, replacing references to deprecated entities with references to a third-party API (RP6) is the dominant reaction pattern. In the case of ‘commons-lang3’ (seen in Fig. 7), some consumers react by replacing deprecated features with features from the same API (RP3). Despite this fact, replacing with a third-party API is still the most common reaction pattern amongst consumers of this API. For the ‘joda-time’ API we see four different kinds of reaction patterns: no reaction (RP1), deletion (RP2), rollback and replacing with third-party API (RP6), as seen in Fig. 7. The consumers of the last API from this set, i.e., ‘commons-pool’, always rollback the version of the API being used (RP7), as visible in Fig. 7. This seem to indicate that for the consumers of this API, deprecation acts as a deterrent to upgrading the version of the API being used.
-
Marginally affecting consumers:
:
-
Among the APIs that marginally affect their consumers, the predominantly popular way to react to deprecation is by not reacting at all: For all the APIs, in over 60% of the cases consumers do not react to deprecation (RP1). There is a little bit of variance in terms of reaction patterns in the cases where a reaction does actually take place. In the case of ‘guava’, ‘hamcrest-all’, and ‘junit’, in 15-20% of the cases consumers have reacted by replacing a deprecated feature with a third-party API (RP6). In the case of the other 3 APIs that fall in category (‘javassist’, ‘mockito’, and ‘commons-httpclient’), in over 25% of the cases features are replaced with third-party API ones (RP7).
-
Largely affecting consumers:
:
-
Among those APIs that affect consumers the most, ‘hibernate-core’ has affected 17% (1,391 out of 7,983) of its consumers and ‘mongo-java-driver’ affects 24% (496 out of 2,077) of its consumers; deprecations in ‘hibernate-core’ and ‘mongo-java-driver’ are more exposed to the consumers than the deprecations in most other APIs. In the final set we see that for ‘android’, ‘poi’, ‘commons-io’, and ‘easymock’, consumers predominantly (∼80% of the cases) do not react (RP1). For these APIs, the alternative reaction patterns is typically to react by replacing the deprecated features with a feature from a third-party API (RP7). Out of this set of APIs, only the consumers of ‘hibernate-core’ (in Fig. 7) show cases of replacing a deprecated feature with its recommended replacement (RP3). For this API the consumers appear to display the most varied reaction patterns. This may be explained by the large number of consumers (over 1,000) affected by deprecation. For ‘mongo-java-driver’ (the API that affects the largest percentage of consumers seen in Fig. 7), in over 40% of the cases the consumers prefer to start using a new API (RP6).
RQ4: Explaining the Non-Reactions
We see that not reacting to deprecation is by far the most popular reaction pattern. This is an unexpected finding and we delve deeper into our data and survey developers to gain a thorough understanding behind this phenomenon.
We do this in two ways: (1) we analyze the impact of the API’s evolution strategy in the consumers’ reaction pattern and (2) we ask API consumers what motivates them to not react to deprecation.
Consumers’ Reactions and API Deprecation Policies
In most cases, API consumers do not react to the deprecation of an API artifact; in some instances where a reaction does take place, the nature of these reactions can be diverse. We would like to investigate whether the API’s deprecation and evolution strategies are associated with the consumer’s behavior toward deprecation.
In Section 3.6 we list the four dimensions along which we measure the behavior concerning an API’s evolution; similar to Section 4.3, for each of the dimensions we define the thresholds for specific categorization by manually analyzing the graphs. The thresholds are detailed in Table 2.
Table 2 Dimensions of API evolution and thresholds We start by looking at the release activeness of the APIs. We notice that some APIs have not been active for more than 5 years and denote these as inactive. For the rest, we define thresholds based on the number of releases per months. A breakdown of this metric per API along with the chosen threshold points can be seen in Fig. 8.
We look at the percentage of deprecated features that an API removes in its lifetime. For some APIs, no deprecated features are removed. For the rest, we define thresholds based on the graph seen in Fig. 9.
We also take into account the percentage of the API that is deprecated over its lifetime. For all our APIs there is at least one feature that has been deprecated. We capture the frequency with which features are deprecated in different bins, the thresholds for which can be seen in Fig. 10.
Finally, we look at the number of breaking changes that an API introduces. The thresholds defined for this can be seen in Fig. 11. We scored each of the APIs based on the categories defined in Table 2 and conducted a card sort (as described in Section 3.6). This card sort resulted in nine API deprecation strategies (DSs), each with its own defining characteristic. In the following, we provide more details about each emerged DS, in terms of its description along with the aforementioned dimensions, which APIs fit in the pattern and an analysis of the behavior of the consumers of the APIs adapting this DS.
- DS1:
Inactive
- Description::
The API is not actively releasing new versions, thus deprecated features are not being removed.
- APIs::
log4j
, commons-dbcp
, hamcrest-all
, standard
, dom4j
, c3p0
, commons-httpclient
, android
, commons-pool
.
- Expected reaction::
APIs in this category are not at all active, i.e., they have not released a new version in the last 5 years, hence there is no danger in using a deprecated feature as there is no immediate danger of it being removed in the new release of the API. Hence, here we expect no reactions to take place.
- Analysis of consumers::
This is the most common strategy with 9 out of 50 APIs belonging to this category. Two of the APIs in this set never affect their consumers, while for 5 APIs over 80% of the consumers never react, as expected. For the last two APIs, some reactions do take place. Out of these APIs, ‘commons-pool’ is the only outlier where 100% consumers affected by deprecation react and do so by rolling back the version of the dependency being used.
- DS2:
Very little deprecation
- Description::
The API has no history of removing features, deprecated or otherwise.
- APIs::
slf4j-api
, aspect-jrt
, json
, javassist
, jsoup
, jersey-client
.
- Expected reaction::
Here APIs deprecate features, however, they never remove deprecated features from their APIs. Thus they always remain backward compatible. In this case, we expect no reactions.
- Analysis of consumers::
Six APIs appear to be backward compatible in all cases, this implies that deprecated features are never removed. For 5 of these APIs, no clients are affected (this is expected, since a defining trait of this strategy is that rare deprecations take place). However, for ‘Javassist’, in over 35% of the cases that a reaction does take place by replacing a deprecated call with one to a third-party API (RP6). Which implies that consumers of this API are not aware that there is no danger in not reacting as no deprecated features are ever removed.
- DS3:
Little deprecation
- Description::
The API does not deprecate a lot, but when it does, it does not remove the deprecated features.
- APIs::
joda-time
, postgresql (A +, R −, D −, B), cglib (A, R −, D −, B), commons-beanutils
, freemarker (A, R −, D, B).
- Expected reaction::
These APIs remove very few deprecated features, thus most deprecated features remain in the API and there is very little danger that they will be removed later. Here we expect no reactions.
- Analysis of consumers::
Five APIs that fall under this category. These APIs are mostly backward compatible, thus consumers do not need to react much as there is very little inherent danger in a deprecated feature being removed. Consumers of two APIs do appear to exhibit this behavior (RP1). However, for ‘joda-time’, we see rollbacks (RP7, 40% of the cases) and for ‘postgresql’ we see migrations to another API (RP6, 60% of the cases).
- DS4:
Never cleans up API
- Description::
The API deprecates a lot but never really removes any deprecated feature.
- APIs::
commons-io
, commons-lang3
, httpclient (A +, R −, D + +, B), commons-logging (A, R −, D + +, B), commons-fileupload
, commons-cli
.
- Expected reaction::
The APIs threaten a lot of breaking changes by deprecating a lot of features, but none of these deprecated features are removed. Thus, no reaction has to take place due to the lack of danger of using a deprecated feature. No reactions are expected.
- Analysis of consumers::
Six APIs fall in this category. For three of these APIs, no consumer is affected by deprecation. On the other hand for the consumers of the other 3 APIs, we do see quite some reactions. For commons-cli (> 50% of the cases), commons-lang3 (> 50% of the cases) and commons-io (20% of the cases) we see that deprecated calls are replaced by another third-party API (RP6).
- DS5:
Rarely cleans up API
- Description::
The API deprecates several features, yet only removes a few of these features.
- APIs::
junit (A, R, D +, B), commons-codec (A, R, D +, B), commons-collections (A, R, D + +, B +).
- Expected reaction::
These APIs deprecate a lot of features, however, also remove a few of these deprecated features. Thus there is moderate danger in using a deprecated feature from this API. We expect a few reactions, but not too many.
- Analysis of consumers::
Three APIs belong to this category. Just like the previous category we expect to see reactions as a lot of deprecations take place but few removals. Consumers of two APIs out of this set do not react to deprecation in over 80% of the cases. However, consumers of commons-collections do follow the more expected pattern of reacting, by replacing deprecated invocations with those being made to other third-party APIs (RP6, > 60% of cases).
- DS6:
Directly breaks few methods
- Description::
The API removes the features sometimes, but not frequently.
- APIs::
mockito-all (A +, R, D −, B), gson (A, R, D −, B), h2 (A +, R, D −, B), poi (A +, R, D −, B), primefaces (A, R, D −, B +).
- Expected reaction::
Not a lot of features are deprecated, instead, some breaking changes are introduced directly. There is quite some danger to using a (deprecated or otherwise) feature from an API in this set as the API can remove a feature at any time. We expect to see reactions.
- Analysis of consumers::
Five APIs exhibit this strategy. We see that in the case of 3 APIs over 98% of the consumers do not react, and one does not affect consumers at all. Only for mockito-all do consumers react by replacing deprecated calls with new ones to a third-party API (RP6, 25% of the cases).
- DS7:
Directly breaks a lot of methods
- Description::
The API removes deprecated and non-deprecated features frequently.
- APIs::
mysql-connector-java (A +, R +, D −, B +), guava (A +, R +, D −, B), aspectjweaver (A +, R +, D −, B), hsqldb (A, R +, D −, B +), guice (A, R + +, D −, B), assertj-core (A +, R +, D −, B).
- Expected reaction::
Here APIs introduce breaking changes with regularity instead of first deprecating a feature. We expect to see many consumers being affected by deprecation.
- Analysis of consumers::
Surprisingly, this strategy is exhibited by 6 APIs. This implies that 6 APIs choose to break their client code as opposed to evolving in a clean manner and first deprecating a feature and only after that removing the feature. Thus, these APIs are not too bothered by the thought of breaking their consumers’ code. This is apparent, given that consumers of 5 out of 6 APIs are unaffected by deprecation at all. Only for guava do we see that consumers are affected and they react. These reactions are either by migrating to another API or rolling back the version of the API being used.
- DS8:
Removes deprecated features
- Description::
The deprecated features are sometimes removed in a future version.
- APIs::
jackson-databind (A +, R, D, B), testng (A +, R, D, B), selenium-java
.
- Expected reaction::
These APIs are quite active and they deprecate and remove deprecated features regularly. Given the danger of using these features, we expect reactions.
- Analysis of consumers::
3 APIs exhibit this strategy. For testng, in over 60% of the cases, there is no reaction seen. Whereas for selenium-java no API consumers are affected by deprecation. However, only for jackson-databind do we see that consumers react in just under 40% of the cases by replacing with another API (RP6).
- DS9:
Actively cleans up deprecated features
- Description::
The API removes most deprecated features in future versions.
- APIs::
spring-core (A +, R +, D, B), hibernate-core (A +, R +, D, B), logback-classic (A +, R +, D, B), mybatis (A +, R +, D, B), mongo-java-driver (A +, R +, D + +, B), easymock (A, R + +, D +, B), jetty-server (A +, R +, D, B).
- Expected reaction::
Here APIs remove deprecated features with regularity, thus ensuring that consumers will be confronted with breaking changes when upgrading the version of an API. We expect to see reactions.
- Analysis of consumers::
This strategy is exhibited by 7 APIs. We see in the case of spring-core, hibernate-core, mybatis, and easymock that no reactions actually take place in over 80% of the cases. Only in the case of mongo-java-driver do we see that in 35% of the cases do reactions take place, where consumers replace deprecated invocations with those to another API (RP6). This counter-intuitive behavior of the API consumers can be explained by the fact that majority of the consumers do not upgrade the version of the API being used, thus minimizing the chance that they will be affected by a breaking change in the API.
API Consumer Perspective on Non-reaction
We asked API consumers to indicate whether one or more reasons for not reacting to deprecation has applied to them in the past. Results from this survey can be seen in Fig. 12.
The most common reason (53.4% of respondents) for not reacting is that the specified replacement by the API is either too complicated to use or is not a good enough replacement. This shows that API producers might not be making their replacement features developer friendly. Furthermore, it also calls for API producers to invest in making detailed upgrade guides or improving documentation. 49% of respondents also indicated that they found reacting to deprecation time-consuming and not worthwhile. This might be explained by the fact that our survey respondents work in industry thus not having sufficient time to react to deprecation.
42% of respondents indicate that they do not react to a deprecated feature as they would rather use another API that provides similar functionality. This is in line with the earlier results where consumers found it hard to react to deprecation due to the convoluted and time-consuming nature of the replacement. Consumers also indicate that they are lax when it comes to reacting to deprecation as they do not feel particularly threatened by the deprecation as the immediate danger of a new release of the API that removes the deprecated feature being used is non-existent. This is reflected in the results seen in Section 4.4.
Approximately the same percentage of consumers indicate that the fact that deprecation is a non-breaking change has an impact on their decision to react (38%) as those that indicate that this fact has no impact on their decision to react (37%). Thus, consumers have diverging opinions over the effectiveness of the deprecation mechanism. However, the fact that the deprecated feature might never be removed thereby never becoming a breaking change, does not act as motivation for non-reaction either.
The reason behind deprecation or lack thereof does not have a major impact on the non-reaction pattern observed according to 47% of consumers. This indicates that consumers feel that the reason behind deprecation is a driving factor to react to deprecation, which is in line with previous results (Sawant et al. 2018b).
Reasons to not react such as the ability to rollback the version being used or developing an in-house alternative to the deprecated API receive very little support from API consumers. Most indicate that such reasons do not motivate non-reactions.
Consumers also mentioned other reasons that have motivated them to not react to deprecation. One consumer mentioned that the fact that the feature had been deprecated for a long time and never been removed, made it apparent that no reaction was needed. In some cases in industry, the management does not want to invest time or money in upgrading a dependency and reacting to deprecated/breaking changes in the API. Another consumer indicated that upgrading the API binary sometimes leads to incompatibilities with other binaries thus preventing reactions to deprecation.
We wanted to further understand the reasons behind reacting to deprecation, to see what motivated consumers to react. Some of these reasons can be seen in Fig. 13.
We see that the reason behind deprecation, the low cost of reaction, the seriousness of the deprecation and the need to upgrade the library are all considered to be very important (over 60% of consumers in each case) motivations behind reacting to deprecation. This is in line with the responses that we obtained for non-reactions.