리팩토링 Tutorial 1주차

             2011.11.4
               심빈구
목차
   리팩토링 배경
   리팩토링 정의
   리팩토링 원리
       왜, 언제?, 문제는?
   냄새
리팩토링 배경
: 리팩토링 이란?

 Bad Code           Good Code




             리팩토링
리팩토링 배경:
: Bad Code가 야기시키는 문제점




                            Broken Window Theory




  나쁜코드에 의한 생산성 저하는 계속 악화됨
리팩토링 정의

        명사형 정의
            “소프트웨어를 보다 쉽게 이해할 수 있고, 적은 비용으로 수정할 수 있도록 겉으로 보이는 동작의 변화 없이 내부 구조를 변
             경하는 것”

        동사형 정의
            “일련의 리팩토링을 적용하여 겉으로 보이는 동작의 변화 없이 소프트웨어의 구조를 바꾼다.”

        다음 방법으로 동작의 변경 여부 검증
            테스팅
            최대한 개발 Tool의 지원 기능 사용
            아주 조심히 진행

        Refactoring의 예


public int getCharge(int quantity) {                           public int getCharge(int quantity) {
   int charge = 0;                                                 int charge = 0;
   Date now = new Date();                                          Date now = new Date();

     // 현재 Summer타임 기간이라면                                          if (isSummerTime(now)) {
     if (now.before(SUMMER_START)|| now.after(SUMMER_END)) {         charge = quantity * WINTER_RATE +
       charge = quantity * WINTER_RATE +                                           WINTER_SERVICEC_CHARGE;
                     WINTER_SERVICEC_CHARGE;                       } else {
     } else {                                                        charge = quantity * SUMMER_RATE;
       charge = quantity * SUMMER_RATE;                            }
     }                                                             return charge;
     return charge                                             }
 }
                                                               private boolean isSummerTime(Date now) {
                                                                  return now.before(SUMMER_START) || now.after(SUMMER_END);
                                                               }
리팩토링 원리
: 왜 리팩토링을 해야 하는가?
   프로그램을 빨리 작성하도록 도와줌

   어떻게?
       리팩토링은 디자인을 개선시켜 줌

   디자인이 나쁜 코드는?
       같은 작업을 위해 더 많은 코드 사용
       중복이 많고 이해하기 어려움
       수정 시 어려움으로 나타남

   리팩토링은 소프트웨어를 더 이해하기 쉽게 만듬
       리팩토링된 코드는 숨겨진 사용자인 유지보수자의 이해를 도움
       낮선 코드에 대해 리팩토링 하면서 코드에 대해 이해하기도 함
리팩토링 원리
: 언제 리팩토링을 해야 하는가?
   틈틈이 계속
       리팩토링 자체가 목적이 아니라, 다른 것을 하기 위해 리팩토링
        을 하는 것이고, 리팩토링은 그 다른 것을 하는데 도움을 준다.

   삼진 규칙
       세 번째로 비슷한 것을 하게 되면 리팩토링을 한다

   기능을 추가할 때, 버그를 수정할 때
       코드에 대한 이해를 돕기 위해서

   코드 검토 시
       고수준의 의견을 얻을 수 있음
       준비가 많이 필요함
리팩토링 원리
    : 두 개의 모자




           기능 추가                      리팩토링

    기존 코드 수정 없이 새로운 기능 추가      기능 추가 없이 코드 구조 수정

    테스트 추가                     테스트 추가하지 않아야 함

    테스트 정상 동작 확인               테스트 정상 동작 확인




      개발할 때에는 모자를 자주 바꿔 쓰고(10분~30분),
                     한 시점에는 하나의 모자만 써야 한다.
리팩토링 원리
: 리팩토링을 할 때의 문제
   데이터 베이스와 연관된 코드의 리팩토링

   인터페이스의 변경
       Publish 된 인터페이스의 이름 및 파라미터에 대한 리팩토링
           Ex) Android의 Service.onStart() 메소드
           새로운 I/F를 만들고 Delegation 사용
           예방책 : 애매한 메소드는 API에 넣지 말자
       Publish 된 인터페이스의 Throw절의 변경
           이 경우 Delegation 사용 불가
           예방책 : Super Exception 사용

   리팩토링이 어려운 디자인 변경
       디자인에 실수가 있어 마음대로 리팩토링 할 수 없을 때
       어떤 디자인 결정 사항이 너무 중요해서 리팩토링을 기대할 수 없는 경우
           보안 문제, 퍼포먼스 문제

   언제 리팩토링을 하지 말아야 하는가?
       코드를 처음부터 작성 하는 게 나을 정도로 엉망인 경우
       현재의 코드가 작동하지 않을 경우
       마감일에 가까울 경우
