관리 메뉴

너와 나의 스토리

[리팩토링] Change Function Declaration 함수 선언 바꾸기 본문

개발/Refactoring

[리팩토링] Change Function Declaration 함수 선언 바꾸기

노는게제일좋아! 2021. 10. 3. 23:14
반응형

배경

  • 예: 대여한 지 30일이 지났는지를 기준으로 지불 기한이 넘었는지를 판단하는 간단한 함수가 있다.
  • 이 함수의 매개변수는 지불 객체가 적절할까, 아니면 마감일이 적절할까?
    • 지불 객체로 설정하는 경우
      • 이 함수는 지불 객체의 인터페이스와 결합돼버린다.
      • 대신 지불이 제공하는 여러 속성에 쉽게 접근할 수 있어서 내부 로직이 복잡해지더라도 이 함수를 호출하는 코드를 일일이 찾아서 변경할 필요가 없다.
      • 실질적으로 함수의 캡슐화 수준이 높아지는 것
    • 지불 객체가 적절할지 마감일이 적절할지에 대한 문제의 정답은 없다. 
      • 그래서 "함수 선언 바꾸기" 리팩터링을 진행하며 코드를 개선해 나가야 한다.
        • 함수 선언 바꾸기: 함수명 + 매개변수 수정

 

 

절차

간단한 절차

  • 함수 선언과 호출문들을 단번에 고칠 수 있는 간단한 상황일 때 이 절차를 따른다.
  • 절차
    1. 매개변수를 제거하려거든 먼저 함수 본문에서 제거 대상 매개변수를 참조하는 곳은 없는지 확인
    2. 메서드 선언을 원하는 형태로 바꿈
    3. 기존 메서드 선언을 참조하는 부분을 모두 찾아서 바뀐 형태로 수정
    4. 테스트
  • 이름 변경과 매개변수 수정을 모두 하고 싶다면 각각을 독립적으로 나눠서 처리하자.
  • 예시
    • 함수 이름이 너무 축약된 경우
      • double circum(double radius) {
            return 2 * Math.PI * radius;
        }
      • circum: 둘레를 두르다
    • 1. 먼저 함수 선언부터 수정하자
      • double circumference(double radius) {
            return 2 * Math.PI * radius;
        }
      • circumference: 원주, 원의 둘레
    • 2. 그 후 circum()을 호출한 곳을 모두 찾아서 circumference()로 바꾼다.
    • 매개변수 수정도 똑같이 처리하면 된다.

 

 

마이그레이션 절차

  • 마이크레이션 절차를 따라야 하는 상황
    • 호출하는 곳이 많거나, 호출 과정이 복잡하거나, 호출 대상이 다형 메서드거나, 선언을 복잡하게 변경하는 경우
    • 예: changeAddress()란 메서드가 사람 클래스와 계약 클래스 모두에 정의되어 있는데, 사람 클래스의 메서드만 이름을 바꾸고 싶은 경우
  • 절차
    1. 이어지는 추출 단계를 수월하게 만들기 위해 함수의 본문을 적절히 리팩터링
    2. 함수 본문을 새로운 함수로 추출
      • 새로 만들 함수 이름이 기존 함수와 같다면 일단 검색하기 쉬운 이름을 임시로 붙여둔다.
        • 예: 매개변수만 바꾸는 경우
    3. 추출한 함수에 매개변수를 추가해야 한다면 '간단한 절차'를 따라 추가한다.
    4. 테스트
    5. 기존 함수를 인라인
    6. 이름을 임시로 붙여뒀다면 함수 선언 바꾸기를 한 번 더 적용해서 원래 이름으로 되돌린다.
    7. 테스트
  • 예시 1
    • 함수 이름이 너무 축약된 경우
      • double circum(double radius) {
            return 2 * Math.PI * radius;
        }
    • 2. 먼저 함수 본문 전체를 새로운 함수로 추출
      • double circum (double radius) {
            return circumference(radius);
        }
            
        double circumference (double radius) {
            return 2 * Math.PI * radius;
        }
    • 4. 수정한 코드를 테스트
    • 5. 예전 함수를 인라인
      • 즉, circum()을 호출하던 곳에서 수정한 함수인 circumference()를 호출하도록 수정
    • 7. 테스트 
    • 8. 테스트 성공하고 모두 변경을 완료하였다면 기존 함수를 삭제한다.
  • 예시 2
    • 매개변수 변경하기
      • 변경 전
        • boolean inNewEngland (Customer customer) {
              return Arrays.asList("NA", "CT", "ME", "VT", "NH", "RI").contains(customer.address.state);
          }
      • 변경 후
        • boolean inNewEngland (String stateCode) {
              return Arrays.asList("NA", "CT", "ME", "VT", "NH", "RI").contains(stateCode);
          }
    • Step 1: 함수 본문 리팩토링
      • 이후 작업인 추출 단계가 수월해지도록 본문을 먼저 리팩터링
      • boolean inNewEngland (Customer customer) {
            const stateCode = customer.address.state;
            return Arrays.asList("NA", "CT", "ME", "VT", "NH", "RI").contains(stateCode);
        }
    • Step 2, 3: 함수 추출 및 새로운 함수에 매개변수 수정
      • 새 함수를 검색하기 좋은 이름으로 만들어 둔다.
      • boolean inNewEngland(Customer customer) {
            const stateCode = customer.address.state;
            return xxinNewEngland(stateCode);
        }
        
        boolean xxinNewEngland (String stateCode) {
            return Arrays.asList("NA", "CT", "ME", "VT", "NH", "RI").contains(stateCode);
        }
    • Step 4: 테스트
    • Step 5: 함수 인라인
      • // 호출문
        Customer newEnglandeers = someCustomers.filter(c -> xxinNewEngland(c.address.state));
    • Step 6: 임시로 붙여둔 함수 이름을 원래대로 수정
      • boolean inNewEngland (String stateCode) {
            return Arrays.asList("NA", "CT", "ME", "VT", "NH", "RI").contains(stateCode);
        }
        
        // 호출문
        Customer newEnglandeers = someCustomers.filter(c -> inNewEngland(c.address.state));

 

출처:

- [리팩터링 2판]

반응형
Comments