Monday, February 29, 2016

Refactoring - parameterize method

When you have similar methods that are doing the same thing with the exception of a value, create one common method and pass the value.

Let's consider the following (ugly) class for a product:

class Product {
    var price: Float = 0
    
    func increasePriceBy5Percent() {
        price = price * 1.05
    }

    func increasePriceBy10Percent() {
        price = price * 1.1
    }

    func decreasePriceBy5Percent() {
        price = price * 0.95
    }
    
    func decreasePriceBy10Percent() {
        price = price * 0.9
    }
}

Let's take a test product and apply the methods:

let product = Product()
product.price = 100

product.increasePriceBy10Percent()
product.increasePriceBy5Percent()
product.decreasePriceBy10Percent()
product.decreasePriceBy5Percent()

We observe that the methods perform the same actions with the exception of the percentage value.

We can easily create just one method and receive the percentage as a parameter:

class Product {
    var price: Float = 0
       
    func applyPercentage(percentage:Float) {
        price = price * (1 + percentage)
    }
}

Our method calls become now:

product.applyPercentage(0.1)
product.applyPercentage(0.05)
product.applyPercentage(-0.1)
product.applyPercentage(-0.05)

Not only the code is cleaner, but it allows us more freedom. For example we can now apply an increase of 20%.

Friday, February 26, 2016

Refactoring: Lazy initialized attribute

Apply the type of refactoring when you have a number of objects that are initialized at the beginning of the program and that take some time to be created. This is causing some delay.

Instead of initializing them at the start, do it only when they are needed.

Let's consider the following example.

We have an object called SlowClass that takes some time to be created.

class SlowClass {
    init(index:Int){
        //this takes a long time
    }
}

We also have a repository that needs 1000 instances of this object

Prevent that

Thursday, February 25, 2016

Refactoring: Introduce Null object

Some of the objects in our programs can have null values (nil in Swift).

The functionality is different if we know the value for those objects or not, so we might need to check in multiple places for that. 

Let's consider the following code:

Wednesday, February 24, 2016

Refactoring in Swift: Introduce named parameter

Functions in Swift allow two types of parameters: named and unnamed.

When calling the function, for the named parameters their name has to be provided. For the unnamed, just the value of the parameter is sufficient.

Sometimes it makes sense to have unnamed parameters.

Pair programming

Tuesday, February 23, 2016

Refactoring - Introduce Assertion

An assertion in Swift is a run time check for a particular condition to be true. If that is the case, the execution of the program continues. If not, the code execution stops and the program is terminated.

Assertions are disabled when the app is built for production, so the users will not see their app crashing.

One can use assertion for verifying a condition is fulfilled in the case when the current implementation excepts it to be always fulfilled.

Bind Parameters for Database Queries by Martin Fowler



Whether you are writing SQL against a relational database, using an object-relational mapping framework, or querying a NoSQL database, you probably need to worry about how input data is used within your queries.

The database is often the most crucial part of any web application since it contains state that can't be easily restored. It can contain crucial and sensitive customer information that must be protected. It is the data that drives the application and runs the business. So you would expect developers to take the most care when interacting with their database, and yet injection into the database tier continues to plague the modern web application even though it's relatively easy to prevent!

read more here

Refactoring - extract template method

Use this refactoring method when different classes have one method that is performing the same steps but each step is different.

We can create a common method (a template method that is) in the super class and define each step in each class

Let's consider the following example:

Monday, February 22, 2016

Interesting suggestion


Refactoring - hide function

Just like human beings, the classes have some public and some private "parts". And as we know very well, the private business is better to stay private.

As a rule, it is good to make everything private to start with and only make something public if really needed.

Let's consider the following class:

Friday, February 19, 2016

When you think you are done...


Refactoring - extract surrounding method

Apply this refactoring when two or more methods are identical except a piece of code somewhere in the middle.

You can create a function to contain the common code that receives a closure or a function to deal with the difference in code.

Consider we have couple of functions as follows. One is displaying the squares and the other one the cubes for values between one and ten.

func printSquares() {
    print("---")
    for i in 1...10 {
        print (i*i)
    }
    print("---")
}

Thursday, February 18, 2016

Refactoring - Extract superclass

This refactoring is applied when different classes have similar functionality. In this case, the common code can be move into a new class that becomes the superclass for the other classes.

Consider a checking and a saving account:

class SavingAccount {
    func calculateInterest(){
    }
    
    func createStatement() {
    }
    
    func emailStatement(){
    }
}

class CheckingAccount {
    func calculateFee(){
    }
    
    func createStatement() {
    }
    
    func emailStatement(){
    }
}

While the classes are not identical, we notice some common functionality. 

We'll create another class, Account and extend the current class from it.