리팩토링 원리
: 사전 디자인과 리팩토링의 효용성 관계
   “디자인으로는 생각을 아주 빨리 할 수 있지만, 그 생각에는 여
    기저기 작은 구멍이 뚫려있다.”
       “With design I can think very fast, but my thinking is full of little
        holes” – Alistair Cockburn

   리팩토링에 의해 사전 디자인의 Role이 변경됨
       완벽한 사전 디자인이 아닌 적절한 솔루션을 제공하는 디자인이면
        충분
           리팩토링을 통해 변경에 많은 비용이 들지 않기 때문
       따라서, 디자인이 단순화 됨

   디자인 중심의 단점
       설계 비용이 많이 든다.
       복잡해 진다.
       유지보수 비용이 상대적으로 많이 든다.
           중복에 의한게 아닌 Complexity 때문
리팩토링 원리
: 리팩토링과 퍼포먼스
   리팩토링은 장기적으로 최적화 단계에 소프트웨어의
    튜닝을 돕는다.
       리팩토링을 통해 퍼포먼스 튜닝에 할당할 수 있는 시간을
        얻을 수 있음.
       프로그램이 잘 분해되어 있으면, 튜닝을 위한 분석 시 좀
        더 세밀한 분석이 가능하다.
냄새
   냄새(코드냄새)는 코드에 잠재된 문제에 대한 경고 표
    시
   리팩토링을 해야 하는 문제점 표시

   대표적 냄새
       중복코드
       부적절한 이름
       기능에 대한 욕심
       부적절한 친밀
       주석
       긴 메소드
       긴 파라미터 리스트
       Switch문
냄새
: 중복 코드
   가장 많이 발생하는 냄새
   두 가지 중복이 있음
       Obvious 중복
           보통 Copy & Paste에 의해 발생
       Unobvious 중복
           계층구조의 병렬적 구현
           비슷한 알고리즘(ex, 문자열, 도메인 특화 로직)

   해결책
       하나의 클래스에서 중복
           ExtractMethod
       두 형제 클래스에서 중복
           ExtractMethod -> Pull Up Field or Pull Up Method -> Form
            Template Method
냄새
: 부적절한 이름
   잘못된 이름은 코드의 이해를 방해한다.
   “People often make assumptions based on the object
    names alone” – Word Cunningham

   해결책
       Rename Method
       Rename Field
       Rename Constants

   Tip !
       일관성 없는 상세이름 보다는 일관성 있는 광의의 이름이 적합
           add, register, put, create -> add
       일관성 있는 이름을 위해서 용어 사전은 필수적
냄새
: 기능에 대한 욕심
   특정 클래스 내의 메소드가 동   PriceCalculator       Product

    작을 위해 다른 클래스에 있는   ..
                       calculate()
                                         ..
                                         getQuantity()
    정보를 많이 필요로 하는 경우   bmethod()         getDiscountRate()




   해결책
       Move Method
냄새
: 부적절한 친밀
   특정 클래스 내의 메소드가 다른                                Class A      Class B

    클래스에 있는 메소드(private 이                       ..             ..

    어야 할)를 더 많이 사용하는 경우
                                                amethod()      xmethod()
                                                bmethod()      ymethod()




   해결책
       두 개의 독립적인 클래스가 엉켜 있다
        면
           Move Method
       서로를 가리키고 있다면
           Change Bidirectional Reference to
            Unidirectional
       중재하는 클래스가 없기 때문에 엉켜
        있다면
           Extract Hierarchy-> Hide Delegate
냄새
: 주석
   주석은 대부분 코드가 명확 치 않다고 판단될 때 쓰임
   주석은 나쁜 코드를 유도함

   해결책
       코드의 일정 블록 설명
           Extract Method
       메소드가 하는 일 설명
           Rename Method
       선 조건 설명
           Introduce Assertion
