블로그 이미지
암초보

calendar

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

Notice

Tag

12-29 11:14

'프로그래밍/Refactoring'에 해당되는 글 15

  1. 2011.09.19 Substitute Algorithm1
  2. 2011.09.19 Replace Method with Method Object
  3. 2011.09.19 Remove Assignments to Parameters
  4. 2011.09.19 Split Temporary Variable
  5. 2011.09.19 Introduce Explaining Variable
  6. 2011.09.19 Replace Temp with Query
  7. 2011.09.18 Inline Temp
  8. 2011.09.18 Inline Method
  9. 2011.09.18 Extract Method
  10. 2011.09.18 리팩토링으로 해결될 수 있는 문제가 있다는 징후
2011. 9. 19. 04:04 프로그래밍/Refactoring

※ 알고리즘을 보다 명확한 것으로 바꾸고 싶을 때는, 메소드의 몸체를 새로운 알고리즘으로 바꾼다.

※ 절차
1. 대체 알고리즘을 준비하여 적용후 컴파일
2. 알고리즘 테스트. 만약 결과가 같다면 작업은 끝
3. 만약 결과가 같지 않다면, 테스트에서 비교하기 위해 예전의 알고리즘을 사용하여 디버깅

Before
String findPerson(String[] people) {
  for (int i=0; i<people.length; i++) {
    if(people[i].equals("Don")) {
      return "Don";
    }
    if(people[i].equals("John")) {
      return "John";
    }
    if(people[i].equals("Kent")) {
      return "Kent";
    }
  }
  return " ";
}


After
String findPerson(String[] people) {
  List candidates = Arrays.asList(new String[] {"Don", "John", "Kent"});
  for (int i=0; i<people.length; i++) {
    if(candidates.contains(people[i]))
      return people[i];
  }
  return " ";
}



//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리펙토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Replace Method with Method Object  (0) 2011.09.19
Remove Assignments to Parameters  (0) 2011.09.19
Split Temporary Variable  (0) 2011.09.19
Introduce Explaining Variable  (0) 2011.09.19
Replace Temp with Query  (0) 2011.09.19
posted by 암초보
2011. 9. 19. 03:52 프로그래밍/Refactoring
※ 긴 메소드가 있는데, 지역변수 때문에 Extract Method를 적용할 수 없는 경우에는,
메소드를 그 자신을 위한 객체로 바꿔서 모든 지역변수가 그 객체의 필드가 되도록 한다. 이렇게 하면 메소드를 같은 객체 안의 여러 메소드로 분해할 수 있다.

※ 절차
1. 메소드의 이름을 따서 새로운 클래스를 생성
2. 새로운 클래스에 원래 메소드가 있던 객체(소스 객체)를 보관하기 위한 final 필드를 하나 만들고, 메소드에서 사용되는 임시변수와 파라미터를 위한 필드를 만든다.
3. 새로운 클래스에 소스 객체와 파라미터를 취하는 생성자를 만든다.
4. 새로운 클래스에 compute라는 이름의 메소드를 만든다.
5. 원래의 메소드를 compute 메소드로 복사한다. 원래의 객체에 있는 메소드를 사용하는 경우에는 소스 객체 필드를 사용하도록 바꾼다.
6. 컴파일한다.
7. 새로운 클래스의 객체를 만들고 원래의 메소드를 새로 만든 객체의 compute 메소드를 호출하도록 바꾼다.
8. 지역변수가 모두 필드로 빠뀌었으므로, 파라미터를 넘길 필요 없이 마음대로 메소드를 분해할 수 있다.


Before
 class Account ....
   int gamma (int inputVal, int quantity, int yearToDate) {
      int importantValue1 = (inputVal * quantity) + delta();
      int importantValue2 = (inputVal * yearToDate) + 100;
      if ((yearToDate - importantValue1) > 100)
         importantValue2 -= 20;
      int importantValue3 = importantValue2 * 7;
      // 기타 등등
      return importantValue3 - 2 * importantValue1;
   }

After
 class Gamma ...
   private final Account _account;
   private int inputVal;
   private int quantity;
   private int yearToDate;
   private int importantValue1;
   private int importantValue2;
   private int importantValue3;
   Gamma(Account source, int inputValArg, int quantityArg, int yearToDateArg) {
      _account = source;
      inputVal = inputValArg;
      quantity = quantityArg;
      yearToDate = yearToDateArg;
   }
   int compute() {
      int importantValue1 = (inputVal * quantity) + _account.delta();
      int importantValue2 = (inputVal * yearToDate) + 100;
      if ((yearToDate - importantValue1) > 100)
         importantValue2 -= 20;
      int importantValue3 = importantValue2 * 7;
      // 기타 등등
      return importantValue3 - 2 * importantValue1;

   }
