Android Refactoring

Post on 21-Jan-2018

455 views 0 download

Transcript of Android Refactoring

RefactoringGodfrey Nolan

"Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”

- Martin Fowler

Android Activities

9/25/17 Refactoring 3

Refactoring (noun): a change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.

"Refactor (verb): to restructure software by applying a series of refactorings without changing its observable behavior".

- Martin Fowler

Goals

9/25/17 Refactoring 5

"Technical debt ..[is]... the implied cost of additional rework caused by choosing an easy solution now instead of using a better approach that would take longer".

- Wikipedia

9/25/17 Refactoring 6

9/25/17 Refactoring 7

Keep it Objective

9/25/17 Refactoring 10

Keep it Objective

9/25/17 Refactoring 11

9/25/17 Refactoring 6

SonarCloud.io

9/25/17 Refactoring 13

SonarCloud.io

9/25/17 Refactoring 14

Metrics Reloaded

9/25/17 Refactoring 15

Metrics Reloaded

9/25/17 Refactoring 16

What’s the Process?

9/25/17 Refactoring 17

Refactor

9/25/17 Refactoring 18

Refactor

9/25/17 Refactoring 19

Rename

9/25/17 Refactoring 20

Move

9/25/17 Refactoring 21

Extract Method

9/25/17 Refactoring 22

Extract Layout

9/25/17 Refactoring 23

Pull Members Up

9/25/17 Refactoring 24

Pull Members Down

9/25/17 Refactoring 25

Convert Anonymous to Inner

9/25/17 Refactoring 26

Replace Temp with Query

9/25/17 Refactoring 27

Lets Begin

9/25/17 Refactoring 28

Lets Begin

9/25/17 Refactoring 29

Lets Begin – Kent Beck Rules

9/25/17 Refactoring 30

• Passes all the tests

• Reveals Intent

• Don’t repeat yourself

• Fewer Parts

Example 1

9/25/17 Refactoring 31

Example 1 – Extract Method

9/25/17 Refactoring 32

Example 1 – Rename

9/25/17 Refactoring 33

Example 1 – Move Method

9/25/17 Refactoring 34

Example 1 – Replace Temp With Query

9/25/17 Refactoring 35

Example 1 – Extract Method

9/25/17 Refactoring 36

Example 1 – Replace Temp With Query

9/25/17 Refactoring 37

Example 1 – Replace Temp With Query

9/25/17 Refactoring 38

Example 1 – Measure Once, Cut Twice

9/25/17 Refactoring 39

9/25/17 Refactoring 40

public String statement() {

double totalAmount = 0;

int frequentRenterPoints = 0;

Enumeration rentals = _rentals.elements();

String result = "Rental Record for " + getName() + "\n";

while (rentals.hasMoreElements()) {

double thisAmount = 0;

Rental each = (Rental) rentals.nextElement();

//determine amounts for each line

switch (each.getMovie().getPriceCode()) {

case Movie.REGULAR:

thisAmount += 2;

if (each.getDaysRented() > 2)

thisAmount += (each.getDaysRented() - 2) * 1.5;

break;

case Movie.NEW_RELEASE:

thisAmount += each.getDaysRented() * 3;

break;

case Movie.CHILDRENS:

thisAmount += 1.5;

if (each.getDaysRented() > 3)

thisAmount += (each.getDaysRented() - 3) * 1.5;

break;

}

// add frequent renter points

frequentRenterPoints++;

// add bonus for a two day new release rental

if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE) &&

each.getDaysRented() > 1) frequentRenterPoints++;

//show figures for this rental

result += "\t" + each.getMovie().getTitle() + "\t" +

String.valueOf(thisAmount) + "\n";

totalAmount += thisAmount;

}

//add footer lines

result += "Amount owed is " + String.valueOf(totalAmount) + "\n";

result += "You earned " + String.valueOf(frequentRenterPoints) +

" frequent renter points";

return result;

}

9/25/17 Refactoring 41

public String statement() {

String result = "Rental Record for " + getName() + "\n";

for (Rental each : rentals) {

// show figures for this rental

result += "\t" + each.getMovie().getTitle() + "\t" + each.getCharge() + "\n";

}

// add footer lines

result += "Amount owed is " + getTotalCharge() + "\n";

result += "You earned " + getTotalFrequentRenterPoints() + " frequent renter points";

return result;

}

private double getTotalCharge() {

double totalCharge = 0;

for (Rental each : rentals) {

totalCharge += each.getCharge();

}

return totalCharge;

}

private int getTotalFrequentRenterPoints() {

int totalFrequentRenterPoints = 0;

for (Rental each : rentals) {

totalFrequentRenterPoints += each.getFrequentRenterPoints();

}

return totalFrequentRenterPoints;

}

9/25/17 Refactoring 42

double getCharge(int numberOfDaysRented) {

double result = 2;

if (numberOfDaysRented > 2) {

result += (numberOfDaysRented - 2) * 1.5;

}

return result;

}

public void setPriceCode(int priceCode) {

switch (priceCode) {

case REGULAR:

price = new RegularPrice();

break;

case CHILDRENS:

price = new ChildrensPrice();

break;

case NEW_RELEASE:

price = new NewReleasePrice();

break;

default:

throw new IllegalArgumentException("illegal price code");

}

}

Example 2 – Convert app to MVP

9/25/17 Refactoring 43

Example 2 – Extract Delegate

9/25/17 Refactoring 44

Example 2 – Create Interface

9/25/17 Refactoring 45

Example 2 – Fix Activity

9/25/17 Refactoring 46

Example 2 – Fix Presenter

9/25/17 Refactoring 47

Example 3

9/25/17 Refactoring 48

Example 4

9/25/17 Refactoring 49

Lessons Learned

9/25/17 Refactoring 50

• Default Android design pattern is Ball of Mud

• Always create unit tests

• Use the metrics as a guide not as a mandate

• Measure early, measure often

• Think twice before you do a complete rewrite

Resources

• https://dev.to/rly

• http://www.mikamantyla.eu/BadCodeSmellsTaxonomy.html

• https://sonarcloud.io

• https://plugins.jetbrains.com/plugin/93-metricsreloaded

• https://github.com/LiushuiXiaoxia/AndroidStudioRefactor

• https://github.com/mroderick/refactoring-day

• https://www.safaribooksonline.com/library/view/developing-high-quality/9781771375580/

• https://medium.com/google-developers/viewmodels-a-simple-example-ed5ac416317e

9/25/17 Refactoring 51

Resources

9/25/17 Refactoring 52

Contact Info

godfrey@riis.com

@godfreynolan