Refactoring - 예시[Example]

No Image

Extract Method

그룹으로 함께 묶을 수 있는 코드 조각이 있으면 코드의 목적이 잘 드러나도록 메소드의 이름을 지어 별도의 메소드로 뽑아낸다.

효과

  • 메소드가 잘 쪼개져 있을 때 다른 메소드에서 사용될 확률이 높아진다
  • 추상화 Level을 적절하게 유지할 수 있어 가독성이 좋아진다.
// Example Code
void printNesoy(String title, int age){
  printTableHead();

  System.out.println( "Nesoy title : " + title );
  System.out.println( "age : " + age );
}
// Refactoring Code
void printNesoy(String title, int age){
    printTableHead();
    printNesoyDetail(title, age);
}

void printNesoyDetail(String title, int age){
    System.out.println( "Nesoy title : " + title );
    System.out.println( "age : " + age );
}

Extract Class

두 개의 클래스가 해야 할 일을 하나의 클래스가 하고 있는 경우 새로운 클래스를 만들어서 관련 있는 필드와 메소드를 예전 클래스에서 새로운 클래스로 옮겨라.

효과

  • 클래스 하나의 크기가 작아짐으로써 클래스의 역할을 이해하기 쉽다.
// Example Code
class Nesoy {
    private String title;
    private int age;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAge() {
       return age + "나이";
    }

    public void setAge(int age) {
        this.age = age;
    }
}
// Refactoring Code
class Nesoy {
    private String title;
    private int age;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

class AgeWriter {
    public String getAgeFormat(int age){
       return age + "나이";
    }
}

Inline Class

클래스가 하는 일이 많지 않은 경우에는 그 클래스에 있는 모든 변수와 메소드를 다른 클래스로 옮기고 그 클래스를 제거하라.

효과

  • 너무 깊은 추상화 Level보단 적절한 추상화 Level을 통해 가독성을 높힌다.
// Example Code
int getRating() {
  return (moreThanFiveLateDeliveries()) ? 2 : 1;
}
boolean moreThanFiveLateDeliveries() {
  return _numberOfLateDeliveries > 5;
}
// Refactoring Code
int getRating() {
  return (_numberOfLateDeliveries > 5) ? 2 : 1;
}

Move Method

메소드가 자신이 정의된 클래스보다 다른 클래스의 기능을 더 많이 사용하고 있다면 이 메소드를 가장 많이 사용하고 있는 클래스에 비슷한 몸체를 가진 새로운 메소드를 만들어라. 그리고 이전 메소드는 간단한 위임으로 바꾸거나 완전히 제거하라

효과

  • 역할에 맞는 클래스에 메소드를 옮김으로써 클래스 행위에 대해 이해도를 높힐 수 있다.
// Example Code
class Project {
  Person[] participants;
}

class Person {
  int id;
  boolean participate(Project p) {
    for(int i=0; i<p.participants.length; i++) {
	  if (p.participants[i].id == id) return(true);
    }
    return(false);
  }
}
// Refactoring Code
class Project {
  Person[] participants;
  boolean participate(Person x) {
    for(int i=0; i<participants.length; i++) {
	  if (participants[i].id == x.id) return(true);
    }
    return(false);
  }
}

class Person {
  int id;
}

Move Field

필드가 자신이 정의된 클래스보다 다른 클래스에 의해 더 많이 사용되고 있다면 타겟 클래스(target class)에 새로운 필드를 만들고 기존 필드를 사용하는 모든 부분을 변경하라

효과

  • Move Method와 비슷한 맥락이다.

Introduce Explaining Variable[Extract Variable]

조건의 목적을 읽기 쉬운 변수의 이름으로 표현한다.

효과

  • 메소드로 구현하는 것보다 훨씬 간단하며 가독성면에서 강력하다.
// Example Code
if ( (platform.toUpperCase().indexOf("MAC") > -1) &&
     (browser.toUpperCase().indexOf("IE") > -1) &&
      wasInitialized() && resize > 0 )
// Refactoring Code
final boolean isMacOs     = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf("IE")  > -1;
final boolean wasResized  = resize > 0;

if (isMacOs && isIEBrowser && wasInitialized() && wasResized)

Remove Data Value with Object

추가적인 데이터나 동작이 필요로하는 데이터 아이템이 있을때는 데이터 아이템을 객체로 바꿔라.

효과

