1. 알고자 하는 것
- 메서드를 추출할 때(Extract method), 해당 메서드에 넘겨야 하는 매개변수가 많아질 경우의 리팩토링
1. 임시 변수를 질의 함수로 바꾸기 (Replace Temp with Query)
2. 매개변수 객체 만들기 (Introduce Parameter Object)
3. 객체 통째로 넘기기 (Preserve Whole Object)
2. 알게된 것
매개변수 객체 만들기 (Introduce Parameter Object)
- 같은 매개변수 패턴이 여러 메서드에 걸쳐 나타난다면, 그 매개변수들을 묶은 자료구조를 만들 수 있다.
- 이를 통해 해당 데이터간의 관계를 보다 명시적으로 나타낼 수 있다. (클래스명을 명시적으로 지정할 수 있으므로)
- 함수에 전달할 매개변수 개수를 줄일 수 있다.
- 도메인을 이해하는데 중요한 역할을 하는 클래스로 추후 발전할 수 있다.
// 추출한 메서드 1 (매개변수 구조에 주목)
private double getRate(int totalNumberOfEvents, Participant p) {
long count = p.homework().values().stream()
.filter(v -> v == true)
.count();
double rate = count * 100 / totalNumberOfEvents;
return rate;
}
// 추출한 메서드 2 (매개변수 구조에 주목)
private String checkMark(int totalNumberOfEvents, Participant p) {
StringBuilder line = new StringBuilder();
for (int i = 1 ; i <= totalNumberOfEvents ; i++) {
if(p.homework().containsKey(i) && p.homework().get(i)) {
line.append("|:white_check_mark:");
} else {
line.append("|:x:");
}
}
return line.toString();
}
- 위와 같이 짧은 메서드를 구성하기 위해 코드를 메서드로 추출했을 때, 반복되는 매개변수 패턴이 발견될 수 있다.
- 이럴 때, 해당하는 int totalNumberOfEvents, Participant p를 field로 가지는 새로운 자료구조(클래스)를 만든다.
public record ParticipantPrinter(int totalNumberOfEvents, Participant p) {
}
- 이 때, JDK 16버전에서 정식으로 추가된 record 클래스를 사용한다면 toString, getter, setter 등이 포함된 불변객체를 쉽게 만들 수 있다.
private double getRate(ParticipantPrinter participantPrinter) {
long count = participantPrinter.p().homework().values().stream()
.filter(v -> v == true)
.count();
double rate = count * 100 / participantPrinter.totalNumberOfEvents();
return rate;
}
private String checkMark(ParticipantPrinter participantPrinter) {
StringBuilder line = new StringBuilder();
for (int i = 1 ; i <= participantPrinter.totalNumberOfEvents() ; i++) {
if(participantPrinter.p().homework().containsKey(i) && participantPrinter.p().homework().get(i)) {
line.append("|:white_check_mark:");
} else {
line.append("|:x:");
}
}
return line.toString();
}
// 위 메서드를 사용할 때는 아래와 같이 호출한다.
String markdown = checkMark(new ParticipantPrinter(totalNumberOfEvents, p));
- 기존 int totalNumberOfEvents, Participant p 패턴으로 구성된 매개변수를 새롭게 정의한 ParticipantPrinter로 바꾼다.
- 매개변수의 개수가 2개 -> 1개로 감소했다.
- (+) totalNumberOfEvents가 외부에서 지정해준 초기값에서 변하지 않는 성질을 가지고, 전역적으로 해당 변수가 활용된다면 해당 클래스의 field로 두는 방법도 있다.
- (+) 이 때는 생성자를 통해 totalNumberOfEvents를 받아올 수 있다.
- (+) 이 때 주의할 점은, field로 선언하게 되면 클래스 내부에 공유하는 데이터가 하나 더 생기는 것이므로 적절하게 판단하여 결정해야 한다.
3. 정리
- 메서드를 추출할 때(Extract method), 해당 메서드에 넘겨야 하는 매개변수가 많아질 경우의 리팩토링 방법은 크게 3가지가 있다.
- 그 중 하나는, 매개변수 객체 만들기 (Introduce Parameter Object) 이다.
- 같은 매개변수 패턴이 여러 메서드에 걸쳐 나타난다면, 그 매개변수들을 묶은 자료구조를 만듦으로써 매개변수의 개수를 줄인다.
- 매개변수 데이터와의 관계를 명시적으로 나타낼 수 있다.
- 도메인을 이해하는데 중요한 역할을 하는 클래스로 추후 발전할 수 있다.
- 매개변수가 외부에서 지정한 초기값에서 불변 성질을 가지고, 전역적으로 매개변수가 사용된다면 클래스의 field로 두는 방법도 있다.
Reference
'Clean Code' 카테고리의 다른 글
Java 리팩토링 - 조건문 분해하기 (0) | 2023.10.31 |
---|---|
Java 리팩토링 - 함수를 명령(Command)으로 바꾸기 (0) | 2023.10.06 |
Java 리팩토링 - 메서드 추출 시 매개변수가 많아질 경우 [3. 객체 통째로 넘기기] (0) | 2023.09.26 |
Java 리팩토링 - 메서드 추출 시 매개변수가 많아질 경우 [1. 임시 변수를 질의 함수로 바꾸기] (0) | 2023.06.20 |
Java 리팩토링 - 짧은 메서드 vs 긴 메서드 & Extract Method (0) | 2023.06.20 |