class Account {
    func createStatement() {
    }
    
    func emailStatement(){
    }
}

class SavingAccount: Account {
    func calculateInterest(){
    }
}

class CheckingAccount: Account {
    func calculateFee(){
    }
}

This makes the hierarchy more elegant and allows a simpler maintenance. Imagine if the emailStatement functionality needs to be changed, in our second example, we need to change it only in one place.

Wednesday, February 17, 2016

Refactoring - extract subsclass

In some instances, one class is providing functionality for only certain cases.

Assume there is a class to manage a bank account.

The class provides functionality for checking as well as for saving accounts but only the saving accounts bring interest to the owner.

class Account {
    //this function is called only for saving accounts
    func calculateInterest(){
        //....
    }
}

let checkingAccount = Account()
let savingAccount = Account()

Nothing prevents a user for calling checkingAccount.calculateInterest() and also get a result that might not be accurate or in the best case is zero.

The solution to prevent this is to create a sub class and move the specific functionality there:

class Account {
    //some functionality
}

class SavingAccount: Account {
    func calculateInterest(){
        //...
    }
}

let checkingAccount = Account()
let savingAccount = SavingAccount()

In this case, checkingAccount.calculateInterest() would raise a compilation error.

In general, each class should only have the functionality that allows to perform its duties and nothing more.

Tuesday, February 16, 2016

Refactoring - exact utility method

When working on a project, especially when multiple developers are involved, the same functionality might be duplicated in different classes.

This, is course, is not only a waste of bytes but it increases the chance of bugs and makes maintenance difficult.

The code needs to be merged and moved in the class that makes more sense or into a new class.

Consider the following two classes:

class User {
    func trim(s:String) -> String {
        return s.stringByTrimmingCharactersInSet(
            NSCharacterSet.whitespaceAndNewlineCharacterSet()
        )
    }
    //more functionality
}

class Product {
    func trimString(s:String) -> String {
        return s.stringByTrimmingCharactersInSet(
            NSCharacterSet.whitespaceAndNewlineCharacterSet()
        )
    }
    //more functionality
}


We notice that trim and trimString have the same functionality.

The first solution would be to create an utility class to include both functionality:

class Util {
    class func trim(s:String) -> String {
        return s.stringByTrimmingCharactersInSet(
            NSCharacterSet.whitespaceAndNewlineCharacterSet()
        )
    }
}

We defined it as a class function so we can simply call the function like follows:

Util.trim(" qqq \n\t")

A better solution is to create an extension to the class String:

extension String {
    func trim() -> String {
        return self.stringByTrimmingCharactersInSet(
            NSCharacterSet.whitespaceAndNewlineCharacterSet()
        )
    }
}

In this case we can simply call the trim functionality:

" qqq \n\t".trim()

Monday, February 15, 2016

Refactoring in Swift - Extract protocol

A protocol (also called interface in other languages) defines a blueprint of properties, functions and other functionality a class needs to follow.

It is used to define a certain type of classes.

Sometimes classes evolve and only after a while their common functionality becomes apparent.

Consider the following classes:

class Car {
    var make: String?
    var model: String?
    var mileage: Float?
    var numberOfDoors: Int?
    var maximumSpeed: Float?
    var horsePower: Float?
    var colour: UIColor?
}

class Motorcycle {
    var make: String?
    var model: String?
    var mileage: Float?
    var maximumSpeed: Float?
    var horsePower: Float?
    var colour: UIColor?
    var wheels: Int?
}

Because they are different classes, functionality that applies to both is difficult to write. For example, it is not easy to create an array of both cars and motorcycles and sort them by maximum speed.

We notice they have common functionality so we can extract a protocol containing it:

protocol Vehicle {
    var make: String? { get set }
    var model: String? { get set }
    var mileage: Float? { get set }
    var maximumSpeed: Float? { get set }
    var horsePower: Float? { get set }
    var colour: UIColor? { get set }
}

In this case, our classes will become:

class Car : Vehicle {
    var make: String?
    var model: String?
    var mileage: Float?
    var numberOfDoors: Int?
    var maximumSpeed: Float?
    var horsePower: Float?
    var colour: UIColor?
}

class Motorcycle : Vehicle {
    var make: String?
    var model: String?
    var mileage: Float?
    var maximumSpeed: Float?
    var horsePower: Float?
    var colour: UIColor?
    var wheels: Int?
}

A sorting function is now obvious:

func sortVehicle(vehicleArray:[Vehicle]) -> [Vehicle] {
    return vehicleArray.sort ({ $0.maximumSpeed < $1.maximumSpeed })
}

Here is some code to test it:


