refactoring for software design smells - tech talk

54
Refactoring for Software Design Smells Ganesh Samarthyam Entrepreneur; author; speaker [email protected] www.codeops.tech

Upload: ganesh-samarthyam

Post on 15-Apr-2017

222 views

Category:

Software


12 download

TRANSCRIPT

Refactoring for Software Design Smells

Ganesh SamarthyamEntrepreneur; author; [email protected]

–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 SolutionLocalDate 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)Bridgepa+ernb)Decoratorpa+ernc)Builderpa+ernd)Strategypa+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