class Account ....
   int gamma (int inputVal, int quantity, int yearToDate) {
     return new Gamma(this, inputVal, yearToDate).compute(); 
   }


※ compute 메소드에서 파라미터를 넘겨주는 것에 대한 걱정 없이 쉽게 Extract Method를 사용할 수 있다.




//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리팩토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Substitute Algorithm  (1) 2011.09.19
Remove Assignments to Parameters  (0) 2011.09.19
Split Temporary Variable  (0) 2011.09.19
Introduce Explaining Variable  (0) 2011.09.19
Replace Temp with Query  (0) 2011.09.19
posted by 암초보
2011. 9. 19. 03:32 프로그래밍/Refactoring
※ 파라미터에 값을 대입하는 코드가 있으면, 대신 임시변수를 사용하도록 하라.

※ 자바에서는 값에 의한 전달만 사용, 참조에 의한 전달은 사용 안함

※ 절차
1. 파라미터를 위한 임시변수를 만든다.
2. 파라미터에 값을 대입한 코드 이후에서 파라미터에 대한 참조를 임시변수로 바꾼다.
3. 파라미터에 대입하는 값을 임시변수에 대입하도록 바꾼다.
4. 컴파일 및 테스트

Before
int discount (int inputVal, int quantity, int yearToDate) {
   if (inputVal > 50) inputVal -= 2;
   if (quantity > 100) inputVal -= 1;
   if (yearToDate > 10000) inputVal -= 4;
   return inputVal;
}

After
int discount (int inputVal, int quantity, int yearToDate) {
   int result = inputVal;
   if (inputVal > 50) result -= 2;
   if (quantity > 100) result -= 1;
   if (yearToDate > 10000) result -= 4;
   return result;
}

More....
파라미터를 final로 선언하여 이 관례를 강제할 수 있지만,
(자바 1.1부터 파라미터를 fianl로 하는 것이 가능해짐)
짧은 메소드에 대해서는 코드를 명확하게 하는데 별로 큰도움이 되지 않으므로 사용 안함.
int discount (final int inputVal, final int quantity, final int yearToDate) {
   int result = inputVal;
   if (inputVal > 50) result -= 2;
   if (quantity > 100) result -= 1;
   if (yearToDate > 10000) result -= 4;
   return result;
}




//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리팩토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Substitute Algorithm  (1) 2011.09.19
Replace Method with Method Object  (0) 2011.09.19
Split Temporary Variable  (0) 2011.09.19
Introduce Explaining Variable  (0) 2011.09.19
Replace Temp with Query  (0) 2011.09.19
posted by 암초보
2011. 9. 19. 03:16 프로그래밍/Refactoring

※ 루프 안에 있는 변수나 collecting temporary variable도 아닌 임시변수에 값을 여러 번 대입하는 경우에는, 각각의 대입에 대해서 따로따로 임시변수를 만들어라.

※ 하나의 임시변수를 두 가지 이상의 용도로 사용하면 코드를 보는 사람이 매우 혼란스러움

※ 절차
1. 임시변수가 처음 선언된 곳과 임시변수에 값이 처음 대입된 곳에서 변수의 이름을 바꿈
2. 임시변수를 final로 선언
3. 임시변수에 두 번째로 대입하는 곳의 직전까지 원래 임시변수를 참조하는 곳을 모두 바꾼다.
4. 임시변수에 두 두번째로 대입하는 곳에서 변수를 선언한다.
5. 컴파일 및 테스트
6. 각 단계를 반복

Before
double temp = 2 * (_height + _width);
System.out.println(temp);
temp = _height * _width;
System.out.println(temp); 

After
final double perimeter = 2 * (_height + _width);
System.out.println(perimeter);
final double area = _height * _width;
System.out.println(area); 





//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리팩토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Replace Method with Method Object  (0) 2011.09.19
Remove Assignments to Parameters  (0) 2011.09.19
Introduce Explaining Variable  (0) 2011.09.19
Replace Temp with Query  (0) 2011.09.19
Inline Temp  (0) 2011.09.18
posted by 암초보
2011. 9. 19. 02:54 프로그래밍/Refactoring

※ 복잡한 수식이 있는 경우에는, 수식의 결과나 또는 수식의 일부에 자신의 목적을 잘 설명하는 이름으로 된 임시변수를 사용하라.

※ 보통 Extract Method로 해결 - 임시변수는 한 메소드의 컨텍스트 내에서만 유용하지만 메소드는 객체의 모든 부분, 다른 객체에서도 유용
※ 지역변수 때문에 Extract Method의 사용이 어려운 경우 Introduce Explaining Variable 사용

※ 절차

1. final 변수를 선언하고, 복잡한 수식의 일부를 이 변수에 대입
2. 원래의 복잡한 수식에서, 임시변수에 대입한 수식을 임시변수로 바꾼다.
3. 컴파일 및 테스트
4. 수식의 다른 부분에 대해서도 위의 작업 반복

