100
Girish Suryanarayana, Ganesh Samarthyam, Tushar Sharma

Refactoring for Design Smells - ICSE 2014 Tutorial

Embed Size (px)

DESCRIPTION

In this tutorial, we introduce a comprehensive catalog, classification, and naming scheme for design smells to the participants. We discuss important structural design smells based on how they violate the four key object oriented design principles (abstraction, encapsulation, modularization, and hierarchy). Smells are illustrated through design smells found in OpenJDK (Open source Java Development Kit) code base, with discussions on refactoring strategies for addressing them.

Citation preview

Page 1: Refactoring for Design Smells - ICSE 2014 Tutorial

Girish Suryanarayana, Ganesh Samarthyam, Tushar Sharma

Page 2: Refactoring for Design Smells - ICSE 2014 Tutorial

2

Outline

Introduction – Design Quality,Technical Debt, and Design Smells

Design Smells Catalog – Examplesand corresponding Refactoring

The Smell Ecosystem and RepayingTechnical Debt in Practice

Page 3: Refactoring for Design Smells - ICSE 2014 Tutorial

3

Outline

Introduction – Design Quality,Technical Debt, and Design Smells

Design Smells Catalog – Examplesand corresponding Refactoring

The Smell Ecosystem and RepayingTechnical Debt in Practice

Page 4: Refactoring for Design Smells - ICSE 2014 Tutorial

Capers Jones on design errors in industrial software

* http://sqgne.org/presentations/2012-13/Jones-Sep-2012.pdf

0

20

40

60

80

100

120

IBM Corportation(MVS)

SPR Corporation(Client Studies)

TRW Corporation MITRE Corporation Nippon ElectricCorp

Perc

enta

geCo

ntrib

utio

n

Industry Data on Defect Origins

Adminstrative Errors

Documentation Errors

Bad Fixes

Coding Errors

Design Errors

Requirements Errors

Up to 64% of software defects canbe traced back to errors in

software design in enterprisesoftware!

Page 5: Refactoring for Design Smells - ICSE 2014 Tutorial

Why care about design quality?

Poor software qualitycosts more than $150billion per year in U.S. andgreater than $500 billionper year worldwide

The debt that accrues whenyou knowingly orunknowingly make wrong ornon-optimal design decisions

SoftwareQuality

TechnicalDebt

DesignQuality

Design Quality meanschangeability, extensibility,

understandability,reusability, ...

Page 6: Refactoring for Design Smells - ICSE 2014 Tutorial

6

Why care about technical debt?

Global 'IT Debt‘ is $500 billion for theyear 2010, with potential to grow to $1

trillion by 2015

Page 7: Refactoring for Design Smells - ICSE 2014 Tutorial

7

What constitutes technical debt?

Code debt

Static analysistool violations

Inconsistentcoding style

Design debt

Design smells

Violations ofdesign rules

Test debt

Lack of tests

Inadequate testcoverage

Documentationdebt

Nodocumentationfor important

concerns

Outdateddocumentation

Page 8: Refactoring for Design Smells - ICSE 2014 Tutorial

“Design smells” aka…

“Smells are certain structures in the code that suggest (sometimes theyscream for) the possibility of refactoring.”

What is a smell?

Page 9: Refactoring for Design Smells - ICSE 2014 Tutorial

9

Why care about smells?

Impacted Quality§ Reusability§ Changeability§ Understandability§ Extensibility§ …

ProductQuality

DesignQuality

DesignSmells

Impacted Quality§ Maintainability: Affected

by changeability &extensibility

§ Reliability: Impacted bypoor understandability

§ …

Indicators§ Rigidity & Fragility§ Immobility & Opacity§ Needless complexity§ Needless repetition§ …

Page 10: Refactoring for Design Smells - ICSE 2014 Tutorial

10

What causes design smells?

Page 11: Refactoring for Design Smells - ICSE 2014 Tutorial

11

Why we focus on smells?

A good designer isone who knows the

design solutions

A GREAT designer isone who understandsthe impact of design

smells and knowshow to address them

Page 12: Refactoring for Design Smells - ICSE 2014 Tutorial

12

Design Smells as violations of fundamental principles

What do smells indicate?Violations of fundamental design principles

We use Booch’s fundamental principles for classification and naming ofsmells

This helps identify cause of the smell and potential refactoring as well

Page 13: Refactoring for Design Smells - ICSE 2014 Tutorial

13

Principles used to classify design smells

Page 14: Refactoring for Design Smells - ICSE 2014 Tutorial

14

Quality attributes impacted by smells

Page 15: Refactoring for Design Smells - ICSE 2014 Tutorial

15

A principle-based approach to design smells classification

Related Publications