냄새
: 긴 메소드
   긴 메소드는 코드를 이해하기 힘들게 만든다.
   주석을 달아야 할 필요를 느낄 때 마다 메소드로 분리

   해결책
       Extract Method


   주의점
       코드의 이해를 돕기 위해서는 코드의 의도를 잘 나타내는
        이름 지어야
           부적절한 이름을 가진 짧은 메소드 집합은 긴 메소드보다 이해하
            기 힘들다.
냄새
: 긴 파라미터 리스트
   객체지향 코드에서는 파라미터가 많을 필요 없다.

   문제점
       이해하기 어려움
       일관성 없음
       변경이 많이 됨

   해결책
       이미 알고 있는 다른 객체로부터 값 얻어올 수 있음
           Replace Parameter with Method
       매개변수가 하나의 Object로 부터 나오면
           Preserve Whole Object
       매개변수 데이터가 하나의 논리 객체로 부터 얻어지는게 아닐 경우
           Introduce Parameter Object

   주의점
       Caller와 Callee간의 데이터 종속성을 만들고 싶지 않을 경우 리팩토링을 피해야함
냄새
: Switch 문
    Switch문은 본질적으로 중복의 문제를 발생
        타입 추가 시, 관련된 모든 Switch문을 수정해야 함
    좋은 OOP코드의 특징은 Switch문이 비교적 적음

    해결책
        동일한 조건에 대한 Switch문이 여러 곳에서 사용됨
            Step 1: Extract Method를 통해 각 조건 절에서 코드 추출
            Step 2: Move Method를 통해 연관된 코드를 옳바른 클래스로 옮김
            Step 3: Replace Type Code with Subclass or
                      Replace Type Code with State/Strategy 를 통해 상속구조 만듬


    주의
        Switch문의 중복이 많지 않다면 바꿀 필요 없음
    20                                       Confidential   12/13/2011
결론
    리팩토링은 코드를 이해하기 쉽게 만든다.

    리팩토링은 목표가 아니라, 다른 작업을 하기 위한 과
     정이다.

    리팩토링은 틈틈히 계속 해야 한다.




    21                Confidential   12/13/2011