Before

double price() {
   // price = (base price) - (quantity discount) + (shipping);
   return _quantity * itemPrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(_quantity * itemPrice * 0.1, 100.0);
}

Step 1.
double price() {
   // price = (base price) - (quantity discount) + (shipping);
   final double basePrice = _quantity * itemPrice;
   return basePrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(_quantity * itemPrice * 0.1, 100.0);
}


Step 2.
double price() {
   // price = (base price) - (quantity discount) + (shipping);
   final double basePrice = _quantity * itemPrice;
   return basePrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(basePrice * 0.1, 100.0);
}

Step 3. (동일하게 모두 적용)
double price() {
   // price = (base price) - (quantity discount) + (shipping);
   final double basePrice = _quantity * itemPrice;
   final double quantityDiscount = Math.max(0, _quantity - 500) * _itemPrice * 0.05;
   final double shipping = Math.min(basePrice * 0.1, 100.0);
   return basePrice - quantityDiscount + shipping;
}



☞ Extract Method를 사용한 경우
Before
double price() {
   // price = (base price) - (quantity discount) + (shipping);
   return _quantity * itemPrice -
      Math.max(0, _quantity - 500) * _itemPrice * 0.05 +
      Math.min(_quantity * itemPrice * 0.1, 100.0);
}

After
double price() {
   // price = (base price) - (quantity discount) + (shipping);
   return basePrice() - quantityDiscount() + shipping();
}
private double quantityDiscount() {
   return Math.max(0, _quantity - 500) * _itemPrice * 0.05 ;
}
private double shipping() {
   return Math.min(basePrice() * 0.1, 100.0);
}
private double basePrice() {
   return _quantity * itemPrice;
}




//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리팩토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Remove Assignments to Parameters  (0) 2011.09.19
Split Temporary Variable  (0) 2011.09.19
Replace Temp with Query  (0) 2011.09.19
Inline Temp  (0) 2011.09.18
Inline Method  (0) 2011.09.18
posted by 암초보
2011. 9. 19. 02:44 프로그래밍/Refactoring

※ 어떤 수식의 결과값을 저장하기 위해서 임시변수를 사용하고 있다면, 수식을 뽑아내서 메소드로 만들고, 임시변수를 참조하는 곳을 찾아 모두 메소드 호출로 바꾼다. 새로 만든 메소드에서도 사용될 수 있다.

※ Extract Method 하기 전의 필수 단계

※ 절차
1. 임시변수에 값이 한번만 대입되는지 확인 (여러번이라면 Split Temporary Variable을 먼저 적용)
2. 임시변수를 final로 선언 후 컴파일 (임시변수에 값이 한번만 대입되는지 확인)
3. 대입문의 우변을 메소드로 추출
- 처음에 메소드를  private로 선언, 이후에 판단하여 접근 권한 변경
- 추출된 메소드에 부작용이 없는지 확인 (있다면 Separate Query from Modifier를 사용)
4. 컴파일 및 테스트
5. Inline Temp 적용

Before
double getPrice() {
   int basePrice = _quantity * _itemPrice;
   double discountFactor;
   if (basePrice > 1000) discountFactor = 0.95;
   else discountFactor = 0.98;
   return basePrice * discountFactor;
}

Step 1.
double getPrice() {
   final int basePrice = _quantity * _itemPrice;
   final double discountFactor;
   if (basePrice > 1000) discountFactor = 0.95;
   else discountFactor = 0.98;
   return basePrice * discountFactor;
}

Step 2.
double getPrice() {
   final int basePrice = basePrice();
   final double discountFactor;
   if (basePrice > 1000) discountFactor = 0.95;
   else discountFactor = 0.98;
   return basePrice * discountFactor;
}

private int basePrice() {
   return _quantity * _itemPrice;
}

Step 3.
double getPrice() {
   final int basePrice = basePrice();
   final double discountFactor;
   if (basePrice() > 1000) discountFactor = 0.95;
   else discountFactor = 0.98;
   return basePrice * discountFactor;
}

private int basePrice() {
   return _quantity * _itemPrice;
}

Step 4.
double getPrice() {
   final double discountFactor;
   if (basePrice() > 1000) discountFactor = 0.95;
   else discountFactor = 0.98;
   return basePrice() * discountFactor;
}

private int basePrice() {
   return _quantity * _itemPrice;
}

Step 5.
double getPrice() {
   final double discountFactor = discountFactor();
   return basePrice() * discountFactor;
}

private int basePrice() {
   return _quantity * _itemPrice;
}

private double discountFactor() {
 if (basePrice() > 1000) return 0.95;
   else return 0.98;

}