let v1 = Car()
v1.maximumSpeed = 100
let v2 = Motorcycle()
v2.maximumSpeed = 150
let v3 = Car()
v3.maximumSpeed = 140

var array1: [Vehicle]
array1 = [v1,v2,v3]

let array2 = sortVehicle(array1)

Friday, February 12, 2016

Refactoring - encapsulate downcast

Consider the following class hierarchy:

class Car {
    //....
}

class ElectricCar : Car {
    //...
}

We have a small database of cars:

var cars = [Car(), Car(), ElectricCar(), ElectricCar(), Car()]

And one function that is returning one electric car:

func findElectricCar() -> Car? {
    for car in cars {
        if car is ElectricCar {
            return car
        }
    }
    return nil
}

In our code, in multiple places we have to downcast the objects from Car to ElectricCar:

var electricCar1, electricCar2, electricCar3: ElectricCar

electricCar1 = findElectricCar() as! ElectricCar
electricCar2 = findElectricCar() as! ElectricCar
electricCar3 = findElectricCar() as! ElectricCar

This, of course, is useless as we know already findElectricCar is returning an Electric car.

To improve the code, we need to move the casting directly into the function

func findElectricCar() -> ElectricCar? {
    for car in cars {
        if car is ElectricCar {
            return (car as! ElectricCar)
        }
    }
    return nil
}

Now our code looks more elegant:

var electricCar1, electricCar2, electricCar3: ElectricCar

electricCar1 = findElectricCar()
electricCar2 = findElectricCar()
electricCar3 = findElectricCar() 

Thursday, February 11, 2016

Refactoring - Eagerly Initialized Attribute

A Fibonacci sequence has each element equal to the sum of the previous two elements.

The first two elements are 1 and 1 so the sequence shows like this:

1, 1, 2, 3, 5, 8, etc

Asked to implement a function to return one element of the series, a smarty pants developer thought to save some time at the initialization of the program and to use a lazy initialized variable:

var fibonacci = [Int]()
fibonacci.append(1)
fibonacci.append(1)

func getFibonacci(index:Int) -> Int {
    if index >= fibonacci.count {
        for i in fibonacci.count ... index {
            fibonacci.append(fibonacci[i-1] + fibonacci[i-2])
        }
    }
    return fibonacci[index]
}

This is interesting but not very straight forward. One needs to think a bit.

The developer realizes that in the current context, only the first 50 elements in the sequence are used.

So, thinking of the future developers who might try to understand what on earth his code is doing, he is simplifying the funtionality by initializing the elements just from the start:

var fibonacci = [Int]()
fibonacci.append(1)
fibonacci.append(1)

for i in 2...50 {
    fibonacci.append(fibonacci[i-1] + fibonacci[i-2])
}

We can even of further and simplify the code a but further, taking advantage of the Swift shortcut of initializing an array:

var fibonacci = [1,1]

for i in 2...50 {
    fibonacci.append(fibonacci[i-1] + fibonacci[i-2])
}

Wednesday, February 10, 2016

Refactoring - Collapse hierarchy

If a hierarchy of classes gets simplified over time, eventually it becomes so simple, that is not really needed. Then, it is time to collapse some classes.

Let's consider the following hierarchy:

class Car {
}

class RegularCar: Car {
}

class HybridCar: Car {
}

The government, in his wisdom, releases a new law to allow only hybrid cars in the market so our hierarchy becomes:

class Car {
}

class HybridCar: Car {
}

This is not useful anymore, so we can simply remove HybridCar and move all the functionality to the superclass, Car.

When to refactor or "if it stinks, change it"

Kent Beck and Martin Fowler described the need for refactoring in terms of smells. To quote them: "If it stinks, change it".

It seems Kent had a newborn daughter at the time, so that explains everything.

As there are many different situations when the code "stinks", Martin lists them in his "Refactoring" book.

Here is a list adapted and added for iOS and Swift world.

Tuesday, February 9, 2016

Refactoring - Decompose Conditional

Simple code is easier to understand and maintain. One of the aim of refactoring techniques is to be sure the code is as simple as it can be.

This refactoring can be applied in the case of a series of conditions that might be to difficult to follow and easy to get it wrong.

Let's write some code that is calculating the taxes one has to pay. In our example, there are 5 levels of tax, depending on the income and number of kids.

if (income < 1000) && (kids == 0) { //level 1
    tax = income * 0.2
} else if (income < 1000) && (kids > 0) { //level 2
    tax = income * 0.1
} else if (income < 2000) && (kids == 0) { //level 3
    tax = 200 + (income - 10000) * 0.3
} else if (income < 2000) && (kids > 0) { //level 4
    tax = 100 + (income - 1000) * 0.2
} else {
    tax = 400 + (income - 2000) * 0.4 //level 5
}

