78
TechDiscuss.net Shaunak Sontakke Code Smells & Refactoring Those Smells

Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

  • Upload
    others

  • View
    13

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Code Smells & Refactoring Those Smells

Page 2: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Shaunak Sontakke

● Bachelor of Engineering, MBA in Systems

● Software Engineer @ Entrata

● Full Stack Developer for 13 years, HusBand for 6 years and Dad for 4 years

● Passionate about clean architecture, clean code, pragmatic development

● Love reading/listening Self-Help Books, Developer Podcasts

● Blog: TechDiscuss.net. Email: [email protected]

Page 3: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Hello Everyones,

Todays are a great day. I is happy because we are learning new thing’s.

Page 4: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Code Smells

● Deeper problems

● Not bugs, nor errors

● Possibly○ Weakness○ Defects○ Inefficiency○ Design principles violation

● Ignore? Sure for cascading failures

● Agile software development term

● Code Smell Catalog gives you vocabulary in code review discussions

● Code Smells vs Anti-Pattern

Page 5: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Code Smells Catalog

1. Alternative classes w/ different interfaces

2. Comments

3. Data class

4. Data clumps

5. Dead code

6. Divergent change

7. Duplicated code

8. Feature envy

9. Inappropriate intimacy

10. Incomplete library client

11. Large class

12. Lazy class

13. Long method

14. Long parameter list

15. Message chains

16. Middle man

17. Parallel inheritance hierarchies

18. Primitive obsession

19. Refused bequest

20. Shotgun surgery

21. Speculative generality

22. Switch statements

23. Temporary field

Page 6: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Code Smells Catalog

1. Alternative classes w/ different interfaces

2. Comments

3. Data class

4. Data clumps

5. Dead code

6. Divergent change

7. Duplicated code

8. Feature envy

9. Inappropriate intimacy

10. Incomplete library client

11. Large class

12. Lazy class

13. Long method

14. Long parameter list

15. Message chains

16. Middle man

17. Parallel inheritance hierarchies

18. Primitive obsession

19. Refused bequest

20. Shotgun surgery

21. Speculative generality

22. Switch statements

23. Temporary field

Page 7: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Code Smells Catalog

1. Long method

2. Large class

3. Data clumps

4. Long parameter list

5. Primitive obsession

1. Alternative classes w/ different interfaces

2. Refused bequest

3. Switch statements

4. Temporary field

1. Divergent change

2. Shotgun surgery

3. Parallel inheritance hierarchies

1. Feature envy

2. Inappropriate intimacy

3. Message chains

4. Middle man

1. Comments

2. Data class

3. Dead code

4. Duplicated code

5. Lazy class

6. Speculative generality

Blo

aters

Disp

ensab

lesC

ou

plers

Ch

ange

Preven

ters

Ob

ject- O

rientatio

n

Ab

users

Page 8: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Code Smell Groups

Change Preventers

If you want to change something in one place you have to

make many changes in other places too

Excessive coupling between classes

Couplers Object-Orientation Abusers

Incomplete or incorrect

implementation of OOP

Bloaters

Grown to a large size

Dispensables

Absence of these would make the code

clean and improve code readability

Page 9: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Long method

● Ask questions if the method is more than 10 lines

● Probably violating design principles like SRP, KISS

Bloaters

Grown to a large size

Page 10: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Long method

Large class

● Class doing too many things

● Too many member variables

● Breeding ground for duplicate code

Bloaters

Grown to a large size

Page 11: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Data clumps

Long method

Large class

● Like children - enjoy hanging around in groups

● Same set of variables seen together

● name_first-name_last, start_date-end_date

Bloaters

Grown to a large size

Page 12: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Long method

Long parameter list

Large class

Data clumps

● More parameters ~ doing more things

● Another object hiding there

● SonarQube defaults: 4 is good

● Uncle Bob’s Clean Code: More than 3 requires

special justification

function doSomething($param1, $param2, $param3, $param4, $param5) { ...}

Bloaters

Grown to a large size

Page 13: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Long method

Primitive obsession

Long parameter list

Large class

Data clumps

● Developers prefer primitive types like floats for

money / currency classes, 2 string dates vs

DateRange object

● Developers reluctant to use small objects for small

tasks

Bloaters

Grown to a large size

Page 14: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Long method

Primitive obsession

Long parameter list

Large class

Data clumps

Bloaters

Grown to a large size

Page 15: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Divergent change

● Requires you to change multiple unrelated

