Refactoring for software design smells - icse 2014 tutorial

Post on 28-Jan-2015

114 Views

Category:

Software

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

This tutorial on refactoring was software design smells was presented in ICSE 2014.

Transcript

Girish Suryanarayana, Ganesh Samarthyam, Tushar Sharma

2

Who we are?

Girish Suryanarayana

girish.suryanarayana@gmail.com

Tushar Sharma

tusharsharma@ieee.org

Ganesh Samarthyam

sgganesh@gmail.com

3

Outline

Introduction – Design Quality, Technical Debt, and Design Smells

Design Smells Catalog – Examples and corresponding Refactoring

The Smell Ecosystem and Repaying Technical Debt in Practice

4

Outline

Introduction – Design Quality, Technical Debt, and Design Smells

Design Smells Catalog – Examples and corresponding Refactoring

The Smell Ecosystem and Repaying Technical Debt in Practice

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 Electric Corp

Pe

rce

nta

ge C

on

trib

uti

on

Industry Data on Defect Origins

Adminstrative Errors

Documentation Errors

Bad Fixes

Coding Errors

Design Errors

Requirements Errors

Up to 64% of software defects can be traced back to errors in software

design in enterprise software!

Why care about design quality?

Poor software quality costs more than $150 billion per year in U.S. and greater than $500 billion per year worldwide

The debt that accrues when you knowingly or unknowingly make wrong or non-optimal design decisions

Software Quality

Technical Debt

Design Quality

Design Quality means changeability, extensibility,

understandability, reusability

7

Why care about technical debt?

8

What constitutes technical debt?

Code debt

Static analysis tool

violations

Inconsistent coding style

Design debt

Design smells

Violations of design rules

Test debt

Lack of tests

Inadequate test coverage

Documentation debt

No documentation for important

concerns

Outdated documentation

“Design smells” aka…

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

What is a smell?

10

Why care about smells?

Impacted Quality

Reusability

Changeability

Understandability

Extensibility

Testability

Reliability

Product Quality

Design Quality

Design Smells

Impacted Quality

Maintainability:

Affected by

changeability &

extensibility

Reliability: Impacted

by poor

understandability

Indicators

Rigidity & Fragility

Immobility & Opacity

Needless complexity

Needless repetition

11

Why we focus on smells?

A good designer is one who knows the

design solutions

A GREAT designer is one who understands the impact of design

smells and knows how to address them

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 of

smells

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

13

Design principles used to classify design smells

Abstraction Encapsulation

Modularization Hierarchy

Principles

14

A principle-based approach to design smells classification

Related Publications

S G Ganesh, Tushar Sharma, Girish Suryanarayana. Towards a Principle-based

Classification 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)

15

Summary till now

Design Quality

Technical Debt

Design Smells

Why care about smells

16

Outline

Introduction – Design Quality, Technical Debt, and Design Smells

Design Smells Catalog – Examples and corresponding Refactoring

The Smell Ecosystem and Repaying Technical Debt in Practice

17

18

A note on examples in this presentation

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

Lack 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 language

Some code examples are in Java, but they are very few

19

20

The principle of abstraction

21

Enabling techniques for abstraction

22

23

Incomplete abstraction

This smell arises when a type does not support a responsibility

completelySpecifically, the public interface of the type is incomplete in that it

does not support all behavior needed by objects of its type

24

Incomplete abstraction – Example

In this case, the MutableTreeNode

supports only setUserObject but no

corresponding getUserObject (which

is provided in its derived class!) Hence, MutableTreeNode has

Incomplete Abstraction smell

How to fix it? Provide all the

necessary and relevant methods

required for satisfying a

responsibility completely in the class

itself

In case of public APIs (as in this

case), it is often “too late” to fix

it!

25

Another example

26

27

How to refactor & in future avoid this smell?

For each abstraction (especially in public interface) look out for symmetrical

methods or methods that go together

For example, methods for comparing equality of objects and getting

hash code (in Java/C#)

Look out for missing matching methods in symmetrical methods (see

table)

min/max open/close create/destroy get/set

read/write print/scan first/last begin/end

start/stop lock/unlock show/hide up/down

source/target insert/delete first/last push/pull

enable/disable acquire/release left/right on/off

28

29

Duplicate abstraction

This smell arises when two or more abstractions have identical

names or identical implementation or both.

30

31

Kinds of clones

• exactly identical except for variations in whitespace, layout, and comments

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 implemented by syntactic variants

Type 4

32

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; // '#'

}

33

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

}

34

Unnecessary abstraction

The smell occurs when an abstraction gets introduced in a software

design which is actually not needed and thus could have been avoided.

35

36

The principle of encapsulation

37

Enabling techniques for encapsulation

38

39

40

Leaky encapsulation

This smell arises when an abstraction “exposes” or “leaks”

implementation details through its public interface.

41

Refactoring leaky encapsulation smell

42

43

44

Missing encapsulation

This smell occurs when the encapsulation of implementation

variations in a type or hierarchy is missing.

45

Refactoring missing encapsulation smell

46

Refactoring missing encapsulation smell

47

48

The principle of modularization

49

Enabling techniques for modularization

50

51

52

Insufficient modularization

This smell arises when an existing abstraction could be further

decomposed thereby reducing its interface size, implementation

complexity or both. Two variants: a) When an abstraction has a large number of members in its interface, its

implementation, or both

b) When an abstraction has one or more methods with excessive complexity

53

Insufficient modularization – Example

The abstract class java.awt.Component is

an example of insufficient modularization

It is a massive class with 332 methods

(of which 259 are public!)

11 nested/inner classes

107 fields (including constants)

source file spans 10,102 lines of

code!

The Component serves as a base class

and the hierarchy is deep

Derived classes inherit the members

=> life is quite difficult!

54

55

56

57

Cyclically-dependent modularization

This smell arises when two or more class-level abstractions depend

on each other directly or indirectly (creating a tight coupling among

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

58

Refactoring cyclically-dependent modularization

59

Refactoring cyclically-dependent modularization

60

Refactoring cyclically-dependent modularization

61

Refactoring cyclically-dependent modularization

62

Refactoring cyclically-dependent modularization

63

Refactoring cyclically-dependent modularization

64

65

The principle of hierarchy

66

Enabling techniques for hierarchy

67

68

69

Unfactored hierarchy

This smell arises when the types in a hierarchy share unnecessary

duplication in the hierarchy. Two forms of this smell:

• Duplication in sibling types

• Duplication in super and subtypes

70

A refactoring for missing intermediate types

71

Refactoring for unfactored hierarchy

72

Refactoring for unfactored hierarchy

73

74

75

76

Broken hierarchy

This smell arises when the base abstraction and its derived

abstraction(s) conceptually do not share “IS-A” relationship

(resulting in broken substitutability).

This design smell arises when inheritance is used wrongly instead of

using composition.

77

LSP

It should be possible to replace objects of supertype with

objects of subtypes without altering the desired behavior of

the program

78

Refactoring broken hierarchy

79

Refactoring broken hierarchy

80

81

82

Unnecessary hierarchy

This smell arises when an inheritance hierarchy has one or more unnecessary

abstractions. 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

83

Refactoring unnecessary hierarchy

84

Refactoring unnecessary hierarchy

85

Refactoring unnecessary hierarchy

86

Summary till now

Abstraction SmellsIncomplete Abstraction

Duplicate Abstraction

Unnecessary Abstraction

Encapsulation Smells Leaky Encapsulation

Missing Encapsulation

Modularization SmellsInsufficient Modularization

Cyclically-dependent Modularization

Hierarchy SmellsUnfactored Hierarchy

Broken Hierarchy

Unnecessary Hierarchy

87

Outline

Introduction – Design Quality, Technical Debt, and Design Smells

Design Smells Catalog – Examples and corresponding Refactoring

The Smell Ecosystem and Repaying Technical Debt in Practice

88

Smell Ecosystem

DD

DD

DD

DD

DD

SmellSmell

Smell

DD

DD: Design DecisionDesign

89

Role of context in smells and refactoring

Could it be Duplicate Abstraction, Unfactored

Hierarchy, or Unnecessary Abstraction smell?

90

Interplay of Smells: Co-occurring smells

91

Interplay of Smells: Amplification

Insufficient Modularization smell due to Component

class amplify the impact of deep hierarchy negatively.

92

Interplay of Smells: Deeper problems

93

How to improve design quality in practice?

94

Refactoring process model

95

What were your key takeaways?

96

Our upcoming book on this topic!

97

98

References

99

Ganesh Samarthyam

sgganesh@gmail.com

Twitter@GSamarthyam

Girish Suryanarayana

girish.suryanarayana@gmail.com

Twitter@girish_sur

Tushar Sharma

tusharsharma@ieee.org

Twitter@Sharma__Tushar

top related