'Programs/Refactoring'에 해당되는 글 4건

  1. 2011.11.30 Refactoring - 데이터 구성 1
  2. 2011.11.21 Refactoring - 객체간의 기능 이동 5
  3. 2011.11.16 Refactoring - 메소드 정리(Composing Methods) 4
  4. 2011.11.07 리팩토링(Refactoring) 4
Self Encapsulate Field

  • 정의
  • 필드에 직접 접근하고 있는데 필드에 대한 결합이 이상해지면, 그 필드에 대한 get/set 메소드를 만들고 항상 이 메소드를 사용하여 필드에 접근하라.

  • 동기
    • 간접 접근 방식(indirect variable access)의 장점은 서브클래스에서 정보를 얻는 메소드를 오버라이드 하여, 데이터를 관리하는데 있어 lazy initialization 과 같은 보다 많은 융통성을 제공할 수 있다는 것이다.
    • 이 리팩토링을 사용해야 하는 가장 중요한 때는 수퍼클래스에 있는 필드에 접근하지만 이 변수 접근을 서브클래스에서 계산되는 값으로 오버라이드 하고 실을 때이다.
    • 직접 접근 방법(direct variable access)의 장점은 코드가 읽기 쉬워진다는 것이다.

  • 주의사항
    • 자체 캡슐화를 사용할 때, 생성자에서 set 메소드가 사용되는 것에 주의해야 한다. 종종 객체가 생성된 후에 속성을 변경하기 위해 set 메소드를 사용하는 것으로 가정하므로, set 메소드에는 초기화 할 때와는 다른 동작을 포함하고 있을 수 있다. 이런 경우에는 생성자에서 직접 접근하거나 또는 별도의 초기화 메소드를 만든다.

Replace Data Value with Object

  • 정의
    추가적인 데이터나 동작을 필요로 하는 데이터 아이템이 있을 때는, 데이터 아이템을 객체로 바꾸어라.

  • 동기
    • 한두 개의 아이템에 대해서는 아이템을 포함하고 있는 객체에 메소드를 추가할 수 있겠지만, 곧 코드는 중복(duplication)과 기능에 대한 욕심(feature envy)의 냄새를 풍기게 된다. 이런 냄새가 나기 시작하면 데이터 값을 객체로 바꾸어야 한다.
  • 주의사항


Change Value to Reference

  • 정의
    동일한 인스턴스를 여러 개 가지고 있는 클래스가 있고 여러 개의 동일한 인스턴스를 하나의 객체로 바꾸고 싶으면, 그 객체를 참조 객체로 바꾸어라.

  • 동기
    • 불변성(immutable) 데이터를 가지는 간단한 값으로 시작하다가 변경 가능한 데이터를 두고, 변경이 그 객체를 참조하고 있는 모든 곳으로 전파되어야 한다면 객체를 참조 객체로 바꾸어라. 

  • 주의사항
    • 어떤 객체가 참조 객체에 대한 접근을 제공하는 책임을 질 것인지 결정한다.
    • 객체를 미리 생성해두고 메모리에서 구해서 쓴다면, 객체를 요구하기 전에 생성하는 것을 확실히 해야 한다.

Change Reference to Value


  • 정의
    작고, 불변성(immutable)이고, 관리하기가 어려운 참조 객체(reference object)가 있는 경우, 그것을 값 객체(value object)로 바꾸어라.

  • 동기
    • 참조 객체로 작업하는 것이 복잡해지면 참조에서 값으로 바꿀 이유가 될 수 있다. 

  • 주의사항
    • 바꿀 객체가 immutable 인지 또는 immutable이 될 수 있는지 확인한다. 만약 객체가 immutable이 될 수 없다면, 이 리팩토링을 포기해야 한다.

Replace Array with Object


  • 정의
    배열의 특정 요소가 다른 뜻을 가지고 있다면, 배열을 각각의 요소에 대한 필드를 가지는 객체로 바꿔라.

    • 다른 종류의 객체를 포함한 배열을 보게 된다. 배열의 첫 번째 요소는 사람의 이름이라는 식의 약속은 기억하기 어렵다. 이런 배열을 보게 되면 리팩토링을 해라.

  • 주의사항


