Wednesday, November 28, 2012

Refactoring › Composing Methods -Extract Method

  • You have a code fragment that can be grouped together.

Turn the fragment into a method whose name explains the purpose of the method.

Example: No Local Variables

before
 // print banner
    System.out.println ("**************************");
    System.out.println ("***** Customer Owes ******");
    System.out.println ("**************************");


after

printBanner();

void printBanner() {
    // print banner
    System.out.println ("**************************");
    System.out.println ("***** Customer Owes ******");
    System.out.println ("**************************");
}

http://sourcemaking.com/refactoring/extract-method



  • The Extract Method refactoring has the following limitations:


    Refactoring does not work with multiple output values in automatic mode. You have to change your code before applying the refactoring.
    Refactoring does not work for a code fragment which conditionally returns from the containing method and is not placed at the end of it.

before (eclipse)

  public class ExtractMethod1 {

public static void main(String[] args) {
method1();
}



 static void method1() {
   int a=1;
   int b=2;
   int c=a+b;
   int d=a+c;
}
}




after (eclipse)

public class ExtractMethod1 {

public static void main(String[] args) {

method1();
}



 static void method1() {
   getSum();
}



private static void getSum() {
int a=1;
int b=2;
int c=a+b;
int d=a+c;
}
}


In Eclipse you select the code fragment you want to refactor,right click,refactor and extract method


before (IntelliJ IDEA 11.1)

  public class ExtractMethod1 {

public static void main(String[] args) {
method1();
}



 static void method1() {
   int a=1;
   int b=2;
   int c=a+b;
   int d=a+c;
}
}


after (IntelliJ IDEA 11.1)

public class ExtractMethod1 {


public static void main(String[] args) {

method1();
}



 static void method1() {
   int a=1;
int b=2;
int c=add(a,b);
int d=add(a,c);
}


private static int add(int a,int b) {
return a+b;
}
}



before (IntelliJ IDEA 11.1)

ArrayList method2()
{
String[] strings={"a","b","c","d"};
ArrayList list=new ArrayList();

for (int i = 0; i < strings.length; i++) {
list.add(strings[i]);
}
return list;
}

}


after (IntelliJ IDEA 11.1)

private ArrayList add(String[] strings)
{
ArrayList list=new ArrayList();

for (int i = 0; i < strings.length; i++) {
list.add(strings[i]);
}
return list;
}


http://www.jetbrains.com/idea/webhelp/extract-method.html#h2example



  • Extract Method


The Extract Method refactoring allows you to select a block of code and convert it to a method. Eclipse automatically infers the method arguments and return types.
This is useful when a method is too big and you want to subdivide blocks of it into different methods. It is also useful if you have a piece of code that is reused across many methods. When you select one of those blocks of code and do a refactoring, Eclipse finds other occurrences of that block of code and replaces it with a call to the new method.

Listing 3. Before Extract Method refactoring

@Override
public Object get(Object key)
{
TimedKey timedKey = new TimedKey(System.currentTimeMillis(), key);
Object object = map.get(timedKey);

if (object != null)
{
/**
* if this was removed after the 'get' call by the worker thread
* put it back in
*/
map.put(timedKey, object);
return object;
}

return null;
}



Listing 4. After Before Extract Method refactoring

@Override
public Object get(Object key)
{
TimedKey timedKey = new TimedKey(System.currentTimeMillis(), key);
Object object = map.get(timedKey);

return putIfNotNull(timedKey, object);
}

private Object putIfNotNull(TimedKey timedKey, Object object)
{
if (object != null)
{
/**
* if this was removed after the 'get' call by the worker thread
* put it back in
*/
map.put(timedKey, object);
return object;
}

return null;
}
http://www.ibm.com/developerworks/opensource/library/os-eclipse-refactoring/index.html

Refactoring


Defining Refactoring
 
 
    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.

The other usage of refactoring is the verb form
    Refactor (verb): to restructure software by applying a series of refactorings without changing its observable behavior.

