끄적끄적

리팩토링 6장 - 메소드 정리 본문

리팩토링

리팩토링 6장 - 메소드 정리

widruv 2016. 3. 6. 21:58
리팩토링의 많은 부분을 차지


Extract Method(v)
  • 그룹으로 함께 묶을 수 있는 코드 조각이 있으면, 코드의 목적이 잘 드러나도록 메소드의 이름을 지어 별도의 메소드로 뽑아낸다.
  • 동기
    • 지나치게 긴 메소드
    • 주석이 필요한 코드( 목적을 이해하기 위한 )
  • 장점 ( 짧고 이해하기 쉬운 이름으로 메소드를 만들었을 때 )
    • 재사용 확률 높아짐
    • 메소드를 볼 때 주석을 읽는 것 같은 느낌이 들도록 할 수 있음
    • 오버라이드 하기 쉬움
  • 절차
    • 메소드를 새로 만듦
    • 의도를 잘 나타내도록 이름을 정함 ( 어떻게 하는지가 아닌 무엇을 하는지를 나타내도록 )
      • 뽑아내고자 하는 부분이 아주 간단한 경우에는 새로운 메소드의 이름이 그 코드의 의도를 더 잘 나타낼 수 있을 때만 뽑아낸다. )
    • 뽑아내고자 하는 부분의 코드를 복사하여 새 메소드로 옮김
    • 원래 메소드에서 사용되고 있는 지역변수가 뽑아낸 코드에 있는지 확인
      • 이 지역변수는 새로운 메소드의 지역변수나 파라미터가 됨
    • 뽑아낸 코드 내에서만 사용되는 임시변수가 있는지 본다. 
      • 있다면 새로 만든 메소드의 임시변수로 선언
    • 뽑아낸 코드 내에서 지역변수의 값이 수정되는지 본다.
      • 하나의 지역변수만 수정된다면 뽑아낸 코드를 질의(query)로 보고, 수정된 결과를 변수에 대입할 수 있는지 확인 ( ex:) temp = extractMethod(); )
      • 두개 이상이면 Split Temporary Variable 사용 후 다시 시도
      • 임시변수는 Replace Temp with Query로 제거할 수 있다
    • 뽑아낸 코드에서 읽기만 하는 변수는 새 메소드의 파라미터로 넘긴다.
    • 지역변수와 관련된 사항을 다룬 후에는 컴파일을 한다.
    • 원래 메소드의 뽑아낸 코드 부분에서 새로 만든 메소드를 호출하도록 바꾼다.
    • 컴파일과 테스트

Inline Method
  • 메소드 몸체가 메소드의 이름만큼이나 명확할 때는, 호출하는 곳에 메소드의 몸체를 넣고, 메소드를 삭제하라
  • 동기
    • 때론 메소드 몸체가 메소드의 이름만큼 명확할 때가 있다면 메소드를 삭제
  • 절차
    • 메소드가 다형성을 가지고 있지 않은지 확인
      • 서브클래스에서 오버라이드하고 있는 메소드에는 적용 X
    • 메소드를 호출하고 있는 부분을 모두 찾는다
    • 각각의 메소드 호출을 메소드 몸체로 바꾼다.
    • 컴파일과 테스트
    • 메소드 정의 제거

Inline Temp
  • 간단한 수식의 결과값을 가지는 임시변수가 있고, 그 임시변수가 다른 리팩토링을 하는데 방해가 된다면, 이 임시변수를 참조하는 부분을 모두 원래의 수식으로 바꾸라.
  • 예) 
    • double temp = anOrder.basePrice();
    • return (temp > 1000);
    •           ↓
    • return ( anOrder.basePrice() > 1000 );
  • 동기
    • Replace Temp with Query의 한 부분으로 사용
    • 메소드 호출의 결과값이 임시변수에 대입되는 경우
  • 절차
    • 임시변수를 final로 선언한 다음 커파일
      • 임시변수에 값이 단 한번만 대입되고 있는지 확인하기 위해서
    • 임시변수를 참조하고 있는 곳을 모두 찾아 대입문의 우변에 있는 수식으로 바꾼다.
    • 각각의 변경에 대해 컴파일과 테스트
    • 임시변수의 선언과 대입문 제거
    • 컴파일과 테스트