methods when you want to do a small change in

class

● Adding a new coupon code functionality? Change

shipping function, printing function, order function,

etc.

● Applicable to changes in one class

Change Preventers

If you want to change something in one place you have to

make many changes in other places too

Page 16: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Divergent change

Shotgun surgery

● One reason for changing multiple classes

● Similar to Divergent Change

● Divergent change is many changes to one class,

while shotgun surgery is single change modifying

multiple classes

Change Preventers

If you want to change something in one place you have to

make many changes in other places too

Page 17: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Divergent change

Shotgun surgery

Parallel inheritance hierarchies

Departments

HR Marketing

Privilege

HRPrivileges MarketingPrivileges

Sales SalesPriveleges

Change Preventers

If you want to change something in one place you have to

make many changes in other places too

Page 18: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Divergent change

Shotgun surgery

Parallel inheritance hierarchies

Change Preventers

If you want to change something in one place you have to

make many changes in other places too

Page 19: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Feature envy

● Method is more interested in a another class

● Accesses more public features of other class than

its own

class SalaryCalculator {

public function calculateTotal() { $tax = $this->calculateTax(); }

public function calculateTax() { $employee = new Employee(); $grossTotal = $employee->getTotalPay()

+ $employee->getTotalBonus();

// ... return $tax; }}

Excessive coupling between classes

Couplers

Page 20: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Feature envy

Inappropriate intimacy

● Class touches internal fields and methods of

another class

● Compromises other class's encapsulation

class Customer { public function sendSms( $name, Contact $contact ) { $message = 'Hello '. $name; $message .= 'Contact:' . $contact->getPhoneNumber() . PHP_EOL; $message .= 'Email:' . $contact->getEmail() . PHP_EOL; }}Excessive coupling

between classes

Couplers

Page 21: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

● Class that uses another class’s method, which in

turn uses another class’s and so on

● Chain: Employee->EmployeeConfig->ConfigFeature envy

Inappropriate intimacy

Message chains

class Employee { public function getConfiguration() { $this->employeeConfig->getConfiguration(); }}class EmployeeConfig { public function getConfiguration() { $this->config->getConfiguration(); }}class Config { public function getConfiguration() { $this->loadConfiguration(); }}

Excessive coupling between classes

Couplers

Page 22: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

● Class exists just to delegate to another

● Is there a real purpose of this class?Feature envy

Middle man

Inappropriate intimacy

Message chains

class Customer {

/** @var Person */ private $person;

public function getNameFirst() { return $this->person->getNameFirst(); }

public function getNameLast() { return $this->person->getNameLast(); }

public function getGender() { return $this->person->getGender(); }}

Excessive coupling between classes

Couplers

Page 23: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Feature envy

Middle man

Inappropriate intimacy

Message chains

Excessive coupling between classes

Couplers

Page 24: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

<?php

class Animal {

public function getSpeed() { switch( $this->type ) { case LION: return $this->getBaseSpeed(); case PUMA: return $this->getBaseSpeed() * 1.5; case COUGAR: return ( $this->isTired ) ? 0 : $this->getBaseSpeed() * 2; default: return $this->getBaseSpeed(); } }}

Switch statements

// It’s not a smell when its in factoryclass AnimalFactory {

public static function getAnimal( $animalType ) { switch( $animalType ) { case LION: return new Lion(); case PUMA: return new Puma(); case COUGAR: return new Cougar(); default: return new Lion(); }

}}

● Same switch cases scattered at multiple places

● Addition of new case in such switch

Object-Orientation Abusers

Incomplete or incorrect

implementation of OOP

Page 25: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Switch statements

Temporary field

● Member variables are set only in certain

circumstances. Otherwise they are empty

● Understanding such variable existence can drive

you nuts

● Not all member variables are required for every

method, but they are just present

Object-Orientation Abusers

Incomplete or incorrect

implementation of OOP

Page 26: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

● Class inherits from a base class but doesn't use any

of the inherited fields or methodsSwitch statements

Temporary field

Refused bequest

class Animal {

private $numberOfLegs;

public function getNumberOfLegs() { return $this->numberOfLegs; }}

class Cat extends Animal {

public function getNumberOfLegs() { parent::getNumberOfLegs(); }}

class GoldFish extends Animal {

public function getNumberOfLegs() { throw NotImplementedException(); }}

Object-Orientation Abusers

Incomplete or incorrect

implementation of OOP

Page 27: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

● Two classes perform identical functions but have

different signatures.

● Difference in interfaces of similar classesSwitch statements

Alternative classes w/ different interfaces

Temporary field

Refused bequest

Object-Orientation Abusers

Incomplete or incorrect

implementation of OOP

Page 28: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Switch statements

Alternative classes w/ different interfaces

Temporary field

Refused bequest

Object-Orientation Abusers

Incomplete or incorrect

implementation of OOP

Page 29: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Comments

● Method is filled with explanations

● When you feel like writing a comment, first try "to

refactor so that the comment becomes

superfluous"

● Having Comments vs. Need Comments

Dispensables

Absence of these would make the code

clean and improve code readability

Page 30: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Comments

Duplicated code

Dispensables

Absence of these would make the code

clean and improve code readability

Page 31: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Comments

Duplicated code

Lazy class

● Class doesn’t do enough to earn your attention

● May be a result of previous refactoring

● Added for future development but was never used

Dispensables

Absence of these would make the code

clean and improve code readability

Page 32: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Comments

Data class

Duplicated code

Lazy class

● Members, getters, setters

● Dump data holder

● Beware of DTO or POPO

Dispensables

Absence of these would make the code

clean and improve code readability

Page 33: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Comments

Dead code

Data class

Duplicated code

Lazy class

Dispensables

Absence of these would make the code

clean and improve code readability

● Requirements changed - nobody had time to clean

up the old code

● Unreachable code in lengthy conditionals

Page 34: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Comments

Dead code

Data class

Duplicated code

Lazy class

Speculative generality

● Premature Generalization

● Add parameters - somebody would need it in future

Dispensables

Absence of these would make the code

clean and improve code readability

Page 35: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Comments

Dead code

Data class

Duplicated code

Lazy class

Speculative generality

Dispensables

Absence of these would make the code

clean and improve code readability

Page 36: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Refactoring

● Systematic approach for restructuring the code

● Art of improving the internal structure of code without modifying observable behavior

● Small restructuring, less likely to go wrong

● Easy to learn techniques

● Done when code is working

● There are around 300 formal refactoring technique

● Building a strong house vs building it faster

Page 37: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

What is not refactoring

● Adding new features

● Bug fixing

● Performance improvement

● Replacing large chunks of code

● Optimisation vs Refactoring

Page 38: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Good time for Refactoring

● Cyclomatic Complexity

● Code Smell○ Duplicate code….refactor!○ Method at wrong place….refactor!○ Function doing more than its name….refactor!○ Lengthy function….refactor!○ Conditions are lengthy….refactor!○ If it stinks….refactor!

● Rule of Three

○ When doing it first time, just do it

○ 3rd time you do same, you refactor

○ 2nd time, you wince duplication, but do the duplication anyways

Page 39: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Good time for Refactoring

● Micro-Refactoring

● Proactive Refactoring: Managers appreciate when we eliminate the need for special refactoring

tasks

● Refactor during any feature type of task○ PhpUnit Test comes handy○ Tasks would be QAed○ Would take more time? Talk to manager ○ // @FIXME and // @TODO comments

● Refactor as you do a code review

● When adding new UnitTests - not mockable code

Page 40: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

When not to refactor

● When you should rewrite from scratch

● Remember, code has to work before you start

● When you are close to deadline

Page 41: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Extract Methodfunction printInvoice( Order $order ) { $invoiceLines = [];

// prints header $invoiceLines[] = '--------------'; $invoiceLines[] = 'Invoice'; $invoiceLines[] = '--------------';

// Line Items if( $order->getTotal() <> 0 ) { $invoiceLines[] = 'Details'; } else { $invoiceLines[] = 'Total:' . $order->getTotal(); }

print_r( $invoiceLines );

}

function printInvoice( Order $order ) { $invoiceLines = []; $invoiceLines = generateHeaders( $invoiceLines ); $invoiceLines = generateInvoiceBody( $order, $invoiceLines );

print_r( $invoiceLines );

}

function generateHeaders( array $invoiceLines ) { $invoiceLines[] = '--------------'; $invoiceLines[] = 'Invoice'; $invoiceLines[] = '--------------';

return $invoiceLines;}

function generateInvoiceBody( Order $order, array $invoiceLines ) { if( $order->getTotal() <> 0 ) { $invoiceLines[] = 'Details'; } else { $invoiceLines[] = 'Total:' . $order->getTotal(); }

return $invoiceLines;}

Page 42: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Duplicated code

2. Comments

3. Data class

4. Long method

5. Feature envy

6. Message chains

7. Switch statements

Page 43: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Inline Methodfunction applyDiscounts( $order ) {

// .. . if( getOrderTotal( $order ) > 500 ) { $shippingAmount = 0; }

}

function getOrderTotal( $order ) { return $order->getOrderTotal();}

function applyDiscounts( $order ) {

if( $order->getOrderTotal() > 500 ) { $shippingAmount = 0; }

}

Page 44: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Speculative generality

Page 45: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Extract Variablefunction handleLogin( $request ) {

if( isset( $request->getAttribute( 'username' ) ) && 'admin' == $request->getAttribute( 'username' ) ) { $attachmentPath = __DIR__ . '/' . $request->getAttribute( 'username' ) . '.txt'; }

}

function handleLogin( $request ) {

$username = $request->getAttribute( 'username' );

if( isset( $username ) && 'admin' == $username ) { $attachmentPath = __DIR__ . '/' . $username . '.txt'; }

}

Page 46: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Duplicated code

2. Comments

Page 47: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Inline Tempfunction calculateOrderTotal( $order ) { $total = $order->getTotal() + $order->getShippingAmount(); return $total;}

function calculateOrderTotal( $order ) { return $order->getTotal() + $order->getShippingAmount();}

Page 48: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Helps in these refactoring

1. Extract Method

2. Replace Temp with Query

Page 49: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Replace Temp with Queryfunction calculateDiscount( $order ) {

$itemTotal = $this->quantity * $this->itemPrice;

if( $itemTotal >= 500 ) { return $itemTotal * 0.02; } else { return $itemTotal; }}

function calculateDiscount( $order ) {

if( getItemTotal() >= 500 ) { return getItemTotal() * 0.02; } else { return getItemTotal(); }}

function getItemTotal() { return $this->quantity * $this->itemPrice;}

● Balance between Performance vs Readability● Helps in UnitTesting

Page 50: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Long method

2. Duplicated code

Page 51: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Move Methodclass SalaryCalculator {

public function calculateTotal() { // ...

$tax = $this->calculateTax(); }

public function calculateTax() { $employee = new Employee(); $grossTotal = $employee->getTotalPay()

+ $employee->getTotalBonus();

// ... return $tax; }}

class Employee {

public function getTotalPay() {

}

public function getTotalBonus() {

}}

class SalaryCalculator {

public function calculateTotal() { // ... $employee = new Employee(); $tax = $employee->calculateTax(); }

}

class Employee {

public function getTotalPay() {

}

public function getTotalBonus() {

}

public function calculateTax() {

$grossTotal = $this->getTotalPay() + $this->getTotalBonus();

// ... return $tax; }}

Page 52: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Shotgun surgery

2. Parallel inheritance hierarchies

3. Feature envy

4. Message chains

5. Inappropriate intimacy

6. Switch statements

7. Data class

Page 53: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Move Fieldclass Car {

/** @var Driver */ public $driver;

public function useNOS() { $this->driver->currentSpeed; }}

class Driver { public $currentSpeed;

}

class Car {

public $currentSpeed;

public function useNOS() { $this->currentSpeed; }}

class Driver {

}

Page 54: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Shotgun surgery

2. Parallel inheritance hierarchies

3. Inappropriate intimacy

Page 55: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Extract Classclass Person {

private $name; private $officeAreaCode; private $officeNumber;

public function getTelephoneNumber() {

}}

class Person {

private $name;

}

class TelephoneNumber {

private $officeAreaCode; private $officeNumber;

public function getTelephoneNumber() {

}}

Page 56: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Duplicated code

2. Large class

3. Divergent change

4. Data clumps

5. Primitive obsession

6. Temporary field

7. Inappropriate intimacy

Page 57: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Inline Classclass Shape {

/** @var \Color */ private $color;

public function draw() { $color = $this->color->getFavoriteColor(); }

}

class Color {

private $favoriteColor = 'blue';

public function getFavoriteColor() { return $this->favoriteColor; }}

class Shape {

private $favoriteColor = 'blue';

public function draw() { $color = $this->favoriteColor; }

}

Page 58: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Shotgun surgery

2. Lazy class

3. Speculative generality

Page 59: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Replace Array with Object$record = [];$record[0] = 'BYU';$record[1] = 20;

$record = new Team();$record->setName( 'BYU' );$record->setWins( 20 );

Page 60: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Primitive obsession

Page 61: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Decompose Conditional

if( ( $orderTotal >= 100 || $quantity > 5 ) && $orderDate >= SALE_START && $orderDate <= SALE_END ) { $discountPercent = 0.05;}

if( isDiscountApplicable() ) { $discountPercent = 0.05;}

function isDiscountApplicable() { return ( $orderTotal >= 100 || $quantity > 5 ) && $orderDate >= SALE_START && $orderDate <= SALE_END;}

Page 62: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Long method

Page 63: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Consolidate Conditional Expressionfunction disabilityAmount() { if( $this->seniority < 2 ) { return 0; } if( $this->monthsDisabled > 12 ) { return 0; } if( $this->isPartTime ) { return 0; } // compute the disability amount...

function disabilityAmount() { if( !$this->isEligibleForDisability() ) { return 0; } // compute the disability amount...

Page 64: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Duplicated code

Page 65: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Replace Conditional with Polymorphismclass Animal {

public function getSpeed() { switch( $this->type ) { case LION: return $this->getBaseSpeed(); case PUMA: return $this->getBaseSpeed() * 1.5; case COUGAR: return ( $this->isTired ) ? 0 : $this->getBaseSpeed() * 2; default: return $this->getBaseSpeed(); } }}

abstract class Animal {

abstract function getSpeed();}

class Lion extends Animal {

public function getSpeed() { return $this->getBaseSpeed(); }}

class Cougar extends Animal {

public function getSpeed() { return ( $this->isTired ) ? 0 : $this->getBaseSpeed() * 2; }}

$speed = $wildAnimal->getSpeed();

Page 66: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Switch statements

Page 67: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Introduce Null Objectclass Logger {

public function error( $message ) { if( ENV == 'production' ) { echo 'RED:' . $message; } else { return; } }

public function alert( $message ) { if( ENV == 'production' ) { echo 'YELLOW:' . $message; } else { return; } }}

class NullLogger {

public function error( $message ) { return NULL; }

public function alert( $message ) { return NULL; }}

class Logger {

public function error( $message ) { echo 'RED:' . $message; }

public function alert( $message ) { echo 'YELLOW:' . $message; }}

if( ENV == 'production' ) { $logger = new Logger();} else { $logger = new NullLogger();}

Page 68: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Switch statements

2. Temporary field

Page 69: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Parameterize Methodclass Car {

public function shiftToDrive() {

}

public function shiftToNeutral() {

}

public function shiftToReverse() {

}}

class Car {

public function shift( $position ) {

}}

Page 70: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Duplicated code

Page 71: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Preserve Whole Objectfunction formatName( $lastName, $firstName, $honorifics ) {

}

$lastName = $customer->getLastName();$firstName = $customer->getFirstName();$honorifics = $customer->getHonorifics();

echo formatName( $lastName, $firstName, $honorifics );

function formatName( Customer $customer ) {

}

echo formatName( $customer );

Page 72: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Primitive obsession

2. Long parameter list

3. Long method

4. Data clumps

Page 73: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Introduce Parameter Objectfunction formatPostalAddress( $addressLine1, $addressLine2, $state, $postalCode, $country ) {

}

class PostalAddress { private $addressLine1; private $addressLine2; private $state; private $postalCode; private $country;

// getters & setters}

function formatPostalAddress( PostalAddress $postalAddress ) {

}

Page 74: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Long parameter list

2. Data clumps

3. Primitive obsession

4. Long method

Page 75: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Pull Up Methodabstract class Vehicle {

}

class Car extends Vehicle {

private $numOfPassengers;

protected function printPassengers() { echo 'Number of passengers = ' . $this->numOfPassengers; }}

class Truck extends Vehicle {

private $numOfPassengers;

protected function printPassengers() { echo 'Number of passengers = ' . $this->numOfPassengers; }}

abstract class Vehicle {

private $numOfPassengers;

protected function printPassengers() { echo 'Number of passengers = ' . $this->numOfPassengers; }}

class Car extends Vehicle {

}

class Truck extends Vehicle {

}

Page 76: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Eliminates

1. Duplicated code

Page 77: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke

Further Reading. Questions?

● Refactoring: Improving the Design of Existing Code

● Refactoring.guru

● https://rules.sonarsource.com/php

Graphics - freepik.com

Page 78: Those Smells Code Smells & Refactoring€¦ · Code Smells Deeper problems Not bugs, nor errors Possibly Weakness Defects Inefficiency Design principles violation Ignore? Sure for

TechDiscuss.net Shaunak Sontakke