'좋은 설계자 & 좋은관리자 & 좋은개발자/Code Refactoring'에 해당되는 글 2건

  1. 2014.06.24 [2] 리펙토링 - 함수를 분리해라 _ 1편
  2. 2014.06.24 [1] 리펙토링이란?
2014. 6. 24. 17:45



메서드의 목적을 분명해야 된다. 너무길거나 메서드의 목적을 알 수 없이 여러개의 목적이 들어 간다면 리펙토링 하는 것이 좋다. 

메서드는 짧고, 이름이 명확해야 한다.


 
void printOwing() {
    Enumeration e = _orders.elements();
    double outstanding = 0.0;
 
    // 배너출력
    System.out.println ("**************************");
    System.out.println ("***** Customer Owes ******");
    System.out.println ("**************************");
 
    // 미지불금액 계산
    while (e.hasMoreElements()) {
        Order each = (Order) e.nextElement();
        outstanding += each.getAmount();
    }
 
    // 상세출력
    System.out.println ("name:" + _name);
    System.out.println ("amount" + outstanding);
}


위 코드를 보면 함수명을 보면 미지불 금액을 출력하는데,  배너도 출력 하고 상세내역도 출력 한다.


이 함수를 기능별로 분리하는 방법을 선호 하는데 이유를 생각해 본다면 다음과 같다.


메서드를 분리 한다면, 분리된 함수들에 대한 사용성이 증가한다.  아래 코드를 보면 배너출력과 상세출력을 분리하였다. 함수명만 봐도 한눈에 이해하기 쉽다. 

또한, 추후에 지불된금액에 대해 출력을 할때,  printBanner() 를 재사용 할 수 있다.





void printOwing() { Enumeration e = _orders.elements(); double outstanding = 0.0; printBanner(); // 미지불금액 계산 while (e.hasMoreElements()) { Order each = (Order) e.nextElement(); outstanding += each.getAmount(); } printDetails(outstanding ); } // 배너출력 void printBanner() { System.out.println ("**************************"); System.out.println ("***** Customer Owes ******"); System.out.println ("**************************"); } // 상세 출력 void printDetails(double outstanding) { System.out.println ("name:" + _name); System.out.println ("amount" + outstanding); } // 추가된 지불된 금액 함수 void printPaidMoney() { printBanner(); // 함수 재사용 증가 }



미지불 금액 계산 로직도 함수로 뺄 수 있다.


void printOwing() { printBanner(); double outstanding = getOutstanding(); printDetails(outstanding ); } // 미지불금액 계산 double getOutstanding() { Enumeration e = _orders.elements(); double result = 0.0; while (e.hasMoreElements()) { Order each = (Order) e.nextElement(); result += each.getAmount(); } return result; } // 배너출력 void printBanner() { System.out.println ("**************************"); System.out.println ("***** Customer Owes ******"); System.out.println ("**************************"); } // 상세 출력 void printDetails(double outstanding) { System.out.println ("name:" + _name); System.out.println ("amount" + outstanding); }

리펙토링의 기본을 공부 했다. 

기억해야 할 부분은 함수는 한눈에 알아 보기 쉬워야 해야하며, 분리가 가능하다면 분리 하는 것이 재사용성이 좋다는 것.




Posted by hoonihoon
2014. 6. 24. 16:57

1. 리펙토링이란?

- 소프트웨어를 보다 쉽게 이해할 수 있어야 하고, 동작변화 없이 내부 구조를 변경하는 것.


2. 리펙토링의 목적?

- 프로그램을 빨리 작성 할 수 있도록 도와준다.

- 코드 디자인을 개선해준다.

- Bad code -> Good code

 

3.  Bad code 란? 

 같은 작업을 위해 더 많은 코드 사용, 중복이 많고 이해하기 어렵다. 

 유지보수하기에도 어려운 코드.


4. 리펙토링은 언제하는가?

 틈틈히 계속, 기능추가할때, 버그수정할때, 코드 검토시에.


5. 리펙토링을 할 수 없을때는?

 1) 디자인 실수가 있어 마음대로 리펙토링을 할 수 없을때

 2) 현재 설계된 구조가 보안문제, 퍼포먼스 문제등 중요사항으로 리펙토링을 기대할 수 없을 때.

 3) 코드가 처음부터 작성 하는게 나을 정도로 엉망인 경우

 4) 현재 코드가 작동하지 않을 경우

 5) 마감일이 가까울 경우.


6. 리펙토링할 나쁜코드는 왜 발생하는가?

 - Copy & paste 에 의해 중복 코드 발생.

 - 잘못된 변수명, 함수에서 발생.  (일관성이 중요   add,register, put, create )

 - 특정 클래스내의 메소드가 동작을 하기 위해 다른 클래스에 있는 정보를 많이 필요로 한경우 ( 메서드를 이동한다.)

- 나쁜주석

- 너무긴 메서드, 파라미터


7. 어떤식으로 리펙토링을 시작해야 되는가?


찾기 쉬운것 부터 한다.

 측정할 수 있는 것  (주석, 긴메서드, 거대한 클래스, 긴 매개변수)

   메소드가 하는일 설명, 블록이 하는일 설명


 
 // 배열값의 각 요소들이 이에 대응되는 예측 값과 허용범위 내의 차이를 갖는지 체크한다.
  public boolean compare(int[] expected, int[] actual, int clipLimit, int delta) {
    // clipLimit보다 큰 값을 잘라낸다.
    for (int i = 0; i < actual.length; i++)
      if (actual[i] > clipLimit)
        actual[i] = clipLimit;
    // 비교하려는 두 배열값의 길이가 같은지 체크한다.
    if (actual.length != expected.length)
      return false;
    return true;
  }



다음 강으로...

Posted by hoonihoon