반응형
- 어떤 함수에 매개변수가 많을수록 함수의 역할을 이해하기 어려워진다
- 그 함수는 한가지 일을 하고 있는게 맞는가?
- 불필요한 매개변수는 없는가?
- 하나의 레코드를 뭉칠 수 있는 매개변수 목록은 없는가?
- 어떤 매개변수를 다른 매개변수를 통해 알아낼 수 있다면, “매개변수를 질의 함수로 바꾸기”를 사용할 수 있다
- 기존 자료구조에서 세부적인 데이터를 가져와서 여러 매개변수로 넘기는 대신,”객체 통째로 넘기기”를 사용할 수 있다
- 일부 매개변수들이 대부분 같이 넘겨진다면, “매개변수 객체 만들기”를 적용할 수 있다
- 매개변수가 플래그로 사용된다면, “플래그 인수 제거하기”를 사용할 수 있다
- 여러 함수가 일부 매개변수를 공통적으로 사용한다면 “여러 함수를 클래스 묶기”를 통해매개변수를 해당 클래스의 필드로 만들고 매서드에 전달해야 할 매개변수 목록을 줄일 수 있다.
매개변수를 질의 함수로 바꾸기
- 함수의 매개변수 목록은 함수의 다영성을 대변하며, 짧을수록 이해하기 좋다
- 어떤 한 매개변수를 다른 매개변수를 통해 알아낼 수 있다면 “중복 매개변수”라 생각할 수 있다.
- 매개변수에 값을 전달하는 것은 “함수를 호출하는 쪽”의 책임이다. 가능하면 함수를 호출하는 쪽의 책임을 줄이고 함수 내부에서 책임지도록 노력한다
- “임시 변수를 질의 함수로 바꾸기”와 “함수 선언 변경하기”를 통해 이 리팩토링을 적용한다.
리팩토링 전
public class Order {
private int quantity;
private double itemPrice;
public Order(int quantity, double itemPrice) {
this.quantity = quantity;
this.itemPrice = itemPrice;
}
public double finalPrice() {
double basePrice = this.quantity * this.itemPrice;
int discountLevel = this.quantity > 100 ? 2 : 1;
return this.discountedPrice(basePrice, discountLevel);
}
private double discountedPrice(double basePrice, int discountLevel) {
return discountLevel == 2 ? basePrice * 0.9 : basePrice * 0.95;
}
}
- int discountLevel 매개변수는 중복 매개변수로 함수로 따로 빼내야한다.
- 함수로 따로 빼서 그 함수가 책임을가지게 하고 가능하면 함수를 호출하는쪽이 책임을 줄이고 함수 내부에서 책임을 가지게 한다.
리팩토링 후
public class Order {
private int quantity;
private double itemPrice;
public Order(int quantity, double itemPrice) {
this.quantity = quantity;
this.itemPrice = itemPrice;
}
public double finalPrice() {
double basePrice = this.quantity * this.itemPrice;
return this.discountedPrice(basePrice );
}
private int discountLevel() {
return this.quantity > 100 ? 2 : 1;
}
private double discountedPrice(double basePrice) {
return discountLevel() == 2 ? basePrice * 0.90 : basePrice * 0.95;
}
}
플래그 인수제거
- 플래그는 보통 함수에 매개변수로 전달해서, 함수 내부의 로직을 분기하는데 사용한다.
- 플래그를 사용한 함수는 차이를 파악하기 어렵다
- bookConcert ( customer, false ), bookConcert( customer, true)
- bookConcert ( customer ), premuimBookConcert ( customer)
- 조건문 분해하기 ( Decompose Condition ) 를 활용할 수 있다.
매개변수를 플래그라고 불린다.
리팩토링 전
public class Shipment {
public LocalDate deliveryDate(Order order, boolean isRush) {
if (isRush) {
int deliveryTime = switch (order.getDeliveryState()) {
case "WA", "CA", "OR" -> 1;
case "TX", "NY", "FL" -> 2;
default -> 3;
};
return order.getPlacedOn().plusDays(deliveryTime);
} else {
int deliveryTime = switch (order.getDeliveryState()) {
case "WA", "CA" -> 2;
case "OR", "TX", "NY" -> 3;
default -> 4;
};
return order.getPlacedOn().plusDays(deliveryTime);
}
}
}
class ShipmentTest {
@Test
void deliveryDate() {
LocalDate placedOn = LocalDate.of(2021, 12, 15);
Order orderFromWA = new Order(placedOn, "WA");
Shipment shipment = new Shipment();
assertEquals(placedOn.plusDays(1), shipment.deliveryDate(orderFromWA, true));
assertEquals(placedOn.plusDays(2), shipment.deliveryDate(orderFromWA, false));
}
}
int deliveryTime = switch (order.getDeliveryState()) {
case "WA", "CA", "OR" -> 1;
case "TX", "NY", "FL" -> 2;
default -> 3;
- 빠른 배송을 선택 했을때 WA, CA, OR 하루 , TX NY FL 2일 , 나머지는 3일
- 그냥 배송을 선택 했을떄 WA,CA 2일 OR, TX, NY 3일 나머지 4일
- 각각의 조건의 액션들을 메서드로 분리하자
리팩토링 후
public class Shipment {
private LocalDate regularDeliveryDate(Order order) {
int deliveryTime = switch (order.getDeliveryState()) {
case "WA", "CA" -> 2;
case "OR", "TX", "NY" -> 3;
default -> 4;
};
return order.getPlacedOn().plusDays(deliveryTime);
}
private LocalDate rushDeliveryDate(Order order) {
int deliveryTime = switch (order.getDeliveryState()) {
case "WA", "CA", "OR" -> 1;
case "TX", "NY", "FL" -> 2;
default -> 3;
};
return order.getPlacedOn().plusDays(deliveryTime);
}
}
class ShipmentTest {
@Test
void deliveryDate() {
LocalDate placedOn = LocalDate.of(2021, 12, 15);
Order orderFromWA = new Order(placedOn, "WA");
Shipment shipment = new Shipment();
assertEquals(placedOn.plusDays(1), shipment.rushDeliveryDate (orderFromWA));
assertEquals(placedOn.plusDays(2), shipment.regularDeliveryDate (orderFromWA));
}
}
리팩토링 전보다 명시적으로 코드가 잘 보이고 어떤기능을 하고 무엇을 위해 만든 코드인지 알기 쉬워졌다.
'Language > Java' 카테고리의 다른 글
Eclipse에 Azure 설치 하기 (0) | 2022.10.27 |
---|---|
엔티티의 생명주기 (0) | 2022.10.10 |
긴 함수(2) (0) | 2022.08.14 |
[리팩토링] 긴 함수 (0) | 2022.08.06 |
Optional (0) | 2022.07.02 |