Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Defaultification Refactoring: A Tool for Automatically Converting Java Methods to Default

267 views

Published on

Enabling interfaces to declare (instance) method implementations, Java 8 default methods can be used as a substitute for the ubiquitous skeletal implementation software design pattern. Performing this transformation on legacy software manually, though, may be non-trivial. The refactoring requires analyzing complex type hierarchies, resolving multiple implementation inheritance issues, reconciling differences between class and interface methods, and analyzing tie-breakers (dispatch precedence) with overriding class methods. All of this is necessary to preserve type-correctness and confirm semantics preservation. We demonstrate an automated refactoring tool called Migrate Skeletal Implementation to Interface for transforming legacy Java code to use the new default construct. The tool, implemented as an Eclipse plug-in, is driven by an efficient, fully-automated, type constraint-based refactoring approach. It features an extensive ruleset covering various corner-cases where default methods cannot be used. The resulting code is semantically equivalent to the original, more succinct, easier to comprehend, less complex, and exhibits increased modularity. A demonstration can be found at http://youtu.be/YZHIy0yePh8.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Defaultification Refactoring: A Tool for Automatically Converting Java Methods to Default

  1. 1. Defaultification Refactoring: A Tool for Automatically Converting Java Methods to Default Raffi Khatchadourian1,2 Hidehiko Masuhara3 International Conference on Automated Software Engineering, 2017 1 Computer Science, Hunter College, City University of New York, USA 2 Computer Science, The Graduate Center, City University of New York, USA 3 Mathematical and Computing Science, Tokyo Institute of Technology, Japan
  2. 2. Motivation
  3. 3. Interfaces Are Traditionally Lists of Method Declarations • Traditionally, an interface is a Java type that lists method declarations. interface Collection<E> { int size(); void add(E elem); boolean isEmpty(); int capacity(); abstract boolean atCapacity();} 1
  4. 4. Interfaces Are Traditionally Lists of Method Declarations • Traditionally, an interface is a Java type that lists method declarations. • Clients are guaranteed that concrete interface implementers provide implementations for all listed methods. interface Collection<E> { int size(); void add(E elem); boolean isEmpty(); int capacity(); abstract boolean atCapacity();} 1
  5. 5. Some Interface Methods Are Optional • Interface methods can be listed as optional operations. interface Collection<E> { // ... void add(E elem); /* optional */ }} 2
  6. 6. Some Interface Methods Are Optional • Interface methods can be listed as optional operations. • Implementers may choose to support them or not. interface Collection<E> { // ... void add(E elem); /* optional */ }} class ImmutableList<E> implements Collection<E> { // ... } 2
  7. 7. Some Interface Methods Are Optional • Interface methods can be listed as optional operations. • Implementers may choose to support them or not. • If operations are unsupported, they conventionally throw an UnsupportedOperationException. interface Collection<E> { // ... void add(E elem); /* optional */ }} class ImmutableList<E> implements Collection<E> { // ... @Override public void add(E elem) { throw new UnsupportedOperationException();}} 2
  8. 8. Skeletal Implementation Classes Help Implement Interfaces • The skeletal implementation design pattern [Bloch, 2008] is used to make implementing interfaces easier. 3
  9. 9. Skeletal Implementation Classes Help Implement Interfaces • The skeletal implementation design pattern [Bloch, 2008] is used to make implementing interfaces easier. • Abstract skeletal implementation class provides partial implementations. abstract class AbstractImmutableList<E> implements Collection<E> { @Override public void add(E elem) { throw new UnsupportedOperationException();}} 3
  10. 10. Skeletal Implementation Classes Help Implement Interfaces • The skeletal implementation design pattern [Bloch, 2008] is used to make implementing interfaces easier. • Abstract skeletal implementation class provides partial implementations. • Implementers extend the skeletal implementation class rather than directly implementing the interface. abstract class AbstractImmutableList<E> implements Collection<E> { @Override public void add(E elem) { throw new UnsupportedOperationException();}} class ImmutableList<E> extends AbstractImmutableList<E>{ // ... @Override public void add(E elem) { throw new UnsupportedOperationException();}}} 3
  11. 11. The Skeletal Implementation Pattern Has Several Drawbacks The skeletal implementation pattern has several drawbacks. 4
  12. 12. The Skeletal Implementation Pattern Has Several Drawbacks The skeletal implementation pattern has several drawbacks. Example ImmutableList cannot: 4
  13. 13. The Skeletal Implementation Pattern Has Several Drawbacks The skeletal implementation pattern has several drawbacks. Example ImmutableList cannot: • Subclass another class. 4
  14. 14. The Skeletal Implementation Pattern Has Several Drawbacks The skeletal implementation pattern has several drawbacks. Example ImmutableList cannot: • Subclass another class. • Inherit skeletal implementations split over multiple classes [Horstmann, 2014]. 4
  15. 15. The Skeletal Implementation Pattern Has Several Drawbacks The skeletal implementation pattern has several drawbacks. Example ImmutableList cannot: • Subclass another class. • Inherit skeletal implementations split over multiple classes [Horstmann, 2014]. • Inherit skeletal implementations for multiple interfaces. 4
  16. 16. Java 8 Default Methods Can Replace Skeletal Implementations • Java 8 enhanced interfaces allow both method declarations and definitions. interface Collection<E> { default void add(E elem) { // optional. throw new UnsupportedOperationException();}} 5
  17. 17. Java 8 Default Methods Can Replace Skeletal Implementations • Java 8 enhanced interfaces allow both method declarations and definitions. • Implementers inherit the (default) implementation if none provided. interface Collection<E> { default void add(E elem) { // optional. throw new UnsupportedOperationException();}} class ImmutableList<E> implements Collection<E> {} 5
  18. 18. Java 8 Default Methods Can Replace Skeletal Implementations • Java 8 enhanced interfaces allow both method declarations and definitions. • Implementers inherit the (default) implementation if none provided. • Original motivation to facilitate interface evolution. interface Collection<E> { default void add(E elem) { // optional. throw new UnsupportedOperationException();}} class ImmutableList<E> implements Collection<E> {} 5
  19. 19. Java 8 Default Methods Can Replace Skeletal Implementations • Java 8 enhanced interfaces allow both method declarations and definitions. • Implementers inherit the (default) implementation if none provided. • Original motivation to facilitate interface evolution. • Can also be used as a replacement of the skeletal implementation pattern [Goetz, 2011]. interface Collection<E> { default void add(E elem) { // optional. throw new UnsupportedOperationException();}} class ImmutableList<E> implements Collection<E> {} abstract class AbstractImmutableList<E> implements Collection<E> { @Override public void add(E elem) { throw new UnsupportedOperationException();}} 5
  20. 20. Implementation
  21. 21. • Implemented as an open source plug-in for the Eclipse IDE (available at http://cuny.is/interefact). 6
  22. 22. • Implemented as an open source plug-in for the Eclipse IDE (available at http://cuny.is/interefact). • Built on existing refactoring support in Eclipse. 6
  23. 23. • Implemented as an open source plug-in for the Eclipse IDE (available at http://cuny.is/interefact). • Built on existing refactoring support in Eclipse. • Conceptual approach based on type-constraints [Palsberg and Schwartzbach, 1994; Tip et al., 2011]. 6
  24. 24. • Implemented as an open source plug-in for the Eclipse IDE (available at http://cuny.is/interefact). • Built on existing refactoring support in Eclipse. • Conceptual approach based on type-constraints [Palsberg and Schwartzbach, 1994; Tip et al., 2011]. • See ICSE 2017 paper [Khatchadourian and Masuhara, 2017] for approach details. 6
  25. 25. • Implemented as an open source plug-in for the Eclipse IDE (available at http://cuny.is/interefact). • Built on existing refactoring support in Eclipse. • Conceptual approach based on type-constraints [Palsberg and Schwartzbach, 1994; Tip et al., 2011]. • See ICSE 2017 paper [Khatchadourian and Masuhara, 2017] for approach details. • Implementation is in procedural-style, similar to Pull Up Method refactoring. 6
  26. 26. High-level System Workflow 7
  27. 27. High-level System Workflow 2. Options control refactoring “invasiveness.” 7
  28. 28. High-level System Workflow 2. Options control refactoring “invasiveness.” • Remove or deprecate empty classes. 7
  29. 29. High-level System Workflow 2. Options control refactoring “invasiveness.” • Remove or deprecate empty classes. • Consider non-standard annotation differences. 7
  30. 30. High-level System Workflow 2. Options control refactoring “invasiveness.” • Remove or deprecate empty classes. • Consider non-standard annotation differences. 3. Simple initial checks, e.g., file writability. 7
  31. 31. High-level System Workflow 2. Options control refactoring “invasiveness.” • Remove or deprecate empty classes. • Consider non-standard annotation differences. 3. Simple initial checks, e.g., file writability. 4. Bulk of processing in final check. 7
  32. 32. Architecture and Plug-In Dependencies • Four plugins: two internal and two with UIs. 8
  33. 33. Architecture and Plug-In Dependencies • Four plugins: two internal and two with UIs. • Internal plug-ins include core and test plug-ins. 8
  34. 34. Architecture and Plug-In Dependencies • Four plugins: two internal and two with UIs. • Internal plug-ins include core and test plug-ins. • 259 automated refactoring tests. 8
  35. 35. Architecture and Plug-In Dependencies • Four plugins: two internal and two with UIs. • Internal plug-ins include core and test plug-ins. • 259 automated refactoring tests. • UI plug-ins include both end-user tool and evaluator. 8
  36. 36. Architecture and Plug-In Dependencies • Four plugins: two internal and two with UIs. • Internal plug-ins include core and test plug-ins. • 259 automated refactoring tests. • UI plug-ins include both end-user tool and evaluator. • Depends on Eclipse refactoring support. 8
  37. 37. Evaluation
  38. 38. Useful? • Successfully converted ∼20% of methods possibly participating in the pattern to default methods in corresponding interfaces (see [Khatchadourian and Masuhara, 2017] for details). 9
  39. 39. Useful? • Successfully converted ∼20% of methods possibly participating in the pattern to default methods in corresponding interfaces (see [Khatchadourian and Masuhara, 2017] for details). • Many failures related to: 9
  40. 40. Useful? • Successfully converted ∼20% of methods possibly participating in the pattern to default methods in corresponding interfaces (see [Khatchadourian and Masuhara, 2017] for details). • Many failures related to: • Inaccessibility of members between skeletal implementers and interfaces. 9
  41. 41. Useful? • Successfully converted ∼20% of methods possibly participating in the pattern to default methods in corresponding interfaces (see [Khatchadourian and Masuhara, 2017] for details). • Many failures related to: • Inaccessibility of members between skeletal implementers and interfaces. • Access to instance fields. 9
  42. 42. Correct? • Ensured that no compilation errors existed before and after refactoring. 10
  43. 43. Correct? • Ensured that no compilation errors existed before and after refactoring. • Verified unit tests results identical before and after the refactoring. 10
  44. 44. Correct? • Ensured that no compilation errors existed before and after refactoring. • Verified unit tests results identical before and after the refactoring. • Preliminary pull request study ensures that the automated results matched what experienced developers may have written. 10
  45. 45. Correct? • Ensured that no compilation errors existed before and after refactoring. • Verified unit tests results identical before and after the refactoring. • Preliminary pull request study ensures that the automated results matched what experienced developers may have written. • Four projects accepted our pull requests so far. 10
  46. 46. Summary
  47. 47. Summary & Future Work • A refactoring tool that migrates the skeletal implementation pattern to instead use Java 8 default methods based on type-constraints. 11
  48. 48. Summary & Future Work • A refactoring tool that migrates the skeletal implementation pattern to instead use Java 8 default methods based on type-constraints. • Implemented as an Eclipse IDE plug-in (available at http://cuny.is/interefact). 11
  49. 49. Summary & Future Work • A refactoring tool that migrates the skeletal implementation pattern to instead use Java 8 default methods based on type-constraints. • Implemented as an Eclipse IDE plug-in (available at http://cuny.is/interefact). • Evaluated using several techniques. 11
  50. 50. Summary & Future Work • A refactoring tool that migrates the skeletal implementation pattern to instead use Java 8 default methods based on type-constraints. • Implemented as an Eclipse IDE plug-in (available at http://cuny.is/interefact). • Evaluated using several techniques. • In the future, composite refactorings (field encapsulation, etc.). 11
  51. 51. For Further Reading Joshua Bloch. Effective Java. Addison Wesley, 2 edition, 2008. ISBN 0321356683. Brian Goetz. Interface evolution via virtual extensions methods. Technical report, Oracle Corporation, June 2011. URL http://cr.openjdk.java.net/ ~briangoetz/lambda/Defender%20Methods%20v4.pdf. Cay S. Horstmann. Java SE 8 for the Really Impatient. Addison-Wesley Professional, 2014. Raffi Khatchadourian and Hidehiko Masuhara. Automated refactoring of legacy Java software to default methods. In International Conference on Software Engineering, 2017. Jens Palsberg and Michael I. Schwartzbach. Object-oriented type systems. John Wiley and Sons Ltd., 1994. ISBN 0-471-94128-X. Frank Tip, Robert M. Fuhrer, Adam Kieżun, Michael D. Ernst, Ittai Balaban, and Bjorn De Sutter. Refactoring using type constraints. ACM Transactions on Programming Languages and Systems, 2011. doi: 10.1145/1961204.1961205. 12

×