Duplicate Observed Data


  • 정의
    GUI 컨트롤에서만 사용 가능한 도메인(domain) 데이터가 있고, 도메인 메소드에서 접근이 필요한 경우, 그 데이터를 도메인 객체로 복사하고, 옵저버(observer)를 두어 두 데이터를 동기화 하라.

  • 동기
    • 비지니스 로직이 사용자 인터페이스와 섞여 있는 2-티어로 개발된 코드를 보게 되면 인터페이스와 동작을 분리해야 한다.
  • 주의사항

Change Unidirectional Association to Bidirectional


  • 정의
    각각 서로의 기능을 필요로 하는 클래스가 있는데, 링크가 한쪽 방향으로만 되어 있는 경우, 반대 방향으로 포인터를 추가하고, 수정자(modifier)가 양쪽 세트(set)를 모두 업데이트 하게 변경하라.

  • 동기
    • 두 개의 클래스 중 단 방향 링크 일때, 기능 추가 등으로 반대 방향의 링크가 필요한 경우 역 포인터(back pointer)로 불리는 양방향 참조를 사용해라.

  • 주의사항
    • 어느 클래스가 이 연관을 책임지게 할 것인지 결정해야 한다. 
      • 두 객체가 모두 참조 객체(reference object)이고, 연관이 일대다(one to many)인 경우, 하나의 참조를 가지는 객체를 컨트롤러로 한다.
      • 한 객체가 다른 객체의 일부로 사용된다면, 그 객체를 포함하고 있는 객체가 연관을 컨트롤 한다.
      • 두 객체가 모두 참조 객체이고, 연관이 다대다(many to many)인 경우, 어느 쪽이 연관을 컨트롤 하든 상관 없다.


Change Bidirectional Association to Unidirectional


  • 정의
    서로 링크를 가지는 두 개의 클래스에서 한 쪽이 다른 한쪽을 더 이상 필요로 하지 않을 때는 불필요한 링크를 제거하라.

  • 동기
    • 양방향 연관은 반드시 필요한 곳에만 사용해야 한다. 제 몫을 하지 못하는 양방향 연관을 발견하면 즉시 불필요한 한쪽 링크를 끊어라. 

  • 주의사항
    • 양방향 링크에서는 죽어야 하는데 참조가 제대로 클리어 되지 않아 계속 살아돌아다니는 객체를 유도하기가 쉽다.
    • 양방향 링크를 유지하게 되면, 객체가 적절히 생성/제거되는지를 확인해야 하는 등의 복잡성(complexity)이 증가한다.
    • 양방향 연관을 자연스럽게 다루지 못하게 되면 종종 에러의 원인이 된다.


Replace Magic Number with Symbolic Constant


  • 정의
    특별한 의미를 가지는 숫자 리터럴이 있으면, 상수를 만들고, 의미를 잘 나타내도록 이름을 지은 다음, 숫자를 상수로 바꾸어라.

  • 동기
    • 매직 넘버는 특정 값을 가지는 숫자로 보통 그 의미는 명확하지 않다. 논리적으로 같은 숫자를 여러 곳에서 사용해야 하는 경우, 여러 곳에서 사용하지 않더라도 그 의미를 이해하기가 어렵다. 이 경우에 리팩토링 한다.

  • 주의사항


Encapsulate Field

  • 정의
    public 필드가 있는 경우, 그 필드를 private으로 만들고, 접근자를 제공하라.

  • 동기
    • 객체 지향에서는 데이터를 절대로 public으로 하지 말라고 한다. 만약 데이터를 public으로 하면, 데이터를 가지고 있는 객체가 알지 못하는 사이에 다른 객체가 데이터 값에 접근하고 변경할 수 있게 된다.

  • 주의사항


Replace Magic Number with Symbolic Constant

  • 정의
    컬렉션(Collection)을 리턴하는 메소드가 있으면, 그 메소드가 읽기 전용 뷰(read-only view)를 리턴 하도록 만들고, add/remove 메소드를 제공하라.

  • 동기
    • 컬렉션은 다른 종류의 데이터를 다룰 때와는 약간 다른 프로토콜을 사용해야 한다.
    • get 메소드가 컬렉션 객체 자체를 리턴하면 안 되는데, 왜냐하면 이것은 클라이언트 코드가 컬렉션을 가지고 있는 클래스가 알지 못하는 사이에 컬렉션의 내용을 조작할 수 있기 때문이다.
    • 컬렉션에 대한 set 메소드가 있으면 안 된다. 대신 컬렉션에 요소(element)를 추가, 삭제하는 오퍼레이션이 잇어야 한다. 이것은 컬렉션을 가지고 있는 객체가 컬렉션에 요소를 추가, 삭제하는 작업을 제어할 수 있게 한다.

  • 주의사항

