이 글은 리팩터링 2판(마틴 파울러) 책을 참고하였습니다.
순서
I. 배경
II. 절차
III. 예시
IV. 기타
I. 배경
복잡한 조건부 로직은 코드를 이해하기도 어렵게 만드는 가장 흔한 원흉이다.
그 이유는 "왜" 일어나는지를 제대로 표현해주지 못해서이다.
따라서 각 조건절을 명확한 이름의 함수로 추출하자.
II. 절차
1. 조건식과 그 조건식에 딸린 조건절 각각을 함수로 추출한다.
III. 예시
원본 코드
#include "gtest/gtest.h"
struct Plan {
int summer_start;
int summer_end;
float summer_rate;
float regular_rate;
int regular_service_charge;
};
Plan plan = {601, 831, 1, 1.2, 800};
// 함수 내부의 조건문을 바꾸자
int GetCharge(int date, int quantity) {
int charge = 0;
if ((date >= plan.summer_start) && (date <= plan.summer_end)){charge = quantity * plan.summer_rate;
} else {
charge = quantity * plan.regular_rate + plan.regular_service_charge;}
return charge;
}
TEST(DecomposeConditional, GetCharge_IsAfter531) {
int quantity = 10000;
int date = 531;
ASSERT_EQ(12800, GetCharge(date, quantity));
}
TEST(DecomposeConditional, GetCharge_IsAfter601) {
int quantity = 10000;
int date = 601;
ASSERT_EQ(10000, GetCharge(date, quantity));
}
TEST(DecomposeConditional, GetCharge_IsBefore831) {
int quantity = 10000;
int date = 831;
ASSERT_EQ(10000, GetCharge(date, quantity));
}
TEST(DecomposeConditional, GetCharge_IsBefore901) {
int quantity = 10000;
int date = 901;
ASSERT_EQ(12800, GetCharge(date, quantity));
}
1. 조건문 로직을 명확히 분해하기
// struct Plan 및 TEST코드 생략
#include "gtest/gtest.h"
struct Plan;
Plan plan = {601, 831, 1, 1.2, 800};
bool isSummer(int date) { /* 1. 조건문 분해 */
return ((date >= plan.summer_start) && (date <= plan.summer_end))
}
int GetCharge(int date, int quantity) {
int charge = 0;
if (isSummer(date)){ /* 1. isSummer()의 함수로 "왜" 일어나는지 말해줌 */
charge = quantity * plan.summer_rate;
} else {
charge = quantity * plan.regular_rate + plan.regular_service_charge;}
return charge;
}
2. 결과값의 로직도 함수로 추출한다.
// struct Plan 및 TEST코드 생략
#include "gtest/gtest.h"
struct Plan;
Plan plan = {601, 831, 1, 1.2, 800};
bool isSummer(int date) { /* 1. 조건문 분해 */
return ((date >= plan.summer_start) && (date <= plan.summer_end))
}
float getSummerCharge() { /* 2. 조건 결과 로직 분리 */
return quantity * plan.summer_rate;
}
float getRegularCharge() { /* 2. 조건 결과 로직 분리 */
return quantity * plan.regular_rate + plan.regular_service_charge;
}
int GetCharge(int date, int quantity) {
int charge = 0;
if (isSummer(date)){ /* 1. isSummer()의 함수로 "왜" 일어나는지 말해줌 */
charge = getSummerCharge; /* 2. 조건 결과 로직 분리 */
} else {
charge = getNormalCharge; /* 2. 조건 결과 로직 분리 */
}
return charge; /* charge 변수 안쓰고 if else에서 바로 return 가능 */
}
IV. 기타
무엇이든 명확한 이름의 함수 쪼개기가 가장 중요한 듯 하다.
'Programming > Refactoring(C++)' 카테고리의 다른 글
[Refactoring] 6. 매개변수를 질의함수로 바꾸기 (For Long Parameter) (0) | 2022.10.18 |
---|---|
[Refactoring] 5. 반복문 쪼개기 (For Long Function Smell) (0) | 2022.10.17 |
[Refactoring] 3. 함수를 명령으로 바꾸기 (For Long Function Smell) (0) | 2022.10.17 |
[Refactoring] 2. 임시변수를 질의함수로 바꾸기 (For Long Function Smell) (0) | 2022.10.16 |