REFACTOR

WHAT IS REFACTORING?

Refactoring consists in modifying software to improve its readibility, maintainability and extensibility without changing what it actually does

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

verb: to restructure software by applying a series of refactorings without changing its observable behavior

MARTIN FOWLER DEFINITION (AUTHOR OF REFACTORING.COM)

Refactoring isn't another word for cleaning up code - it specifically defines one technique for improving the health of a code-base. I use "restructuring" as a more general term for reorganizing code that may incorporate other techniques.

WHY REFACTOR?

It’s like I want to go 100 miles east but instead of just traipsing through the woods, I’m going to drive 20 miles north to the highway and then I’m going to go 100 miles east at three times the speed I could have if I just went straight there. When people are pushing you to just go straight there, sometimes you need to say, “Wait, I need to check the map and find the quickest route.” The preparatory refactoring does that for me.

Keep the external quality but improve the internal quality

Keep the external quality but improve the internal quality

Refactoring involves changing things, hence it can (and so it will!) introduce problems.

 

Be ready for them, take the opportunity to automate tests, do it in small incremental steps, etc.

Refactoring Risks

Keep the external quality but improve the internal quality

EXAMPLES????

Keep the external quality but improve the internal quality

Extract code to new/other method/classes

Move methods

Rename methods/objects/attributes

add attributes to classes/methods

Change Classes Structure

EXAMPLES

Example 1 - Consolidate Conditional Expression

Example 1 - Consolidate Conditional Expression

Example 2 - Decompose Conditionals

Example 3

Move a method from class A to class B if uses/is being used by more features in class B

Example 4

Introduce Null Object

Imagine in your software you are always checking if instances of an object are null:

Customer c = findCustomer(...);

...

if (customer == null) {
  name = "occupant";
} else {
  name = customer.getName();
}

...

if (customer == null) {
...
}

Duplicating code, makes it more difficult to be maintained, more complex, more difficult to be understood

Example 4

Introduce Null Object

public class NullCustomer extends Customer {

   public String getName() {
	return “occupant”
}

------------------------------------------------------------

Customer c = findCustomer()
name = c.getName()

Example 5

Switch Statements

  • switch statements are very rare in properly designed object-oriented code
  • Therefore, a switch statement is a simple and easily detected “bad smell”
  • Of course, not all uses of switch are bad
    • Switch statement should not be used to distinguish between various kinds of objects.
  • There are several well-defined refactorings for this case.
    • The simplest is the creation of subclasses

 

Example 5

Switch Statements

class Animal {
   final int MAMMAL = 0, BIRD = 1, REPTILE = 2;
   int myKind;  // set in constructor
   ...
   String getSkin() {
      switch (myKind) {
         case MAMMAL: return "hair";
         case BIRD: return "feathers";
         case REPTILE: return "scales";
         default: return "integument";
      }
   }
}

Example 5

Switch Statements

class Animal {
   final int MAMMAL = 0, BIRD = 1, REPTILE = 2;
   int myKind;  // set in constructor
   ...
   String getSkin() {
      switch (myKind) {
         case MAMMAL: return "hair";
         case BIRD: return "feathers";
         case REPTILE: return "scales";
         default: return "integument";
      }
   }
}
class Animal {
     String getSkin() { return "integument"; }
}
class Mammal extends Animal {
     String getSkin() { return "hair"; }
}
class Bird extends Animal {
     String getSkin() { return "feathers"; }
}
class Reptile extends Animal {
     String getSkin() { return "scales"; }
}
- Adding a new animal type, such as Amphibian, does not require revising and recompiling existing code

- Mammals, birds, and reptiles are likely to differ in other ways, and we’ve already separated them out (so we won’t need more switch statements)

- We’ve gotten rid of the flags we needed to tell one kind of animal from another

- Basically, we’re now using Objects the way they were meant to be used

Advantages:

A lot of examples

Identifying aspects to refactor

"Bad Smells"

Bad Smells: is a term coined by Martin Fowler

Developing Stinky Code

BAD SMELLS - I

  • DUPLICATED CODE: Bad because you need to mantain the code as many times as it's duplicated
  • LONG METHOD: Bad because they are more difficult to be understood, more error prone, etc.
  • LARGE CLASS: If a class is doing too much, OO is useless.
  • LONG PARAMETER LIST: Hard to understand
  • DATA CLASS: Class without behaviour implementation

BAD SMELLS - II

  • DIVERGENT CHANGES / SHOTGUN SURGERY: Two sides of the coin:
    • No matter what you need to change in your code, a class must be always modified.
    • One change/new feature requires changing a lot of things in different places.
  • FEATURE ENVY: Method is more interested in a class than in its own class.
  • REPEATED SWITCH STATEMENTS: Symptom of not using properly OO programming

 

https://sourcemaking.com/refactoring/smells

Bad Smells Video - I

Bad Smells Video - II

Develop your nose

https://sourcemaking.com/refactoring/smells

Choose one group and investigate some possible bad-smells

A "complete" example

5.D.1 and 5.D.2

DETECTING BAD SMELLS

HOW CAN YOU DETECT THEM?

REMEMBER THIS IS ABOUT INTERNAL QUALITY!

CODE REVIEWS

CODE ANALYSIS

DEFECT ANALYSIS

STATIC ANALYSIS TOOLS CAN HELP US 

 

(EXAMPLE: LINTERS)

MAKING IT SMELL WELL

There are a lot patterns/catalogs

Have a look at them, but the most important thing is to use common sense

... and practice a lot!

... and tools can also help us

REFACTOR

By Daniel Coloma

REFACTOR

  • 750