Date post: | 08-Feb-2017 |
Category: |
Software |
Upload: | tushar-sharma |
View: | 206 times |
Download: | 4 times |
Achieving Design Agilityby Refactoring Design Smells
Tushar Sharma@Sharma__Tushar
16 - 17 June 2016, London, UK
Tushar Sharma
Researcher@AUEB Earlier, Siemens Research (Bangalore).
Interests: Software design and architecture, software quality, smells, refactoring, technical debt, and infrastructure as code.
http://www.tusharma.in @Sharma__Tushar
A
B
C
D
PART-B • Exercise
PART-C • Design smell catalog • Design smells with examples
PART-D • Tools to repay the debt
PART-A • Design Agility • Importance of Software Design • Technical Debt • Design Smells
Agile is not only about a process!!
Agile is all about achieving “Agility”.
transforms
Agile
Process
Artifacts
Mind-set
enablesSpeed
Agi
lity
“Agility is the ability to both create and respond to change.”
-Jim Highsmith
“Design Agility” is the ability of the design to respond to change quickly and swiftly.
Let us connect the dots
Agility
Agileshould facilitate
Speedenables
Smells
reduces
Refactoringimproves
Capers Jones on design errors in industrial software
* http://sqgne.org/presentations/2012-13/Jones-Sep-2012.pdf
Industry Data on Defect Origins
Perc
enta
ge C
ontr
ibut
ion
0
25
50
75
100
Requirements ErrorsDesign ErrorsCoding ErrorsBad FixesDocumentation ErrorsAdminstrative Errors
Up to 64% of software defects can be traced back to errors in
software design in enterprise software!
Software Quality
Technical Debt
Design Quality
IMPACTS
Why care about design quality?
INDICATES
Poor
Design Quality means changeability, extensibility,
understandability, reusability, ...
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 are certain structures in the design that indicate violation of fundamental design principles and
negatively impact design quality.”
Design Smell
Why care about smells?
Impacted Quality ▪ Reusability ▪ Changeability ▪ Understandability ▪ Extensibility ▪ … 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 ▪ …
A
B
C
D
PART-B • Exercise
PART-C • Design smell catalog • Design smells with examples
PART-D • Tools to repay the debt
PART-A • Design Agility • Importance of Software Design • Technical Debt • Design Smells
A
B
C
D
PART-B • Exercise
PART-C • Design smell catalog • Design smells with examples
PART-D • Tools to repay the debt
PART-A • Design Agility • Importance of Software Design • Technical Debt • Design Smells
Duplicate abstractionThis smell arises when two or more abstractions have identical names or identical implementation or both.
Let us refactor the smell
Change name of one of the abstractions
Factor out the commonality into a third abstraction which can be used by the original abstraction
Remove a duplication from one of the abstractions which then refers to the other abstraction for that particular functionality
public class Throwable {
// following method is available
//from Java 1.0 version.
// Prints the stack trace as a string
//to standard output // for processing a stack trace,
// we need to write
//regular expressions
public void printStackTrace();
// other methods elided
} What’s that smell?
Missing abstraction
This smell arises when clumps of data or encoded strings are used instead of
creating a class or an interface.
Let us refactor the smell
public class Throwable {
public void printStackTrace();
public StackTraceElement[]
getStackTrace(); // Since 1.4
// other methods elided
}public final class StackTraceElement { public String getFileName(); public int getLineNumber(); public String getClassName(); public String getMethodName(); public boolean isNativeMethod();
}
public class Throwable {
// following method is available
//from Java 1.0 version.
// Prints the stack trace as a string
//to standard output
// for processing a stack trace,
// we need to write
//regular expressions
public void printStackTrace();
// other methods elided
}
java.util.Calendar
In addition to methods supporting dates, the class has
methods for supporting time as well!
What’s that smell?
Multi-faceted abstraction
This smell arises when an abstraction has more than one responsibility assigned to it.
Deficient encapsulation
This design smell occurs when the declared accessibility of one or
more members of an abstraction is more permissive than actually
required.
Missing encapsulation
This smell occurs when implementation variations are not encapsulated within an abstraction or hierarchy.
Broken modularization
This smell arises when members of an abstraction are broken and spread across multiple abstractions (when ideally they should have been localized into a single abstraction). Two forms of this smell:
Data and methods that ideally belong to an abstraction are split among two or more abstractions. Methods in a class that are interested in members of other classes.
Insufficient modularization
This smell arises when an abstraction exists that has not been completely decomposed and a further decomposition could reduce its size, implementation complexity, or both.
There are two forms of this smell - • Bloated interface • Bloated implementation
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!
Let us refactor the smell
Refactoring for ‘bloated interface’ Extract-class Client specific interfaces
Refactoring for ‘bloated implementation’ Extract-method => private helper methods Extract-class or Move-field/Move-method to encapsulate each responsibility within separate (new or existing) abstractions.
Unnecessary hierarchy
This smell arises when the whole inheritance hierarchy is unnecessary, indicating that inheritance has been applied needlessly for the particular design context.
Rebellious hierarchy
This smell arises when a subtype rejects the methods provided by its supertype(s):
throw an exception, provide an empty (or NOP i.e., NO Operation) method provide a method definition that just prints “should not implement” message
Broken hierarchy
This smell arises when a supertype and its subtype conceptually do not share an “IS-
A” relationship resulting in broken substitutability.
A
B
C
D
PART-B • Exercise
PART-C • Design smell catalog • Design smells with examples
PART-D • Tools to repay the debt
PART-A • Design Agility • Importance of Software Design • Technical Debt • Design Smells
Tools
Comprehension tools Imagix 4D, Structure 101
Critique, code-clone detectors, and metric tools Infusion, Designite, Ndepend Simian, CPD Understand, Source-monitor, Designite
Technical debt quantification and visualization tools SonarQube
Refactoring tools Refactoring inferencing tools – SCOUT, Jdeoderant Refactoring performing tools – Eclipse, Resharper