  • 데이터의 관련된 내용을 하나의 클래스로 작성할 수 있다.
// Example Code
class Order{
    String customer;
}
// Refactoring Code
class Order{
    Customer customer;
}
class Customer{
    String name;
}

Replace Array with Object

배열 대신 Object를 사용하라.

효과

  • 배열로 접근하여 값을 입력하는 것은 잘못 넣을 위험성이 있다.
  • Object를 통해 값을 입력하면 잘못 들어갈 가능성을 없앨 수 있다.
// Example Code
String[] row = new String[3];
row [0] = "Liverpool";
row [1] = "15"
// Refactoring Code
Performance row = new Performance();
row.setName("Liverpool");
row.setWins("15");

Replace Magic Number with Symbolic Constant

Magic Number를 상수로 바꾸자.

효과

  • Magic Number는 무엇을 의미하는지 이해하기 힘들다. 하지만 상수로 표현하면 이해하기 쉽다.
  • Magic Number는 변경하기도 어렵다. 하지만 상수로 관리하면 변경하기 쉽다.
// Example Code
double potentialEnergy(double mass, double height) {
  return mass * height * 9.81;
}
// Refactoring Code
static final double GRAVITATIONAL_CONSTANT = 9.81;

double potentialEnergy(double mass, double height) {
  return mass * height * GRAVITATIONAL_CONSTANT;
}

Encapsulate Collection

Collection을 직접 반환하지마라.

효과

  • 변경될 수 있는 약점에 대해 보호할 수 있다.
  • 요소를 추가하거나 삭제하는 작업은 있어야 한다.
// Example Code
getCourses(): Set
setCourses(:Set)
// Refactoring Code
getCourses(): UnmodifiableSet
addCourse(:Course)
removeCourse(:Course)

Rename Method

메소드의 이름을 적절하게 바꿔라.

Introduce Parameter Object

많은 매개변수를 하나의 매개변수 객체로 바꾸어라.

효과

  • 읽기 더 편하다.
// Example Code
amountInvoicedIn (start : Date, end : Date)
amountReceivedIn (start : Date, end : Date)
amountOverdueIn (start : Date, end : Date)
// Refactoring Code
amountInvoicedIn (: DateRange)
amountReceivedIn (: DateRange)
amountOverdueIn (: DateRange)

Remove Setting Method

필요없는 setter는 제거해라.

Replace Constructor with Factory Method

생성자 대신 Factory Method를 사용해라.

// Example Code
class Employee {
  Employee(int type) {
    this.type = type;
  }
  //...
}
// Refactoring Code
class Employee {
  static Employee create(int type) {
    employee = new Employee(type);
    // do some heavy lifting.
    return employee;
  }
  //...
}

Pull Up/Down Field / Pull Up/Down Method

공통으로 쓰는 필드,메소드는 상위 클래스로 특정한 필드,메소드는 특정한 클래스로

Field

Method

Extract Subclass/Superclass

특징들을 상/하위 클래스로 분리하라.

Extract Interface

인터페이스로 분리하라.

Split Temporary Variable

Motivate

  • 임시 변수는 반복하서 다양하게 쓰일 수 있지만 하나의 목적에 맞게 변수는 존재해야 한다.
  • ex) for loop의 i변수
  • 두 가지 용도로 사용하면 코드를 보는 사람이 매우 혼란스러울 수 있다.
// Example Code
double temp = 2 * (height + width);
System.out.println(temp);
temp = height * width;
System.out.println(temp);

// Refactoring Code
double perimeter = 2 * (height + width);
System.out.println(perimeter);
double area = height * width;
System.out.println(area);

Hide Delegate

  • 캡슐화는 객체에서 가장 중요한 개념 가운데 하나이다.
  • 시스템의 다른 부분에 대해 좀 적게 알아도 된다는 것을 의미한다.
  • 캡슐화가 되어 있는 경우 클래스가 변경되었을 때 시스템의 다른 부분이 영향을 덜 받으므로, 결과적으로 변경을 좀 더 쉽게 할 수 있다.

Reference

0%