APIDiff: Detecting API Breaking Changes (SANER 2018, Tools Track)

APIDiff: Detecting API Breaking Changes (SANER 2018, Tools Track)

Libraries are commonly used to increase productivity. As most software systems, they evolve over time and changes are required. However, this process may involve breaking compatibility with previous versions, leading clients to fail. In this context, it is important that libraries creators and clients frequently assess API stability in order to better support their maintenance practices. In this paper, we introduce APIDIFF, a tool to identify API breaking and non-breaking changes between two versions of a Java library. The tool detects changes on three API elements: types, methods, and fields. We also report usage scenarios of APIDIFF with four real-world Java libraries.

13beaa3b7239eca3319d54c6a9f3a85a?s=128

ASERG, DCC, UFMG

March 21, 2018
Tweet

Transcript

  1. APIDiff: Detecting API Breaking Changes Aline Brito, Laerte Xavier, Andre

    Hora, Marco Tulio Valente SANER 2018, Tool Track
  2. Motivation Libraries have a key importance in modern software development

    2
  3. Motivation Libraries have a key importance in modern software development

    3
  4. Library services are provided via APIs 4

  5. In theory, APIs should be stable 5

  6. But, 28% out of 500K API changes break backward compatibility

    Historical and Impact Analysis of API Breaking Changes: A Large-Scale Study SANER, 2017 6
  7. Which changes break my code? How stable is this library?

    7
  8. 8 On the owner side… Write migration documents Identify and

    revert accidental breaking changes
  9. 9 On the client side… Analyze the amount of breaking

    changes over time Select more stable libraries to depend on
  10. APIDiff Detecting API Breaking Changes

  11. 11 APIDiff The tool analyses libraries available on git

  12. Catalog of Breaking and Non-breaking Changes detected by APIDiff

  13. Breaking Changes (BC) Changes performed in API elements that may

    break client applications 13 We exclude changes performed on deprecated API elements
  14. 14 Element Breaking Changes (BC) Type REMOVE TYPE, LOST VISIBILITY,

    CHANGE IN SUPERTYPE, ADD FINAL MODIFIER, REMOVE STATIC MODIFIER, RENAME TYPE, MOVE TYPE Method REMOVE METHOD, LOST VISIBILITY, CHANGE IN RETURN TYPE, CHANGE IN PARAMETER LIST, CHANGE IN EXCEPTION LIST, ADD FINAL MODIFIER, REMOVE STATIC MODIFIER, MOVE METHOD, RENAME METHOD, PUSH DOWN METHOD, INLINE METHOD Field REMOVE FIELD, LOST VISIBILITY, CHANGE IN FIELD TYPE, CHANGE IN FIELD DEFAULT VALUE, ADD FINAL MODIFIER, MOVE FIELD, PUSH DOWN FIELD
  15. Example: Change in Access Modifiers 15 public int M1(String){ ...

    } private int M1(String){ ... }
  16. Example: Change in Parameter List 16 public int M1(Context){ ...

    } public int M1(){ ... }
  17. Example: Element Removal 17 public class C1{ ... } public

    class C1{ ... }
  18. Example: Refactoring Operations 18 public int M1(String, Integer){ ... }

    public int M2(String, Integer){ ... }
  19. Non-breaking Changes (NBC) Changes that do not break clients 19

  20. 20 Element Non-Breaking Changes (NBC) Type ADD TYPE, GAIN VISIBILITY,

    REMOVE FINAL MODIFIER, ADD STATIC MODIFIER, ADD SUPERTYPE, EXTRACT SUPERTYPE, DEPRECATED TYPE Method ADD METHOD, PULL UP METHOD, GAIN VISIBILITY, REMOVE FINAL MODIFIER, ADD STATIC MODIFIER, DEPRECATED METHOD, EXTRACT METHOD Field ADD FIELD, PULL UP FIELD, GAIN VISIBILITY, REMOVE FINAL MODIFIER, DEPRECATED FIELD
  21. Example: Change in Access Modifiers 21 private int M1(String){ ...

    } public int M1(String){ ... }
  22. Example: Add Element 22 public class C1{ public void M1(){

    … } } public class C1{ }
  23. Examples 23

  24. 24 An image loading and caching library 20K stars A

    framework to implement unit tests 6K stars
  25. Example 1: Detecting Changes in Version Histories 25

  26. 26 Detecting Changes in Version Histories Useful to analyze several

    commits at once Useful to assess libraries stability
  27. Detecting Changes in Version Histories 27 APIDiff diff = new

    APIDiff( “bumptech/glide”, “https://github.com/bumptech/glide.git”); Result result = diff.detectChangeAllHistory(“master”, Classifier.API);
  28. Detecting Changes in Version Histories 28 APIDiff diff = new

    APIDiff( “bumptech/glide”, “https://github.com/bumptech/glide.git”); Result result = diff.detectChangeAllHistory(“master”, Classifier.API);
  29. Example 2: Fetching New Commits 29

  30. 30 Fetching New Commits Useful to monitor changes in a

    repository Contributors are notified shortly after BCs are introduced
  31. Fetching New Commits 31 APIDiff diff = new APIDiff( “bumptech/glide”,

    “https://github.com/bumptech/glide.git”); Result result = diff.fetchAndDetectChange(Classifier.API);
  32. Fetching New Commits 32 APIDiff diff = new APIDiff( “bumptech/glide”,

    “https://github.com/bumptech/glide.git”); Result result = diff.fetchAndDetectChange(Classifier.API);
  33. Example 3: Detecting Changes in Specific Commits 33

  34. 34 Detecting Changes in Specific Commits Useful to analyze pull

    requests Useful to detect accidental BCs
  35. Detecting Changes in Specific Commits 35 APIDiff diff = new

    APIDiff( “mockito/mockito”, “https://github.com/mockito/mockito.git”); Result result = diff.detectChangeAtCommit( "4ad5fdc14ca4b979155d10dcea0182c82380aefa", Classifier.API);
  36. Detecting Changes in Specific Commits 36 APIDiff diff = new

    APIDiff( “mockito/mockito”, “https://github.com/mockito/mockito.git”); Result result = diff.detectChangeAtCommit( "4ad5fdc14ca4b979155d10dcea0182c82380aefa", Classifier.API);
  37. Detecting Changes in Specific Commits 37 APIDiff diff = new

    APIDiff( “mockito/mockito”, “https://github.com/mockito/mockito.git”); Result result = diff.detectChangeAtCommit( "4ad5fdc14ca4b979155d10dcea0182c82380aefa", Classifier.API); Category: Add Method Description: Method answersWithDelay(long, Answer<T >) added in class org.mockito.AdditionalAnswers
  38. Result Type 38 - category : String - description :

    String - path : String - element : String - javadoc : Boolean - deprecated : Boolean - breakingChange : Boolean - revCommit: RevCommit Change
  39. Example 4: Filtering Packages 39

  40. 40 Filtering Packages It is also possible to filter in/out

    packages Useful to detect changes in internal implementations
  41. Filtering Packages 41 Result result = diff.detectChangeAtCommit( "4ad5fdc14ca4b979155d10dcea0182c82380aefa", Classifier.API);

  42. Architecture

  43. 43

  44. 44 Processing Module • Git operations • Instances library

  45. 45 Refactoring Module detects refactoring actions (reused from RefDiff) RefDiff:

    Detecting Refactorings in Version Histories Danilo Silva, Marco Tulio Valente - MSR, 2017
  46. 46 Analysis Module detects the changes in the library history

  47. Future Work 47

  48. Future Work 48 • Evaluate the precision of APIDiff •

    Support to other programming languages • Feature to analyze changes at release level
  49. https://github.com/aserg-ufmg/apidiff 49

  50. Thank you! Aline Brito, Laerte Xavier, Andre Hora, Marco Tulio

    Valente SANER 2018, Tool Track