Replace Record with Data Class

  • 정의
    전통적인 프로그래밍 환경에서의 레코드 구조에 대한 인터페이스가 필요한 경우, 그 레코드를 위한 데이터 객체를 만들어라.

  • 동기
    • 레거시(legacy) 프로그램을 복사하는 경우, 전통적인 프로그래밍 API에서 사용되는 구조적 레코드 또는 데이터베이스 레코드와 통신하는 경우, 이런 외부 요소를 다루는 인터페이스 클래스를 만들면 편리하다.

  • 주의사항

Replace Type Code with Class

  • 정의
    클래스의 동작에 영향을 미치지 않는 숫자로 된 타입 코드(numeric type code)가 있으면, 숫자를 클래스로 바꾸어라.

  • 동기
    • 숫자를 클래스로 바꾼다면, 컴파일러는 클래스에 대해서 타입 체크를 할 수 있다.

  • 주의사항

Replace Type Code with Subclasses

  • 정의
    클래스의 동작에 영향을 미치는 변경 불가능한(immutable) 타입 코드가 있다면, 타입 코드를 서브클래스로 바꾸어라.

  • 동기
    • 타입 코드가 동작에 영향을 미치는 경우 대부분 switch 문이거나 if then - else 구조일 것이다. 이런 조건문은 Replace Conditional with Polymorphism을 사용하여 리팩토링 할 필요가 있다. 그러기 위해서는 타입 코드가 다형성 동작을 가지는 상속 구조로 바뀌어야 한다.
    • 또 다른 경우는, 특정 타입 코드를 가지는 객체에만 관계된 기능이 있을 때이다.

  • 주의사항
    • 객체가 생성된 다음에 그 객체의 타입 코드 값이 바뀌는 경우에는 이 리팩토링을 할 수 없다.
    • 타입 코드를 가지는 클래스가 이미 다른 이유로 서브클래스를 가지고 있는 경우에는 이 리팩토링을 할 수 없다.
    • Replace Type Code with Subclasses 는 주로  Replace Type Code with State/Strategy을 가능하게 하기 위한 발판이 된다.
    •  만약 타입 코드가 생성자로 전달된다면, 생성자를 팩토리 메소드로 바꾸어야 한다.

Replace Type Code with State/Strategy

  • 정의
    클래스의 동작에 영향을 미치는 타입 코드가 있지만 서브클래싱을 할 수 없을 때는, 타입 코드를 스테이트(State) 객체로 바꾸어라.

  • 동기
    • 객체의 존속기간 동안 타입 코드가 바뀌거나 또는 다른 이유로 서브클래싱을 할 수 없는 경우에 사용한다.

  • 주의사항

Replace Subclass with Fields

  • 정의
    상수 데이터를 리턴하는 메소드만 다른 서브클래스가 있으면, 그 메소드를 수퍼클래스의 필드로 바꾸고 서브클래스를 제거하라.

  • 동기
    • 상수 메소드만을 포함하고 있는 서브클래스는 존재할 가치가 있을 만큼 충분한 일을 하는 것이 아니다. 이런 서브클래스는 수퍼클래스에 필드를 추가하고 완전히 샂게할 수 있다. 이렇게 하며녀 서브클래스를 사용하면서 생기는 여러 복잡성을 제거할 수 있다.

  • 주의사항

'Programs > Refactoring' 카테고리의 다른 글

Refactoring - 객체간의 기능 이동  (5) 2011.11.21
Refactoring - 메소드 정리(Composing Methods)  (4) 2011.11.16
리팩토링(Refactoring)  (4) 2011.11.07
Posted by outliers
,