S G Ganesh, Tushar Sharma, Girish Suryanarayana. Towards a Principle-basedClassification of Structural Design Smells. In Journal of Object Technology, vol. 12,no. 2, 2013, pages 1:1–29.doi:10.5381/jot.2013.12.2.a1

URL: http://www.jot.fm/issues/issue_2013_06/article1.pdf (open access)

Page 16: Refactoring for Design Smells - ICSE 2014 Tutorial

16

Summary till now

Design Quality

Technical Debt

Design SmellsWhy care about smells

Page 17: Refactoring for Design Smells - ICSE 2014 Tutorial

17

Outline

Introduction – Design Quality,Technical Debt, and Design Smells

Design Smells Catalog – Examplesand corresponding Refactoring

The Smell Ecosystem and RepayingTechnical Debt in Practice

Page 18: Refactoring for Design Smells - ICSE 2014 Tutorial

18

Page 19: Refactoring for Design Smells - ICSE 2014 Tutorial

19

A note on examples in this presentation

We cover only a few examples of each smell category in this presentationLack of time

Most examples are from OpenJDK 7.0 (open source)All illustrations are mostly as UML diagrams so no need to know Java(though you’ll appreciate more if you know Java)

Almost all examples are UML-like diagrams – so agnostic of OO languageSome code examples are in Java, but they are very few

Page 20: Refactoring for Design Smells - ICSE 2014 Tutorial

20

Page 21: Refactoring for Design Smells - ICSE 2014 Tutorial

21

The principle of abstraction

Page 22: Refactoring for Design Smells - ICSE 2014 Tutorial

22

Enabling techniques for abstraction

Page 23: Refactoring for Design Smells - ICSE 2014 Tutorial

23

Page 24: Refactoring for Design Smells - ICSE 2014 Tutorial

24

Incomplete abstraction

This smell arises when a type does not support a responsibilitycompletely

Specifically, the public interface of the type is incomplete in that itdoes not support all behavior needed by objects of its type

Page 25: Refactoring for Design Smells - ICSE 2014 Tutorial

25

Incomplete abstraction – Example

In this case, the MutableTreeNodesupports only setUserObject but nocorresponding getUserObject (whichis provided in its derived class!)

Hence, MutableTreeNode hasIncomplete Abstraction smell

How to fix it? Provide all thenecessary and relevant methodsrequired for satisfying aresponsibility completely in the classitself

In case of public APIs (as in thiscase), it is often “too late” to fixit!

Page 26: Refactoring for Design Smells - ICSE 2014 Tutorial

26

Another example

Page 27: Refactoring for Design Smells - ICSE 2014 Tutorial

27

Page 28: Refactoring for Design Smells - ICSE 2014 Tutorial

28

How to refactor & in future avoid this smell?

For each abstraction (especially in public interface) look out for symmetricalmethods or methods that go together