Replace Temp with Query(v)
  • 어떤 수식의 결과값을 저장하기 위해서 임시변수를 사용하고 있다면, 수식을 뽑아내서 메소드로 만들고, 임시변수를 참조하는 곳을 찾아 모두 메소드 호출로 바꾼다.
  • 새로 만든 메소드는 다른 메소드에서도 사용될 수 있다.
  • 동기
    • Extract Method 적용하기 전의 필수 단계
    • 지역변수 또는 임시변수는 메소드 추출을 어렵게 하기 때문에 가능한 많은 지역변수를 질의 메소드로 바꾸는 것이 좋음
  • 절차
    • 임시변수에 값이 한번만 대입되는지 확인
      • 여러번 대입되는 경우 Split Temporary Variable 적용
    • 임시변수를 final로 선언
    • 컴파일
    • 대입문의 우변을 메소드로 추출
    • 컴파일과 테스트
    • Inline Temp 적용
  • 퍼포먼스에 대한 문제
    • 약간 느려질지 몰라도 큰 문제가 되진 않을 것
    • 문제가 된다면 최적화 단계에서 수정하면 된다.
    • 일단 적용하고 나면 최적화를 한다고 해도 코드가 잘 정리되어 있기 때문에 더 좋은 최적화 방법을 찾을 수도 있다.
    • 최악의 경우라도, 임시변수를 다시 집어넣는 건 쉽다.

Introduce Explaining Variable(v)
  • 복잡한 수식이 있는 경우에는, 수식의 결과나 또는 수식의 일부에 자신의 목적을 잘 설명하는 이름으로 된 임시변수를 사용하라.
  • 동기
    • 특히 조건문에서 각각의 조건의 뜻을 잘 설명하는 이름의 변수로 만들어 사용할 때 유용
    • 긴 알고리즘에서 각 단계의 계산 결과
    • 하지만 대부분 Extract Method를 보통 쓰게 된다.

Split Temporary Variable(v)
  • 루프 안에 있는 변수나 collecting temporary variable도 아닌 임시변수에 값을 여러 번 대입하는 경우에는, 각각의 대입에 대해서 따로따로 임시변수를 만들어라.
  • 동기
    • 어떤 변수든 여러 가지 용도로 사용되는 경우에는 각각의 용도에 대해 따로 변수를 사용하도록 바꾸어야 함
  • 절차
    • 임시변수가 처음 선언된 곳과 임시변수에 값이 처음 대입된 곳에서 변수의 이름을 바꾼다.
    • 새로 만든 임시변수를 final로 선언
    • 임시변수에 두 번째로 대입하는 곳의 직전까지 원래 임시변수를 참조하는 곳을 모두 바꿈
    • 임시변수에 두 번째로 대입하는 곳에서 변수 선언
    • 컴파일 & 테스트

Remove Assignments to Parameters(v)
  • 파라미터에 값을 대입하는 코드가 있으면, 대신 임시변수를 사용하도록 하라.
  • 동기
    • 파라미터가 값에 의한 전달(pass by value)이라면 문제 없지만 참조에 의한 전달(pass by reference)일 때는 혼동
    • 출력 파라미터를 사용하는 언어는 상관없긴 하지만 출력 파라미터는 가능한 적게 사용하는 것이 좋다.
  • 절차
    • 파라미터를 위한 임시변수를 만든다.
    • 파라미터에 값을 대입한 코드 이후에서 파라미터에 대한 참조를 임시변수로 바꾼다.
    • 파라미터에 대입하는 값을 임시변수에 대입하도록 바꾼다.
    • 컴파일 & 테스트

Replace Method with Method Object(써보자)
  • 긴 메소드가 있는데, 지역변수 때문에 Extract Method를 적용할 수 없는 경우에는, 
  • 메소드를 그 자신을 위한 객체로 바꿔서 모든 지역변수가 그 객체의 필드가 되도록 한다. 이렇게 하면 메소드를 같은 객체 안의 여러 메소드로 분해할 수 있다.
  • 절차
    • 메소드의 이름을 따서 새로운 클래스를 만든다.
    • 새로운 클래스에 원래 메소드가 있던 객체를 보관하기 위한 final 필드를 하나 만들고, 메소드에서 사용되는 임시변수와 파라미터를 위한 필드를 만들어준다.
    • 새로운 클래스에 소스 객체와 파라미터를 취하는 생성자를 만들어준다.
    • 새로운 클래스에 compute라는 이름의 메소드를 만들어준다.
    • 원래의 메소드를 compute 메소드로 복사한다. 원래의 객체에 있는 메소드를 사용하는 경우에는 소스 객체 필드를 사용하도록 바꾼다.
    • 컴파일
    • 새로운 클래스의 객체를 만들고 원래의 메소드를 새로 만든 객체의 compute 메소드를 호출하도록 바꾼다.
  • 이 후로는 지역변수가 모두 필드로 바뀌었으므로, 파라미터를 넘길 필요 없이 마음대로 메소드를 분해할 수 있다.


Substitute Algorithm
  • 알고리즘을 보다 명확한 것으로 바꾸고 싶을 때는, 메소드의 몸체를 새로운 알고리즘으로 바꾼다.
  • 절차
    • 대체 알고리즘을 적용하여 컴파일
    • 알고리즘 테스트, 결과가 같으면 끝
    • 결과 같지 않다면, 디버깅



Comments