User Tools

Site Tools


evolving_java-based_apis

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
evolving_java-based_apis [2014/02/06 07:31]
yann
evolving_java-based_apis [2014/02/06 08:01]
yann
Line 22: Line 22:
   * a Component can offer an API and its implementation,​ it is the implementor;​ the Client access the API, it is the caller;   * a Component can offer an API and its implementation,​ it is the implementor;​ the Client access the API, it is the caller;
   * a Component can offer a "​callback"​ API, it is the caller; the Client must implement the API, it is the implementaor.   * a Component can offer a "​callback"​ API, it is the caller; the Client must implement the API, it is the implementaor.
-and the question is "For roles played by Clients, would the [...] API change render invalid a hypothetical Client making legal usage of the existing API?" The document then provides a table (augmented here with the addition of API methods to assess the contract compatibility of a change:+and the question is "For roles played by Clients, would the [...] API change render invalid a hypothetical Client making legal usage of the existing API?" The document then provides ​[[http://​wiki.eclipse.org/​Evolving_Java-based_APIs|a table]] (augmented here with the addition of API methods to assess the contract compatibility of a change:
  
 ^   Types of Changes ​   ^^   ​Roles ​  ^^ ^   Types of Changes ​   ^^   ​Roles ​  ^^
Line 31: Line 31:
 | Field invariants ​     | Strengthen | Contract compatible for getters ​ | Breaks compatibility for setters ​     | | Field invariants ​     | Strengthen | Contract compatible for getters ​ | Breaks compatibility for setters ​     |
 | :::                   | Weaken ​    | Breaks compatibility for getters | Contract compatible for setters ​      | | :::                   | Weaken ​    | Breaks compatibility for getters | Contract compatible for setters ​      |
-| Adding an API method ​                                                                                      ​|||| +| Adding an API method:                                                                                      ​|||| 
-&#​9632; ​To an interface ​          ​|| Contract compatible for callers ​ | Breaks compatibility for implementors | +To an interface ​                                         || Contract compatible for callers ​ | Breaks compatibility for implementors | 
-&#​9632; ​To a class((Intended to be sub-classed by implementors)) ​    ​|| Contract compatible for callers ​ | Breaks compatibility for implementors | +To a class((Intended to be sub-classed by implementors)) || Contract compatible for callers ​ | Breaks compatibility for implementors | 
-&#​9632; ​To a class((Not to be sub-classed by implementors)) ​         || Contract compatible for callers ​ | Contract compatible for callers |+To a class((Not to be sub-classed by implementors)) ​     || Contract compatible for callers ​ | Contract compatible for callers |
  
 +Then, the document goes on enumerating,​ for each possible types of changes to API-related constituents of a Component, which ones are binary compatible and which ones are not, see the [[http://​wiki.eclipse.org/​Evolving_Java-based_APIs_2|original document]] for exhaustive lists. The API-related constituents include:
 +  * API packages;
 +  * API interfaces (methods, fields, and type members);
 +  * API classes (methods and constructors,​ fields, type members).
 +
 +The document also discusses annotations on API constituents,​ turning non-generic types into generic ones, and Java reflection. Regarding reflection, it emphasises that "[n]o additional provision are made for clients that access the API using Java reflection"​. It also explains that most reflection APIs are safe, except Class.getDeclaredXXX(...) methods, because they are "​dependent on the exact location of [a constituent] and include non-public [constituents] as well as public ones".
 +
 +Finally, the document includes several suggestions to design better API or make it easier to change them:
 +  * Clients must only use published (not internal), API (even if other constituents are public);
 +  * "​[O]bsolete API elements are notoriously difficult to get rid of";
 +  * "[A]ll gender changes involving classes, enums, interfaces, and annotation types break binary compatibility [...]";​
 +  * "[A] pre-existing Client subclass of an existing implementation might still provide a pre-existing implementation [of a newly added method, by sheer luck]";​
 +  * "API interfaces that Clients should implement should not include fields",​ which is not always possible because enumeration constants used in switch statements;
 +  * "​[A]dding type parameters to a previously unparameterised type retains compatibility";​
 +  * "API classes should always explicitly declare at least one constructor";​
 +  * "​Client code can use the values() method to determine the ordinal positions of enums constants";​
 +  * "​Adding and deleting checked exceptions declared as thrown by an API method does not break binary compatibility;​ however, it breaks contract compatibility (and source code compatibility)";​
 +  * "Java compiler always inline the value[s] of constant fields [...] this does not meet the objective of changing the API field'​s value";​
 +  * "As long as the erasure looks like the corresponding declaration prior to generification,​ the change is binary compatible with existing code";
 +  * "​[G]enerifying an existing API is something that should be considered from the perspective of the API as a whole rather than piecemeal on a method-by-method or class-by-class basis";​
 +  * "[T]ag all stored data with its format version number";​
 +  * "​Deprecate and forward"​ and-or "Start over in a new package"​ and-or [[http://​www.mif.vu.lt/​~plukas/​resources/​Extension%20Objects/​ExtensionObjectsPattern%20Gamma96.pdf|"​COM style"​]] and-or "​Mak[e] obsolete hook method final"​.
 +
 +Also, the document provides the simplest, clearest explanation of Java 1.5+ type erasure mechanism, that I reproduce here for the sake of beauty:
 +
 +>> A raw type is a use of a generic type without the normal type arguments. For example, "​List"​ in the declaration statement "List x = null;" is a raw type since List is a generic type declared "​public interface List<​E>​ ..." in JDK 1.5. Contrast this to a normal use of List which looks like "​List<​String>​ x = null;" or "​List<?>​ x = null;" where a type augument ("​String"​) or wildcard is specified. ​
 +>> ​
 +>> The term erasure is suggestive. Imagine going through your code and literally erasing the type parameters from the generic type declaration (e.g., erasing the "<​E>"​ in "​public interface List<​E>​ ...") to get a non-generic type declaration,​ and replacing all occurrence of the deleted type variable with Object. For type parameters with type bounds (e.g., "<E extends T1 & T2 & T3 & ...>"​),​ the leftmost type bound ("​T1"​),​ rather than Object, is substituted for the type variable. The resulting declaration is known as the erasure."​
evolving_java-based_apis.txt · Last modified: 2019/10/06 20:37 (external edit)