It is not easy to follow the code, let alone change. Imagine what would have happened if there were 20 levels instead of 5.

We can simplify it by extracting a function for each conditional and each branch:

if checkLevel1() {
    tax = computeTaxLevel1()
} else if checkLevel2() {
    tax = computeTaxLevel2()
} else if checkLevel3() {
    tax = computeTaxLevel3()
} else if checkLevel4() {
    tax = computeTaxLevel1()
} else {
    tax = computeTaxLevel5()
}

Of course, each of the function are defined as follows

func checkLevel1() -> Bool {
   return (income < 1000) && (kids == 0)
}

func computeTaxLevel1() -> Double {

    return income * 0.2
}

The other ones are similar.

Now the code is clear and also for changing one level, one knows exactly where to do it: in the function corresponding to that level.

Monday, February 8, 2016

Refactoring - Consolidate Duplicate Conditional Fragments

Apply this refactoring when the same code is duplicated in the branches of a if/else or switch statement.

Move the common code outside of the statement.

Let's consider the following code that is creating the full name using the first and last name:

var firstName, lastName: String?

//....

var fullName = ""
if firstName == nil {
    if lastName == nil {
        fullName = "unknown name"
        print(fullName)
    } else {
        fullName = lastName!
        print(fullName)
    }
} else {
    if lastName == nil {
        fullName = firstName!
        print(fullName)
    } else {
        fullName = firstName! + " " + lastName!
        print(fullName)
    }
}

We can easily notice that for each branch the full name is printed.

We can move it outside the branch as follows:

var fullName = ""
if firstName == nil {
    if lastName == nil {
        fullName = "unknown name"
    } else {
        fullName = lastName!
    }
} else {
    if lastName == nil {
        print(fullName)
    } else {
        fullName = firstName! + " " + lastName!
    }
}
print(fullName)

Friday, February 5, 2016

Refactoring - consolidate conditional expressions

This refactoring is applied when there are multiple conditional tests that have the same outcome. You can combine them in the same condition.

Consider the following piece of code that is checking if the length of a username is correct (that is between 5 and 20).

let username:String?

username = "test"

var lengthCorrect = true
if username == nil {
    lengthCorrect = false
} else if username?.characters.count < 5 {
    lengthCorrect = false
} else  if username?.characters.count > 20 {
    lengthCorrect = false
}

As you can see all the tests have the same outcome: length is incorrect

The first step would be to combine all the checks into the same if statement:

if (username == nil) || (username?.characters.count < 5) 
   || (username?.characters.count > 20) {
    lengthCorrect = false
}

Of course, the next step is to extract this code into its own function:

func checkUsernameLength(username:String?) -> Bool {
    return !((username == nil) || (username?.characters.count < 5) 
           || (username?.characters.count > 20))
}

Now, the code to check the the validity of the username is simply:

var lengthCorrect = checkUsernameLength(username)


Thursday, February 4, 2016

Refactoring - Replace Type Code with Polymorphism

This type of refactoring applies when a class has a property that represent a type of some kind and the code is depending on it. This usually manifests through if/else or switch statements.

Let’s continue the example of the Karateka but simplify it a bit.

Wednesday, February 3, 2016

Refactoring - Replace type code with enumeration

Karate is a Japanese style of martial arts that rewards its participant attaining a certain level of sport mastery with color belts.

Let's have a class for a Karateka, that is a Karate practitioner.

let kWhiteBelt = 0, kYellowBelt = 1, kOrangeBelt = 3 
let kGreenBelt = 4, kBlueBelt = 5, kBrownBelt = 6, kBlackBelt = 6

class Karateka {
    var name = ""
    var belt = kWhiteBelt
    
    func isBeginner () -> Bool {
        return belt == kWhiteBelt
    }
    
    func isMaster () -> Bool {
        return belt == kBlackBelt
    }
}

The code works fine but it is not an elegant one.

Tuesday, February 2, 2016

Refactoring: Replace magic numbers with constants

Magic numbers are values with unexplained meaning and multiple occurrences in the code, according to Wikipedia. Here is an example:

func validateUsername(username:String?) {
    if let username = username {
        let length = username.characters.count
        if length <= 3 {
            print("Username too short.")
            print("It needs to be longer than 3.")
        } else if length >= 10 {
            print("Username too long.")
            print("It needs to be shorter than 10.")
        } else {
            print("username valid")
        }
    } else {
        print("username cannot be nil")
    }
}

Monday, February 1, 2016

Refactoring: Change bidirectional association to unidirectional

In the previous post we analyzed how, sometime, adding another association between the objects can drastically improve performance and reduce the amount of code we need to write.

The situation can happen in reverse as well.

Consider the following example: