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:19]
yann
evolving_java-based_apis [2017/09/06 01:54] (current)
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   ​^^ 
-| Method preconditions | Strengthen | Breaks compatibility for callers | Contract compatible for implementors | +| Method preconditions ​ | Strengthen | Breaks compatibility for callers | Contract compatible for implementors ​ 
-                     | Weaken ​    | Contract compatible for callers ​ | Breaks compatibility for implementors |+:::                   | Weaken ​    | Contract compatible for callers ​ | Breaks compatibility for implementors ​
 +| Method postconditions | Strengthen | Contract compatible for callers ​ | Breaks compatibility for implementors | 
 +| :::                   | Weaken ​    | Breaks compatibility for callers | Contract compatible for implementors ​ | 
 +| Field invariants ​     | Strengthen | Contract compatible for getters ​ | Breaks compatibility for setters ​     | 
 +| :::                   | Weaken ​    | Breaks compatibility for getters | Contract compatible for setters ​      | 
 +| Adding an API method: ​                                                                                     |||| 
 +| - To an interface ​                                         || 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 | 
 +| - To a class((Not to be sub-classed by implementors)) ​     || Contract compatible for callers ​ | Contract compatible for callers ​|
  
-Method postconditions Strengthen Contract ​compatible for callers Breaks compatibility ​for implementors +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: 
-Weaken Breaks ​compatibility ​for callers Contract compatible for implementors +  * API packages; 
-Field invariants Strengthen Contract compatible for getters Breaks ​compatibility ​for setters +  * API interfaces (methods, fields, and type members); 
-Weaken Breaks ​compatibility ​for getters Contract ​compatible for setters+  * 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.1391671177.txt.gz · Last modified: 2017/09/06 01:54 (external edit)