Refactoring for
Software Design Smells
Ganesh Samarthyam
Entrepreneur; author; speaker
ganesh@codeops.tech
www.codeops.tech
–Craig Larman
"The critical design tool for software development
is a mind well educated in design principles"
Poor software quality costs
more than $150 billion per year
in U.S. and greater than $500
billion per year worldwide
- Capers Jones
Source: Estimating the Principal of an Application's Technical Debt, Bill Curtis, Jay
Sappidi, Alexandra Szynkarski, IEEE Software, Nov.-Dec. 2012.
Source: Consortium of IT Software Quality (CISQ), Bill Curtis, Architecturally Complex Defects, 2012
“The problem with quick and dirty...is that dirty
remains long after quick has been forgotten”
Steve C McConnell
For Architects: Design is the Key!
"... a delightful, engaging, actionable read... you have
in your hand a veritable field guide of smells... one
of the more interesting and complex expositions of
software smells you will ever find..."
- From the foreword by Grady Booch (IBM Fellow and Chief Scientist for
Software Engineering, IBM Research)
"This is a good book about ‘Design Smells’ – actually
a great book – nicely organized - clearly written with
plenty of examples and a fair sprinkling of
anecdotes."
- Will Tracz (Principal Research Scientist & Fellow, Lockheed Martin)
(review in ACM SIGSOFT Software Engineering Notes)
Fundamental Principles in Software Design
Principles*
Abstrac/on*
Encapsula/on*
Modulariza/on*
Hierarchy*
Proactive Application: Enabling Techniques
Reactive Application: Smells
Is this a Smell?
abstract class Printer {
private Integer portNumber = getPortNumber();
abstract Integer getPortNumber();
public static void main(String[]s) {
Printer p = new LPDPrinter();
System.out.println(p.portNumber);
}
}
class LPDPrinter extends Printer {
/* Line Printer Deamon port no is 515 */
private Integer defaultPortNumber = 515;
Integer getPortNumber() {
return defaultPortNumber;
}
}
prints
“null”!
What’s that smell?
public'Insets'getBorderInsets(Component'c,'Insets'insets){'
''''''''Insets'margin'='null;'
'''''''''//'Ideally'we'd'have'an'interface'defined'for'classes'which'
''''''''//'support'margins'(to'avoid'this'hackery),'but'we've'
''''''''//'decided'against'it'for'simplicity'
''''''''//'
''''''''if'(c'instanceof'AbstractBuEon)'{'
'''''''''''''''''margin'='((AbstractBuEon)c).getMargin();'
''''''''}'else'if'(c'instanceof'JToolBar)'{'
''''''''''''''''margin'='((JToolBar)c).getMargin();'
''''''''}'else'if'(c'instanceof'JTextComponent)'{'
''''''''''''''''margin'='((JTextComponent)c).getMargin();'
''''''''}'
''''''''//'rest'of'the'code'omiEed'…'
Refactoring
Refactoring
!!!!!!!margin!=!c.getMargin();
!!!!!!!!if!(c!instanceof!AbstractBu8on)!{!
!!!!!!!!!!!!!!!!!margin!=!((AbstractBu8on)c).getMargin();!
!!!!!!!!}!else!if!(c!instanceof!JToolBar)!{!
!!!!!!!!!!!!!!!!margin!=!((JToolBar)c).getMargin();!
!!!!!!!!}!else!if!(c!instanceof!JTextComponent)!{!
!!!!!!!!!!!!!!!!margin!=!((JTextComponent)c).getMargin();!
!!!!!!!!}
Design Smells: Example
Discussion Example
Design Smells: Example
Discussion Example
// using java.util.Date
Date today = new Date();
System.out.println(today);
$ java DateUse
Wed Dec 02 17:17:08 IST 2015
Why should we get the
time and timezone details
if I only want a date? Can
I get rid of these parts?
No!
So What!
Date today = new Date();
System.out.println(today);
Date todayAgain = new Date();
System.out.println(todayAgain);
System.out.println(today.compareTo(todayAgain) == 0);
Thu Mar 17 13:21:55 IST 2016
Thu Mar 17 13:21:55 IST 2016
false
What is going
on here?
Refactoring for Date
Replace inheritance
with delegation
java.time package!
Refactored Solution
LocalDate today = LocalDate.now();
System.out.println(today);
LocalDate todayAgain = LocalDate.now();
System.out.println(todayAgain);
System.out.println(today.compareTo(todayAgain) == 0);
2016-03-17
2016-03-17
true
Works fine
now!
Refactored Example …
You can use only date,
time, or even timezone,
and combine them as
needed!
LocalDate today = LocalDate.now();
System.out.println(today);
LocalTime now = LocalTime.now();
System.out.println(now);
ZoneId id = ZoneId.of("Asia/Tokyo");
System.out.println(id);
LocalDateTime todayAndNow = LocalDateTime.now();
System.out.println(todayAndNow);
ZonedDateTime todayAndNowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(todayAndNowInTokyo);
2016-03-17
13:28:06.927
Asia/Tokyo
2016-03-17T13:28:06.928
2016-03-17T16:58:06.929+09:00[Asia/Tokyo]
More classes in Date/Time API
What’s that smell?
Liskov’s Substitution Principle (LSP)
It#should#be#possible#to#replace#
objects#of#supertype#with#
objects#of#subtypes#without#
altering#the#desired#behavior#of#
the#program#
Barbara#Liskov#
Refactoring
Replace inheritance
with delegation
What’s that smell?
switch'(transferType)'{'
case'DataBuffer.TYPE_BYTE:'
byte'bdata[]'='(byte[])inData;'
pixel'='bdata[0]'&'0xff;'
length'='bdata.length;'
break;'
case'DataBuffer.TYPE_USHORT:'
short'sdata[]'='(short[])inData;'
pixel'='sdata[0]'&'0xffff;'
length'='sdata.length;'
break;'
case'DataBuffer.TYPE_INT:'
int'idata[]'='(int[])inData;'
pixel'='idata[0];'
length'='idata.length;'
break;'
default:'
throw' new' UnsupportedOperaQonExcepQon("This' method' has' not' been' "+' "implemented'
for'transferType'"'+'transferType);'
}'
Replace conditional with polymorphism
protected(int(transferType;! protected(DataBuffer(dataBuffer;!
pixel(=(dataBuffer.getPixel();(
length(=(dataBuffer.getSize();!
switch((transferType)({(
case(DataBuffer.TYPE_BYTE:(
byte(bdata[](=((byte[])inData;(
pixel(=(bdata[0](&(0xff;(
length(=(bdata.length;(
break;(
case(DataBuffer.TYPE_USHORT:(
short(sdata[](=((short[])inData;(
pixel(=(sdata[0](&(0xffff;(
length(=(sdata.length;(
break;(
case(DataBuffer.TYPE_INT:(
int(idata[](=((int[])inData;(
pixel(=(idata[0];(
length(=(idata.length;(
break;(
default:(
throw( new( UnsupportedOperaRonExcepRon("This( method(
has( not( been( "+( "implemented( for( transferType( "( +(
transferType);(
}!
Configuration Smells!
Language Features & Refactoring
public static void main(String []file) throws Exception {
// process each file passed as argument
// try opening the file with FileReader
try (FileReader inputFile = new FileReader(file[0])) {
int ch = 0;
while( (ch = inputFile.read()) != -1) {
// ch is of type int - convert it back to char
System.out.print( (char)ch );
}
}
// try-with-resources will automatically release FileReader object
}
public static void main(String []file) throws Exception {
Files.lines(Paths.get(file[0])).forEach(System.out::println);
}
Java 8 lambdas and streams
Refactoring Windows!
Refactoring Windows!
“A large number of dependencies at the module level
could be reduced and optimized to:
* make modular reasoning of the system more efficient
* maximize parallel development efficiency
* avoid unwanted parallel change interference
* selectively rebuild and retest subsystems effectively”
Refactoring performed to reduce
and optimize dependencies - by
creating and enforcing layering
Source: Kim, Miryung, Thomas Zimmermann, and Nachiappan Nagappan. "An Empirical Study of RefactoringChallenges and Benefits at Microsoft."
IEEE Transactions on Software Engineering 7 (2014): 1-1.
Refactoring Windows!
Refactoring decisions made after substantial
analysis of existing dependency structure
Refactoring effort was centralized and top
down with designated team for refactoring
Use of custom refactoring tools (MaX)
and processes (quality gate check)
Source: Kim, Miryung, Thomas Zimmermann, and Nachiappan Nagappan. "An Empirical Study of RefactoringChallenges and Benefits at Microsoft."
IEEE Transactions on Software Engineering 7 (2014): 1-1.
Tangles in
JDK
Copyright © 2015, Oracle and/or its affiliates. All rights reserved
Copyright © 2015, Oracle and/or its affiliates. All rights reserved
Structural Analysis for Java (stan4j)
JArchitect
InFusion
SotoArc
CodeCity
Name the first
object oriented
programming
language
Which pattern is this?
a)	Bridge	pa+ern		
b)	Decorator	pa+ern		
c)	Builder	pa+ern			
d)	Strategy	pa+ern	
LineNumberReader lnr =
new LineNumberReader(
new BufferedReader(
new FileReader(“./test.c")));
String str = null;
while((str = lnr.readLine()) != null)
System.out.println(lnr.getLineNumber() + ": " + str);
Decorator pattern in Reader
Who coined the
term “code
smell”?
Meetups
h+p://www.meetup.com/JavaScript-Meetup-Bangalore/	
h+p://www.meetup.com/Container-Developers-Meetup-Bangalore/		
h+p://www.meetup.com/SoBware-CraBsmanship-Bangalore-Meetup/	
h+p://www.meetup.com/Core-Java-Meetup-Bangalore/	
h+p://www.meetup.com/Technical-Writers-Meetup-Bangalore/	
h+p://www.meetup.com/CloudOps-Meetup-Bangalore/	
h+p://www.meetup.com/Bangalore-SDN-IoT-NetworkVirtualizaKon-Enthusiasts/	
h+p://www.meetup.com/SoBwareArchitectsBangalore/
Upcoming Java 8 Bootcamp
Modern Programming with Java 8
Refactor your legacy applications using Java 8 features
Register here: https://www.townscript.com/e/java8-refactoring
ganesh@codeops.tech @GSamarthyam
www.codeops.tech slideshare.net/sgganesh
+91 98801 64463 bit.ly/ganeshsg

Refactoring for Software Design Smells - Tech Talk