Refactoring tutorial 1주차[refactoring 개요]

  • 1.
    리팩토링 Tutorial 1주차 2011.11.4 심빈구
  • 2.
    목차  리팩토링 배경  리팩토링 정의  리팩토링 원리  왜, 언제?, 문제는?  냄새
  • 3.
    리팩토링 배경 : 리팩토링이란? Bad Code Good Code 리팩토링
  • 4.
    리팩토링 배경: : BadCode가 야기시키는 문제점 Broken Window Theory 나쁜코드에 의한 생산성 저하는 계속 악화됨
  • 5.
    리팩토링 정의  명사형 정의  “소프트웨어를 보다 쉽게 이해할 수 있고, 적은 비용으로 수정할 수 있도록 겉으로 보이는 동작의 변화 없이 내부 구조를 변 경하는 것”  동사형 정의  “일련의 리팩토링을 적용하여 겉으로 보이는 동작의 변화 없이 소프트웨어의 구조를 바꾼다.”  다음 방법으로 동작의 변경 여부 검증  테스팅  최대한 개발 Tool의 지원 기능 사용  아주 조심히 진행  Refactoring의 예 public int getCharge(int quantity) { public int getCharge(int quantity) { int charge = 0; int charge = 0; Date now = new Date(); Date now = new Date(); // 현재 Summer타임 기간이라면 if (isSummerTime(now)) { if (now.before(SUMMER_START)|| now.after(SUMMER_END)) { charge = quantity * WINTER_RATE + charge = quantity * WINTER_RATE + WINTER_SERVICEC_CHARGE; WINTER_SERVICEC_CHARGE; } else { } else { charge = quantity * SUMMER_RATE; charge = quantity * SUMMER_RATE; } } return charge; return charge } } private boolean isSummerTime(Date now) { return now.before(SUMMER_START) || now.after(SUMMER_END); }
  • 6.
    리팩토링 원리 : 왜리팩토링을 해야 하는가?  프로그램을 빨리 작성하도록 도와줌  어떻게?  리팩토링은 디자인을 개선시켜 줌  디자인이 나쁜 코드는?  같은 작업을 위해 더 많은 코드 사용  중복이 많고 이해하기 어려움  수정 시 어려움으로 나타남  리팩토링은 소프트웨어를 더 이해하기 쉽게 만듬  리팩토링된 코드는 숨겨진 사용자인 유지보수자의 이해를 도움  낮선 코드에 대해 리팩토링 하면서 코드에 대해 이해하기도 함
  • 7.
    리팩토링 원리 : 언제리팩토링을 해야 하는가?  틈틈이 계속  리팩토링 자체가 목적이 아니라, 다른 것을 하기 위해 리팩토링 을 하는 것이고, 리팩토링은 그 다른 것을 하는데 도움을 준다.  삼진 규칙  세 번째로 비슷한 것을 하게 되면 리팩토링을 한다  기능을 추가할 때, 버그를 수정할 때  코드에 대한 이해를 돕기 위해서  코드 검토 시  고수준의 의견을 얻을 수 있음  준비가 많이 필요함
  • 8.
    리팩토링 원리 : 두 개의 모자 기능 추가 리팩토링  기존 코드 수정 없이 새로운 기능 추가  기능 추가 없이 코드 구조 수정  테스트 추가  테스트 추가하지 않아야 함  테스트 정상 동작 확인  테스트 정상 동작 확인 개발할 때에는 모자를 자주 바꿔 쓰고(10분~30분), 한 시점에는 하나의 모자만 써야 한다.
  • 9.
    리팩토링 원리 : 리팩토링을할 때의 문제  데이터 베이스와 연관된 코드의 리팩토링  인터페이스의 변경  Publish 된 인터페이스의 이름 및 파라미터에 대한 리팩토링  Ex) Android의 Service.onStart() 메소드  새로운 I/F를 만들고 Delegation 사용  예방책 : 애매한 메소드는 API에 넣지 말자  Publish 된 인터페이스의 Throw절의 변경  이 경우 Delegation 사용 불가  예방책 : Super Exception 사용  리팩토링이 어려운 디자인 변경  디자인에 실수가 있어 마음대로 리팩토링 할 수 없을 때  어떤 디자인 결정 사항이 너무 중요해서 리팩토링을 기대할 수 없는 경우  보안 문제, 퍼포먼스 문제  언제 리팩토링을 하지 말아야 하는가?  코드를 처음부터 작성 하는 게 나을 정도로 엉망인 경우  현재의 코드가 작동하지 않을 경우  마감일에 가까울 경우
  • 10.
    리팩토링 원리 : 사전디자인과 리팩토링의 효용성 관계  “디자인으로는 생각을 아주 빨리 할 수 있지만, 그 생각에는 여 기저기 작은 구멍이 뚫려있다.”  “With design I can think very fast, but my thinking is full of little holes” – Alistair Cockburn  리팩토링에 의해 사전 디자인의 Role이 변경됨  완벽한 사전 디자인이 아닌 적절한 솔루션을 제공하는 디자인이면 충분  리팩토링을 통해 변경에 많은 비용이 들지 않기 때문  따라서, 디자인이 단순화 됨  디자인 중심의 단점  설계 비용이 많이 든다.  복잡해 진다.  유지보수 비용이 상대적으로 많이 든다.  중복에 의한게 아닌 Complexity 때문
  • 11.
    리팩토링 원리 : 리팩토링과퍼포먼스  리팩토링은 장기적으로 최적화 단계에 소프트웨어의 튜닝을 돕는다.  리팩토링을 통해 퍼포먼스 튜닝에 할당할 수 있는 시간을 얻을 수 있음.  프로그램이 잘 분해되어 있으면, 튜닝을 위한 분석 시 좀 더 세밀한 분석이 가능하다.
  • 12.
    냄새  냄새(코드냄새)는 코드에 잠재된 문제에 대한 경고 표 시  리팩토링을 해야 하는 문제점 표시  대표적 냄새  중복코드  부적절한 이름  기능에 대한 욕심  부적절한 친밀  주석  긴 메소드  긴 파라미터 리스트  Switch문
  • 13.
    냄새 : 중복 코드  가장 많이 발생하는 냄새  두 가지 중복이 있음  Obvious 중복  보통 Copy & Paste에 의해 발생  Unobvious 중복  계층구조의 병렬적 구현  비슷한 알고리즘(ex, 문자열, 도메인 특화 로직)  해결책  하나의 클래스에서 중복  ExtractMethod  두 형제 클래스에서 중복  ExtractMethod -> Pull Up Field or Pull Up Method -> Form Template Method
  • 14.
    냄새 : 부적절한 이름  잘못된 이름은 코드의 이해를 방해한다.  “People often make assumptions based on the object names alone” – Word Cunningham  해결책  Rename Method  Rename Field  Rename Constants  Tip !  일관성 없는 상세이름 보다는 일관성 있는 광의의 이름이 적합  add, register, put, create -> add  일관성 있는 이름을 위해서 용어 사전은 필수적
  • 15.
    냄새 : 기능에 대한욕심  특정 클래스 내의 메소드가 동 PriceCalculator Product 작을 위해 다른 클래스에 있는 .. calculate() .. getQuantity() 정보를 많이 필요로 하는 경우 bmethod() getDiscountRate()  해결책  Move Method
  • 16.
    냄새 : 부적절한 친밀  특정 클래스 내의 메소드가 다른 Class A Class B 클래스에 있는 메소드(private 이 .. .. 어야 할)를 더 많이 사용하는 경우 amethod() xmethod() bmethod() ymethod()  해결책  두 개의 독립적인 클래스가 엉켜 있다 면  Move Method  서로를 가리키고 있다면  Change Bidirectional Reference to Unidirectional  중재하는 클래스가 없기 때문에 엉켜 있다면  Extract Hierarchy-> Hide Delegate
  • 17.
    냄새 : 주석  주석은 대부분 코드가 명확 치 않다고 판단될 때 쓰임  주석은 나쁜 코드를 유도함  해결책  코드의 일정 블록 설명  Extract Method  메소드가 하는 일 설명  Rename Method  선 조건 설명  Introduce Assertion
  • 18.
    냄새 : 긴 메소드  긴 메소드는 코드를 이해하기 힘들게 만든다.  주석을 달아야 할 필요를 느낄 때 마다 메소드로 분리  해결책  Extract Method  주의점  코드의 이해를 돕기 위해서는 코드의 의도를 잘 나타내는 이름 지어야  부적절한 이름을 가진 짧은 메소드 집합은 긴 메소드보다 이해하 기 힘들다.
  • 19.
    냄새 : 긴 파라미터리스트  객체지향 코드에서는 파라미터가 많을 필요 없다.  문제점  이해하기 어려움  일관성 없음  변경이 많이 됨  해결책  이미 알고 있는 다른 객체로부터 값 얻어올 수 있음  Replace Parameter with Method  매개변수가 하나의 Object로 부터 나오면  Preserve Whole Object  매개변수 데이터가 하나의 논리 객체로 부터 얻어지는게 아닐 경우  Introduce Parameter Object  주의점  Caller와 Callee간의 데이터 종속성을 만들고 싶지 않을 경우 리팩토링을 피해야함
  • 20.
    냄새 : Switch 문  Switch문은 본질적으로 중복의 문제를 발생  타입 추가 시, 관련된 모든 Switch문을 수정해야 함  좋은 OOP코드의 특징은 Switch문이 비교적 적음  해결책  동일한 조건에 대한 Switch문이 여러 곳에서 사용됨  Step 1: Extract Method를 통해 각 조건 절에서 코드 추출  Step 2: Move Method를 통해 연관된 코드를 옳바른 클래스로 옮김  Step 3: Replace Type Code with Subclass or Replace Type Code with State/Strategy 를 통해 상속구조 만듬  주의  Switch문의 중복이 많지 않다면 바꿀 필요 없음 20 Confidential 12/13/2011
  • 21.
    결론  리팩토링은 코드를 이해하기 쉽게 만든다.  리팩토링은 목표가 아니라, 다른 작업을 하기 위한 과 정이다.  리팩토링은 틈틈히 계속 해야 한다. 21 Confidential 12/13/2011