“Is refactoring just cleaning up code?” In a way the answer is yes, but I think refactoring goes further because it provides a technique for cleaning up code in a more efficient and controlled manner

 the purpose of refactoring is to make the software easier to understand and modify.
 Only changes made to make the software easier to understand are refactorings
 Like refactoring, performance optimization does not usually change the behavior of a component (other than its speed); it only alters the internal structure
 the purpose is different. Performance optimization often makes code harder to understand, but you need to do it to get the performance you need.
 The software still carries out the same function that it did before

 When you use refactoring to develop software, you divide your time between two distinct activities: adding function and refactoring

 When you add function, you shouldn’t be changing existing code; you are just adding new capabilities. You can measure your progress by adding tests and getting the tests to work
 When you refactor, you make a point of not adding function; you only restructure the code. You don’t add any tests (unless you find a case you missed earlier)

 http://sourcemaking.com/refactoring/defining-refactoring




Why Should You Refactor?
The harder it is to see the design in the code, the harder it is to preserve it, and the more rapidly it decays. Regular refactoring helps code retain its shape.
By eliminating the duplicates, you ensure that the code says everything once and only once, which is the essence of good design.

Refactoring Makes Software Easier to Understand
Refactoring helps you to make your code more readable.
Ralph Johnson describes these early refactorings as wiping the dirt off a window so you can see beyond.
http://sourcemaking.com/refactoring/why-should-you-refactor


Refactoring Helps You Program Faster
When I talk about refactoring, people can easily see that it improves quality. Improving design, improving readability, reducing bugs, all these improve quality. But doesn’t all this reduce the speed of development?
the whole point of having a good design is to allow rapid development. Without a good design, you can progress quickly for a while, but soon the poor design starts to slow you down.
http://sourcemaking.com/refactoring/refactoring-helps-you-find-bugs


When Should You Refactor?
In my view refactoring is not an activity you set aside time to do. Refactoring is something you do all the time in little bursts

The Rule of Three
he first time you do something, you just do it.
The second time you do something similar, you wince at the duplication, but you do the duplicate thing anyway.
The third time you do something similar, you refactor.

Refactor When You Add Function
The most common time to refactor is when I want to add a new feature to some software
This code may have been written by someone else, or I may have written it
 Whenever I have to think to understand what the code is doing, I ask myself if I can refactor the code to make that understanding more immediately apparent

 I look at the design and say to myself, “If only I’d designed the code this way, adding this feature would be easy.” In this case I don’t fret over my past misdeeds—I fix them by refactoring

 Refactor When You Need to Fix a Bug
 As I look at the code trying to understand it, I refactor to help improve my understanding.
 if you do get a bug report, it’s a sign you need refactoring, because the code was not clear enough for you to see there was a bug


Refactor As You Do a Code Review
Reviews help more experienced developers pass knowledge to less experienced people
My code may look clear to me but not to my team.
This idea of active code review is taken to its limit with the Extreme Programming [Beck, XP] practice of Pair Programming

Why Refactoring Works
Kent Beck

Programs have two kinds of value: what they can do for you today and what they can do for you tomorrow. Most times when we are programming, we are focused on what we want the program to do today. Whether we are fixing a bug or adding a feature, we are making today’s program more valuable by making it more capable

If you can get today’s work done today, but you do it in such a way that you can’t possibly get tomorrow’s work done tomorrow, then you lose.

http://sourcemaking.com/refactoring/when-should-you-refactor


Changing Interfaces
Something that is disturbing about refactoring is that many of the refactorings do change an interface. Something as simple as Rename Method is all about changing an interface. So what does this do to the treasured notion of encapsulation?



You should also use the deprecation facility in Java to mark the code as deprecated. That way your callers will know that something is up.
A good example of this process is the Java collection classes. The new ones present in Java 2 supersede the ones that were originally provided

When Shouldn’t You Refactor?
There are times when you should not refactor at all. The principle example is when you should rewrite from scratch instead. There are times when the existing code is such a mess that although you could refactor it, it would be easier to start from the beginning.

The other time you should avoid refactoring is when you are close to a deadline. At that point the productivity gain from refactoring would appear after the deadline and thus be too late

http://sourcemaking.com/refactoring/problems-with-refactoring