Move Method

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

  • 동기
    • 클래스가 너무 많은 동작을 가지고 있거나, 다른 클래스와 공동으로 일하는 부분이 너무 많아서 단단히 결합되어 있을 때 사용한다.
    • 자신이 속해 있는 클래스보다 다른 클래스를 더 많이 참조하는 메소드가 존재하면 리팩토링 한다.


  • 주의사항
    • 어떤 부분이 지금 옮기려는 메소드에서만 사용된다면, 그 부분 또한 같이 옮기는 것이 낫다.
    • 소스 클래스의 서브 클래스나 수퍼클래스에서 옮기려고 하는 메소드에 대한 다른 선언이 있다면, 다형성이 타겟 클래스에서도 역시 표현될 수 있는 경우에만 해당 메소드를 옮길 수 있을 것이다.
    • 만약 소스 메소드를 참조하는 부분이 많다면, 소스 메소드를 위임 메소드로 남겨두는 것이 더 쉬운 방법이다.
    • 소스 클래스의 일부부능 사용하려 할 때 다음 네 가지중 한 가지를 선택 할 수 있다.
      • 사용 부분을 타겟 클래스로 옮긴다.
      • 타겟 클래스에서 소스 클래스를 참조하는 부분을 새로 만들거나 사용한다.
      • 메소드에 소스 객체를 파라미터로 넘긴다.
      • 사용하려는 부분이 변수라면 파라미터로 넘긴다.

Move Field

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

  • 동기
    • 어떤 필드가 자신이 속한 클래스보다 다른 클래스의 메소드에서 더 많이 사용되고 있는 것을 보면 그 필드를 옮겨라.
    • Extract Class를 하고 있을 경우 필드를 먼저 옮기고 그 다음에 메소드를 옮겨야 한다.

  • 주의사항
    • 필드가 public으로 선언되어 있으면 Encapsulate Field를 사용한다.
    • 필드가 private로 선언되어 있지 않다면, 필드를 참조하는 부분을 찾기 위해서 소스 클래스의 모든 서브 클래스를 살펴봐야 한다.


Extract Class

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

  • 동기
    • 클래스에 많은 메소드와 데이터를 가지고 있고, 너무 커서 쉽게 이해할 수도 없을 경우 데이터의 부분 집합과 메소드의 부분 집합이 같이 몰려다니는 것은 별도의 클래스로 분리할 수 있는 좋은 신호이다.
    • 보통 같이 변하거나 특별히 서로에게 의존적인 데이터의 부분 집합 또한 별도의 클래스로 분리할 수 있다는 좋은 신호이다.

  • 주의사항
    • 클래스의 책임을 어떻게 나눌지를 결정하라. 
    • 양방향 링크가 필요할지도 모른다. 그러나 필요해지기 전에는 새로 만든 클래스에서 이전 클래스로 가는 링크를 만들지 마라.
    • 양방향 링크를 가지고 있다면, 단방향 링크로 만들 수 있는지 알아본다.


Inline Class

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

  • 동기
    • 클래스가 더이상 제 몫을 하지 못하고 더 이상 존재할 필요가 없다면 Inline Class를 사용해라.

  • 주의사항
    • 소스 클래스 메소드에 대한 인터페이스를 분리하는 것이 이치에 맞다면, 인라인화 하기 전에 Extract Interface를 사용하라.

Hide Delegate

  • 정의
  • 클라이언트가 객체의 위임 클래스를 직접 호출하고 있는 경우, 서버에 메소드를 만들어서 대리객체(delegate)를 숨겨라.

  • 동기
  • 클라이언트가 서버 객체의 필드에 들어있는 객체에 정의된 메소드를 호출한다면, 서버 객체에 간단한 위임 메소드를 두어 위임을 숨김으로서 종속성을 제거 할 수 있다.

  • 주의사항


Remove Middle Man

  • 정의
  • 클래스가 간단한 위임을 너무 많이 하고 있는 경우에는, 클라이언트가 대리객체를 직접 호출하도록 하라..

  • 동기
  • 서버 클래스에서 단지 간단한 위임 메소드가 많이 존재 하는 경우 리팩토링을 한다.

  • 주의사항