Step 6.
double getPrice() {
   return basePrice() * discountFactor();
}

private int basePrice() {
   return _quantity * _itemPrice;
}

private double discountFactor() {
 if (basePrice() > 1000) return 0.95;
   else return 0.98;

}




//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리팩토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Split Temporary Variable  (0) 2011.09.19
Introduce Explaining Variable  (0) 2011.09.19
Inline Temp  (0) 2011.09.18
Inline Method  (0) 2011.09.18
Extract Method  (0) 2011.09.18
posted by 암초보
2011. 9. 18. 18:04 프로그래밍/Refactoring

※ 간단한 수식의 결과값을 가지는 임시변수가 있고, 그 임시변수가 다른 리팩토링을 하는데 방해가 된다면, 이 임시변소를 참조하는 부분을 모두 원래의 수식으로 바꾸라.

※ Replace Temp with Query 의 한 부분으로 사용됨

Before
   double basePrice = anOrder.basePrice();
   return (basePrice > 1000);
(임시변수를 final로 선언한다음 컴파일해본다. 임시변수에 값이 단 한번만 대입되고 있는지를 확인)

After
   return (anOrder.basePrice() > 1000);






//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리팩토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Introduce Explaining Variable  (0) 2011.09.19
Replace Temp with Query  (0) 2011.09.19
Inline Method  (0) 2011.09.18
Extract Method  (0) 2011.09.18
리팩토링으로 해결될 수 있는 문제가 있다는 징후  (0) 2011.09.18
posted by 암초보
2011. 9. 18. 17:59 프로그래밍/Refactoring

※ 메소드 몸체가 메소드의 이름 만큼이나 명확할 때는, 호출하는 곳에 메소드의 몸체를 넣고, 메소드를 삭제하라.

Before
 int getRating() {
   return (moreThanFiveLateDeliveries()) ? 2:1;
}
boolean moreThanFiveLateDeliveries() {
   return _numberOfLateDeliveries > 5
}

After
 int getRating() {
   return (_numberOfLateDeliveries > 5) ? 2:1;
}




//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리팩토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Replace Temp with Query  (0) 2011.09.19
Inline Temp  (0) 2011.09.18
Extract Method  (0) 2011.09.18
리팩토링으로 해결될 수 있는 문제가 있다는 징후  (0) 2011.09.18
이클립스 리팩토링 단축키  (0) 2011.09.17
posted by 암초보
2011. 9. 18. 17:52 프로그래밍/Refactoring

간단하게 정리, 상세한 부분은 생략

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

Before
 void printOwing(double amount) {
   printBanner();
   //상세 정보 표시
   System.out.println("name:"+_name);
   System.out.println("amount:"+amount);
}

After
 void printOwing(double amount) {
   printBanner();
   printDetails(amount)
}
 void printDetails(double amount) {
   System.out.println("name:"+_name);
   System.out.println("amount:"+amount);
}




//////////////////////////////////////////////////////////////////////////////////////////
출처 : 마틴 파울러의 리팩토링
//////////////////////////////////////////////////////////////////////////////////////////

'프로그래밍 > Refactoring' 카테고리의 다른 글

Inline Temp  (0) 2011.09.18
Inline Method  (0) 2011.09.18
리팩토링으로 해결될 수 있는 문제가 있다는 징후  (0) 2011.09.18
이클립스 리팩토링 단축키  (0) 2011.09.17
리팩토링이란?  (0) 2011.09.17
posted by 암초보
2011. 9. 18. 03:18 프로그래밍/Refactoring

1. 중복된 코드

2. 긴 메소드
- 주석 대신 메소드
- 주석 대신 코드의 목적을 잘 설명하는 메소드 이름
 
3. 거대한 클래스

4. 긴 파라미터 리스트
- 이해하기 어려움
- 일관성이 없거나 사용하기 어려움
- 다른 데이터가 필요할 때마다 계속 고쳐야함

5. 확산적 변경

6. 산탄총 수술

7. 기능에 대한 욕심

8. 데이터 덩어리

9. 기본 타입에 대한 강박관념

10. Switch 문

11. 평행 상속 구조

12. 게으른 클래스

13. 추측성 일반화

14. 임시 필드

15. 메시지 체인

16. 미들 맨

17. 부적절한 친밀

18. 다른 인터페이스를 가진 대체 클래스

19. 불완전한 라이브러리 클래스

20. 데이터 클래스

21. 거부된 유산

22. 주석

'프로그래밍 > Refactoring' 카테고리의 다른 글

Inline Method  (0) 2011.09.18
Extract Method  (0) 2011.09.18
이클립스 리팩토링 단축키  (0) 2011.09.17
리팩토링이란?  (0) 2011.09.17
코드를 짤 때는..  (0) 2011.09.17
posted by 암초보
prev 1 2 next