For example, methods for comparing equality of objects and gettinghash code (in Java/C#)Look out for missing matching methods in symmetrical methods (seetable)

min/max open/close create/destroy get/setread/write print/scan first/last begin/endstart/stop lock/unlock show/hide up/down

source/target insert/delete first/last push/pullenable/disable acquire/release left/right on/off

Page 29: Refactoring for Design Smells - ICSE 2014 Tutorial

29

Page 30: Refactoring for Design Smells - ICSE 2014 Tutorial

30

Duplicate abstraction

This smell arises when two or more abstractions have identicalnames or identical implementation or both.

Page 31: Refactoring for Design Smells - ICSE 2014 Tutorial

31

Page 32: Refactoring for Design Smells - ICSE 2014 Tutorial

32

Kinds of clones

• exactly identical except for variations in whitespace, layout, andcomments

Type 1

• syntactically identical except for variation in symbol names,whitespace, layout, and comments

Type 2

• identical except some statements changed, added, or removed

Type 3

• when the fragments are semantically identical but implementedby syntactic variants

Type 4

Page 33: Refactoring for Design Smells - ICSE 2014 Tutorial

33

public class FormattableFlags {// Explicit instantiation of this class is prohibited.private FormattableFlags() {}/** Left-justifies the output. */public static final int LEFT_JUSTIFY = 1<<0; // '-'/** Converts the output to upper case */public static final int UPPERCASE = 1<<1; // 'S'/**Requires the output to use an alternate form. */public static final int ALTERNATE = 1<<2; // '#'

}

Page 34: Refactoring for Design Smells - ICSE 2014 Tutorial

34

public class Dollar {public static final String symbol = “$”;

}

Page 35: Refactoring for Design Smells - ICSE 2014 Tutorial

35

Unnecessary abstraction

The smell occurs when an abstraction gets introduced in a softwaredesign which is actually not needed and thus could have been avoided.

Page 36: Refactoring for Design Smells - ICSE 2014 Tutorial

36

Page 37: Refactoring for Design Smells - ICSE 2014 Tutorial

37

The principle of encapsulation

Page 38: Refactoring for Design Smells - ICSE 2014 Tutorial

38

Enabling techniques for encapsulation

Page 39: Refactoring for Design Smells - ICSE 2014 Tutorial

39

Page 40: Refactoring for Design Smells - ICSE 2014 Tutorial

40

Page 41: Refactoring for Design Smells - ICSE 2014 Tutorial

41

Leaky encapsulation

This smell arises when an abstraction “exposes” or “leaks”implementation details through its public interface.

Page 42: Refactoring for Design Smells - ICSE 2014 Tutorial

42

Refactoring leaky encapsulation smell

Page 43: Refactoring for Design Smells - ICSE 2014 Tutorial

43

Page 44: Refactoring for Design Smells - ICSE 2014 Tutorial

44

Page 45: Refactoring for Design Smells - ICSE 2014 Tutorial

45

Missing encapsulation

This smell occurs when the encapsulation of implementationvariations in a type or hierarchy is missing.

Page 46: Refactoring for Design Smells - ICSE 2014 Tutorial

46

Refactoring missing encapsulation smell

Page 47: Refactoring for Design Smells - ICSE 2014 Tutorial

47

Refactoring missing encapsulation smell

Page 48: Refactoring for Design Smells - ICSE 2014 Tutorial

48

Page 49: Refactoring for Design Smells - ICSE 2014 Tutorial

49

The principle of modularization

Page 50: Refactoring for Design Smells - ICSE 2014 Tutorial

50

Enabling techniques for modularization

Page 51: Refactoring for Design Smells - ICSE 2014 Tutorial

51

Page 52: Refactoring for Design Smells - ICSE 2014 Tutorial

52

Page 53: Refactoring for Design Smells - ICSE 2014 Tutorial

53

Insufficient modularization

This smell arises when an existing abstraction could be furtherdecomposed thereby reducing its interface size, implementationcomplexity or both. Two variants:a) When an abstraction has a large number of members in its interface, itsimplementation, or bothb) When an abstraction has one or more methods with excessive complexity

Page 54: Refactoring for Design Smells - ICSE 2014 Tutorial

54

Insufficient modularization – Example

The abstract class java.awt.Component isan example of insufficient modularization

It is a massive class with 332 methods(of which 259 are public!)11 nested/inner classes107 fields (including constants)source file spans 10,102 lines ofcode!

The Component serves as a base classand the hierarchy is deep

Derived classes inherit the members=> life is quite difficult!

Page 55: Refactoring for Design Smells - ICSE 2014 Tutorial

55

Page 56: Refactoring for Design Smells - ICSE 2014 Tutorial

56

Page 57: Refactoring for Design Smells - ICSE 2014 Tutorial

57

Page 58: Refactoring for Design Smells - ICSE 2014 Tutorial

58

Cyclically-dependent modularization

This smell arises when two or more class-level abstractions dependon each other directly or indirectly (creating a tight coupling amongthe abstractions).

(This smell is commonly known as “cyclic dependencies”)

Page 59: Refactoring for Design Smells - ICSE 2014 Tutorial

59

Refactoring cyclically-dependent modularization

Page 60: Refactoring for Design Smells - ICSE 2014 Tutorial

60

Refactoring cyclically-dependent modularization

Page 61: Refactoring for Design Smells - ICSE 2014 Tutorial

61

Refactoring cyclically-dependent modularization

Page 62: Refactoring for Design Smells - ICSE 2014 Tutorial

62

Refactoring cyclically-dependent modularization

Page 63: Refactoring for Design Smells - ICSE 2014 Tutorial

63

Refactoring cyclically-dependent modularization

Page 64: Refactoring for Design Smells - ICSE 2014 Tutorial

64

Refactoring cyclically-dependent modularization

Page 65: Refactoring for Design Smells - ICSE 2014 Tutorial

65

Page 66: Refactoring for Design Smells - ICSE 2014 Tutorial

66

The principle of hierarchy

Page 67: Refactoring for Design Smells - ICSE 2014 Tutorial

67

Enabling techniques for hierarchy

Page 68: Refactoring for Design Smells - ICSE 2014 Tutorial

68

Page 69: Refactoring for Design Smells - ICSE 2014 Tutorial

69

Page 70: Refactoring for Design Smells - ICSE 2014 Tutorial

70

Unfactored hierarchy

This smell arises when the types in a hierarchy share unnecessaryduplication in the hierarchy. Two forms of this smell:

• Duplication in sibling types• Duplication in super and subtypes

Page 71: Refactoring for Design Smells - ICSE 2014 Tutorial

71

A refactoring for missing intermediate types