Introduce Foreign Method

  • 정의
  • 사용하고 있는 서버 클래스에 부가적인 메소드가 필요하지만 클래스를 수정할 수 없는 경우에는, 첫 번째 인자로 서버 클래스의 인스턴스를 받는 메소드를 클라이언트에 만들어라.

  • 동기
  • 꼭 필요하지만 그 클래스가 제공하지 않는 서비스가 하나 있다. 소스 코드를 변경할 수 없다면 부족한 메소드를 클라이언트쪽에 만들어야 한다.

  • 주의사항
  • 만든 메소드는 클라이언트 클래스의 어떤 부분에도 접근 해서는 안 된다. 값이 필요하다면 값을 파라미터로 넘겨야 한다.

      Introduce Local Extension

      • 정의
      • 사용하고 있는 서버 클래스에 여러 개의 메소드를 추가할 필요가 있지만 서버 클래스를 수정할 수 없는 경우, 필요한 추가 메소드를 포함하는 새로운 클래스를 만들어라. 이 확장 클래스를 원래 클래스의 서브클래스 또는 래퍼(wrapper) 클래스로 만들어라.

      • 동기
      • 꼭 필요하지만 그 클래스가 제공하지 않는 서비스가 많이 존재 하는 경우 리팩토링을 한다.

      • 주의사항
        • 서브 클래스 방식과 래퍼 방식 중 하는를 선택해야 할 때, 보통 서브클래스로 만든다.
        • 객체가 가변성(mutable)라면 래퍼를 사용해라.
        • 래퍼 클래스를 사용하는 경우 원래 클래스를 인자로 받을 때 오버라이드를 하지 말고 메소드를 추가해라.

      'Programs > Refactoring' 카테고리의 다른 글

      Refactoring - 데이터 구성  (1) 2011.11.30
      Refactoring - 메소드 정리(Composing Methods)  (4) 2011.11.16
      리팩토링(Refactoring)  (4) 2011.11.07
      Posted by outliers
      ,


      Extract Method

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

      • 동기
        • 지나치게 긴 메소드를 보거나, 또는 목적을 이해하기 위해서 주석이 필요한 코드를 보면 그 부분을 하나의 메소드로 뽑아낸다.
        • 메소드가 잘게 쪼개져 있을 때 다른 메소드에서 사용될 확률이 높아진다.
        • 고수준의 메소드를 볼 때 일련의 주석을 읽는 것 같은 느낌이 들도록 할 수 있다. 또한 메소드가 잘게 쪼개져 있을 때 오버라이드 하는 것도 훨씬 쉽다.

      • 주의사항
        • 작은 메소드는 실제로 이름을 잘 지었을 때만 그 진가가 드러나므로, 이름을 지을 때 주의해야 한다.
        • 메소드의 이름과 메소드 몸체의 의미적 차이다. 뽑아내는 것이 코드를 더욱 명확하게 하면, 새로 만든 메소드의 이름이 원래 코드의 길이보다 길어져도 뽑아낸다.
        • 메소드를 새로 만들고, 의도를 잘 나태낼 수 있도록 이름을 정한다. 어떻게 하는지를 나타내는 방식으로 이름을 정하지 말고, 무엇을 하는지를 나타내게 이름을 정한다.


      Inline Method

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

      • 동기
        메소드의 몸체가 메소드의 이름 만큼이나 명확할 때가 있다. 또는 메소드의 몸체를 메소드의 이름 만큼 명확하게 리팩토링 할 수도 있다.
        • 너무 많은 인디렉션이 사용되어 모든 메소드가 단순히 다른 메소드에 위임을 하고 있어, 그 인디렉션 속에서 길을 읽을 염려가 있을 때 사용한다.
        • 메소드가 잘못 나누어져 있을 때에도 사용할 수 있다. 이런 경우 나누어져 있는 메소드를 다시 합쳐 하나의 큰 메소드로 만든 다음, 메소드를 다시 추출한다.
        • Replace Method with Method Object를 사용하기 전에 이 리팩토링을 사용하면 좋다는 것을 알아냈다.

      • 주의사항
        메소드가 다형성을 가지고 있지 않은지 확인한다. 서브클래스에서 오버라이드하고 있는 메소드에는 적용하지 않는다. 수퍼클래스에 없는 메소드를 서브클래스에서 오버라이드 할 수는 없다.


      Inline Temp

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

      • 동기
        대부분의 경우 Inline Temp는 Replace Temp with Query의 한 부분으로 사용된다.

      • 주의사항


      Replace Temp with Query

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

      • 동기
        • 임시변수는 임시로 사용되고, 특정 부분에서만 의미를 가지므로 문제가 된다. 임시변수는 그것이 사용되는 메소드의 컨텍스트 안에서만 볼 수 있으므로, 임시변수가 사용되는 메소드는 보통 길이가 길어지는 경향이 있다.
        • 임시변수를 질의 메소드로 바꿈으로써 클래스 내의 어떤 메소드도 임시변수에 사용될 정보를 얻을 수 있다. 또한 이것은 클래스의 코드가 더 깔끔해 지도록 한다.
        • Replace Temp with Query 는 Extract Method를 적용하기 전의 필수 단계이다. 지역변수는 메소드의 추출을 어렵게 하기 때문에 가능한 많은 지역변수를 질의 메소드로 바꾸는 것이 좋다.

      • 주의사항
        • 임시변수에 값이 여러 변 대입되는 경우에는 Split Temporay Variable을 먼저 적용한다.
        • 반복문 같은 경우 이 리팩토링을 할 경우 퍼포먼스에 대해서 걱정이 될 것이다. 하지만 걱정하지 마라. 코드가 잘 분해되어 있으면, 보통 리팩토링을 하지 않았을 때에는 보지 못했을 더 강력한 최적화 방법을 찾을 수 있다. 최악의 경우라도, 임시변수를 다시 집어넣는 것은 쉽다.


      Introduce Explaining Variable

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

      • 동기
        • 수식은 매우 복잡해져 알아보기가 어려워질 수 있다. 이런 경우 임시변수가 수식을 좀더 다루기 쉽게 나누는데 도움이 될 수 있다.
        • 특히 조건문에서 각각의 조건의 뜻을 잘 설명하는 이름의 변수로 만들어 사용할 때 유용하다. 다른 경우로는 긴 알고리즘에서 각 단계의 계산 결과를 잘 지어진 이름의 임시변수로 설명할 수 있다.
        • 지역변수 때문에 Extract Method를 사용하기 어려운 경우에도 사용한다.

      • 주의사항
        Introduce Explaining Variable 보다는 Extract Method 를 사용하라. Extract Method 가 사용하기 어려울 때에만 Introduce Explaining Variable를 사용해라. 만약 Replace Method with Method Object를 사용하게 된다면 임시변수 또한 유용하다.


      Split Temporary Variable

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

      • 동기
        어떤 변수든 여러가지 용도로 사용되는 경우에는 각각의 용도에 대해 따로 변수를 사용하도록 바꾸어야 한다. 왜냐하면 하나의 임시변수를 두 가지 용도로 사용하면 코드를 보는 사람이 매우 혼란스러울 수 있다.

      • 주의사항

      Remove Assignments to Parameters

      • 정의
        파라미터에 값을 대입하는 코드가 있으면, 대신 임시변수를 사용하도록 하라.

      • 동기
        • 값에 의한 전달에서는 파라미터에 어떤 변경을 가하더라도 호출하는 루틴 쪽에는 반영되지 않는다. 참조에 의한 전달을 사용하던 사람들에게는 아마도 이것이 헷갈릴 것이다.
        • 메소드 몸체 안의 코드 자체에서도 혼동이 된다. 따라서 파라미터는 전달된 그대로 쓰는 것이 일관적인 사용법이고, 훨씬 명확하다.
        • 지역변수 때문에 Extract Method를 사용하기 어려운 경우에도 사용한다.

      • 주의사항
        자바에서는 파라미터에 값을 대입해서는 안된다.


      Replace Method with Method Object

      • 정의
        긴 메소드가 있는데, 지역변수 때문에 Extract Method를 적용할 수 없는 경우에는, 메소드를 그 자신을 위한 객체로 바꿔서 모든 지역변수가 그 객체의 필드가 되도록 한다. 이렇게 하면 메소드를 같은 객체 안의 여러 메소드로 분해할 수 있다.

      • 동기
        지역변수는 메소드를 분해할 때 어려움을 준다. 즉 지역변수가 많으면 분해가 어려워질 수 있다. Replace Temp with Query는 이런 짐을 덜도록 도와주지만, 때로는 쪼개야 하는 메소드를 쪼갤 수 없는 경우가 생길 수도 있다. 이런 경우에 사용한다.

      • 주의사항

      Substitute Algorithm

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

      • 동기
        어떤 것을 할 때건 한 가지 이상의 방법이 있게 마련이다. 그 중 어떤 것은 분명 다른 것보다 쉬울 것이다. 알고리즘에서도 마찬가지다. 어떤 것을 할 때 더 명확한 방법을 찾게 되면, 복잡한 것을 명확한 것으로 바꾸어야 한다.

      • 주의사항

      'Programs > Refactoring' 카테고리의 다른 글

      Refactoring - 데이터 구성  (1) 2011.11.30
      Refactoring - 객체간의 기능 이동  (5) 2011.11.21
      리팩토링(Refactoring)  (4) 2011.11.07
      Posted by outliers
      ,
      Refactoring 이란?
      소프트웨어를 보다 쉽게 이해할 수 있고, 적은 비용으로 수정할 수 있도록 겉으로 보이는 동작의 변화 없이 내부 구조를 변경하는 것

      핵심 정리
      • 새로운 기능을 추가해야 하는데 프로그램의 코드가 새로운 기능을 추가하기 쉽도록 구조화되어있지 않은 경우에는 먼저 리팩토링을 해서 프로그램에 기능을 추가하기 쉽게 하고, 그 다음에 기능을 추가한다.
      • 리팩토링을 시작하기 전에 견고한 테스트 세트를 가지고 있는지 확인하라. 이 테스트는 자체 검사여야 한다.
      • 리팩토링은 작은 단계로 나누어 프로그램을 변경한다. 실수를 하게 되더라도 쉽게 버그를 찾을 수 있다.
      • 컴퓨터가 이해할 수 있는 코드는 어느 바보나 다 짤 수있다. 좋은 프로그래머는 사람이 이해할 수 있는 코드를 짠다.
      • 완전하지 않은 인터페이스를 공표하지 마라. 매끄러운 리팩토링을 위해 코드 소유권 정책을 수정하라.

      왜 리팩토링을 해야 하는가?

      • 리팩토링은 소프트웨어의 디자인을 개선시킨다.
      • 리팩토링은 소프트웨어를 더 이해하기 쉽게 만든다.
      • 리팩토링은 버그를 찾도록 도와준다.
      • 리팩토링은 프로그램을 빨리 작성하도록 도와준다.


      언제 리팩토링을 해야 하는가?

      • 별도의 시간을 내는것이 아니라, 틈틈히 계속 해야 하는 것이다.
      • 어떤 것을 할 때 비슷한 어떤것을 하게 되면 리팩토링을 한다.(책에서는 3번째 부터 하라고 나와있지만 바로 한다.)
      • 기능을 추가할 때 리팩토링을 해라.
      • 버그를 수정해야 할 때 리팩토링을 하라.
      • 코드 검토(code review)를 할 때 리팩토링을 하라.
        • 읽기 어려운 프로그램은 수정하기 어렵다.
        • 중복된 로직을 가지고 있는 프로그램 수정하기 어렵다.
        • 실행중인 코드를 변경해야 하는 특별한 동작을 요구하는 프로그램은 수정하기 어렵다.
        • 복잡한 조건문이 포함된 프로그램은 수정하기 어렵다.

      언제 리팩토링을 하지 말아야 하는가?

      • 코드를 처음부터 다시 작성해야 할때
      • 마감일에 가까울 때


      리팩토링과 디자인
      리팩토링이 사전 디자인의 역할을 바꿀수 있기 때문에 간단한 솔루션을 만든 다음에 코딩을 하고 리팩토링을 한다.
      ※ 시스템이 어떻게 돌아가는지 정확하게 알고 있다 하더라도, 추측만 하지 말고 실제로 퍼포먼스를 측정해보라. 무엇인가 배울 것이고, 십중팔구는 추측이 틀렸을 것이다.

      리팩토링과 퍼포먼스
      리팩토링은 확실히 소프트웨어를 더 느리게 할 것이지만, 반면에 소프트웨어에 대한 퍼포먼스 튜닝을 더 쉽게 할 수 있도록 만든다.

       

      Posted by outliers
      ,