210 likes | 289 Views
Removing Duplication from java.io: a Case Study using Traits. Emerson R. Murphy-Hill, Philip J. Quitslund, Andrew P. Black Maseeh College of Engineering and Computer Science Portland State University. Introduction. Duplication: widespread and problematic Here we demonstrate it
E N D
Removing Duplication from java.io: a Case Study using Traits Emerson R. Murphy-Hill, Philip J. Quitslund, Andrew P. Black Maseeh College of Engineering and Computer Science Portland State University Slide 1 (of 21)
Introduction • Duplication: widespread and problematic • Here we demonstrate it • Look through some well-weathered code • Try to factor out encountered duplication with traits Slide 2 (of 21)
Traits • A trait is a collection of pure methods • Classes “use” traits • Traits can be used to supply the same methods to multiple classes in the inheritance hierarchy Slide 3 (of 21)
and Solution Duplication: Problem Slide 4 (of 21)
Some Trait Implementations • Original implementation in Squeak Smalltalk • Also in Perl, Scala, and C# • Our implementation in Java, on top of Eclipse • Traits represented as abstract classes • No compiler modification Slide 5 (of 21)
java.io Slide 6 (of 21)
The Plan 9 AM Find duplication 9:15 AM Remove duplication using Traits 11:15 AM Pat selves on back; go home early Slide 7 (of 21)
Finding Duplication • We identified some duplication detection tools: • Duplication Management Framework • SimScan • PMD’s Copy-Paste Detector (CPD) • Some obvious duplication found, but that was just the tip of the iceberg… Slide 8 (of 21)
Interesting Detected Duplication } else if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } • Other throwers of IndexOutOfBoundsException? x 3 Slide 9 (of 21)
Why? • Differences in: • Semantics • Structure • Efficiency • Miscellaneous Detection Effectiveness Slide 10 (of 21)
Semantic differences (StringWriter>>write(...)) if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } (StringReader>>read(...)) if ((off < 0) || (off > cbuf.length) || (len < 0) || ((off + len) > cbuf.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } Slide 11 (of 21)
Structural Differences (ByteArrayOutputStream>>write(...)) if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } (ByteArrayInputStream>>read(...)) if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } if (pos >= count) { return -1; } if (pos + len > count) { len = count - pos; } if (len <= 0) { return 0; } Slide 12 (of 21)
? Exception Handling Differences (ByteArrayOutputStream>>write(...)) if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } (ByteArrayInputStream>>read(...)) if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } if (pos >= count) { return -1; } if (pos + len > count) { len = count - pos; } if (len <= 0) { return 0; } Suppose b == null AND off == -1 Slide 13 (of 21)
Bounds check changed in 1.3, but in exactly 3 of 26 cases! Efficiency Differences (ByteArrayOutputStream>>write(...)) if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } (PipedWriter>>write(...)) if (sink == null) { throw new IOException("Pipe not connected"); } else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) throw new IndexOutOfBoundsException(); Slide 14 (of 21)
Miscellaneous Differences (PushbackReader>>read(...)) try { if (len <= 0) { if (len < 0) { throw new IndexOutOfBoundsException(); } else if ((off < 0) || (off > cbuf.length)) { throw new IndexOutOfBoundsException(); } return 0; } //...actual work... } catch (ArrayIndexOutOfBoundsException e) { throw new IndexOutOfBoundsException(); } Slide 15 (of 21)
What did we Learn? • Duplication occurs non-uniformly • So we can’t detect it easily using tools • And we can’t easily remove it • We can’t tell the difference between intentional and accidental differences Slide 16 (of 21)
Our Refactoring Slide 17 (of 21)
The Plan 9 AM Find duplication 9:15 AM Remove duplication using Traits 11:15 AM Pat selves on back; go home early + 3 weeks Slide 18 (of 21)
Conclusion • Finding duplication during the maintenance stage of software development is hard • Intentional and accidental differences • Traits can factor out duplication in a commercial code base • If coders use traits while programming, the need to duplicate is reduced Slide 19 (of 21)
Related Work • Related Studies • “Applying traits to the smalltalk collection classes,” OOPSLA 2003. • Related Approaches • Multiple Inheritance, Mixins, Delegation • Static Utility Classes • AOP • AspectJ, CME(Hyper/J), etc. • Any more? Slide 20 (of 21)
Questions? Slide 21 (of 21)