Page 72: Refactoring for Design Smells - ICSE 2014 Tutorial

72

Refactoring for unfactored hierarchy

Page 73: Refactoring for Design Smells - ICSE 2014 Tutorial

73

Refactoring for unfactored hierarchy

Page 74: Refactoring for Design Smells - ICSE 2014 Tutorial

74

Page 75: Refactoring for Design Smells - ICSE 2014 Tutorial

75

Page 76: Refactoring for Design Smells - ICSE 2014 Tutorial

76

Page 77: Refactoring for Design Smells - ICSE 2014 Tutorial

77

Broken hierarchy

This smell arises when the base abstraction and its derivedabstraction(s) conceptually do not share “IS-A” relationship(resulting in broken substitutability).

This design smell arises when inheritance is used wrongly instead ofusing composition.

Page 78: Refactoring for Design Smells - ICSE 2014 Tutorial

78

LSP

It should be possible to replaceobjects of supertype with

objects of subtypes withoutaltering the desired behavior of

the program

Page 79: Refactoring for Design Smells - ICSE 2014 Tutorial

79

Refactoring broken hierarchy

Page 80: Refactoring for Design Smells - ICSE 2014 Tutorial

80

Refactoring broken hierarchy

Page 81: Refactoring for Design Smells - ICSE 2014 Tutorial

81

Page 82: Refactoring for Design Smells - ICSE 2014 Tutorial

82

Page 83: Refactoring for Design Smells - ICSE 2014 Tutorial

83

Unnecessary hierarchy

This smell arises when an inheritance hierarchy has one or more unnecessaryabstractions. Includes the following cases:

• all the subtypes are unnecessary (i.e., inappropriate use of inheritance)• supertype has only one subtype (i.e., speculative generalization)• intermediate types are unnecessary

Page 84: Refactoring for Design Smells - ICSE 2014 Tutorial

84

Refactoring unnecessary hierarchy

Page 85: Refactoring for Design Smells - ICSE 2014 Tutorial

85

Refactoring unnecessary hierarchy

Page 86: Refactoring for Design Smells - ICSE 2014 Tutorial

86

Refactoring unnecessary hierarchy

Page 87: Refactoring for Design Smells - ICSE 2014 Tutorial

87

Summary till now

Abstraction SmellsIncomplete AbstractionDuplicate AbstractionUnnecessary Abstraction

Encapsulation SmellsLeaky EncapsulationMissing Encapsulation

Modularization SmellsInsufficient ModularizationCyclically-dependent Modularization

Hierarchy SmellsUnfactored HierarchyBroken HierarchyUnnecessary Hierarchy

Page 88: Refactoring for Design Smells - ICSE 2014 Tutorial

88

Outline

Introduction – Design Quality,Technical Debt, and Design Smells

Design Smells Catalog – Examplesand corresponding Refactoring

The Smell Ecosystem and RepayingTechnical Debt in Practice

Page 89: Refactoring for Design Smells - ICSE 2014 Tutorial

89

Smell Ecosystem

DD

DD

DD

DD

DD

SmellSmell

Smell

DD

DD: Design DecisionDesign

Page 90: Refactoring for Design Smells - ICSE 2014 Tutorial

90

Role of context in smells and refactoring

Could it be DuplicateAbstraction, Unfactored

Hierarchy, or UnnecessaryAbstraction smell?

Page 91: Refactoring for Design Smells - ICSE 2014 Tutorial

91

Interplay of Smells: Co-occurring smells

Page 92: Refactoring for Design Smells - ICSE 2014 Tutorial

92

Interplay of Smells: Amplification

Insufficient Modularizationsmell due to Component

class amplify the impact ofdeep hierarchy negatively.

Page 93: Refactoring for Design Smells - ICSE 2014 Tutorial

93

Interplay of Smells: Deeper problems

Page 94: Refactoring for Design Smells - ICSE 2014 Tutorial

94

How to improve design quality in practice?

Page 95: Refactoring for Design Smells - ICSE 2014 Tutorial

95

Refactoring process model

Page 96: Refactoring for Design Smells - ICSE 2014 Tutorial

96

What were your key takeaways?

Page 97: Refactoring for Design Smells - ICSE 2014 Tutorial

97

Our upcoming book on this topic!

Page 98: Refactoring for Design Smells - ICSE 2014 Tutorial

98

Page 99: Refactoring for Design Smells - ICSE 2014 Tutorial

99

References

Page 100: Refactoring for Design Smells - ICSE 2014 Tutorial

100

Ganesh Samarthyam

[email protected]

Twitter@GSamarthyam

Girish Suryanarayana

[email protected]

Twitter@girish_sur

Tushar Sharma

[email protected]

Twitter@Sharma__Tushar