[회고록] 우아한테크 프리코스 회고록2-2
작성일 10월 31일 AM 02:18
양이 엄청많아서 카톡에 회고를 그때그때 적어놨습니다.ㅠㅠㅠ
이제는 조금 회고록도 대충 쓰기 싫어서 콘셉트를 하나 잡고 쓰려고 하는데요.
오늘 주제는 Refactoring입니다. 음 Car , RacingCars, Result 총 3가지 모델로 이번 과제를 구성하였는데요.
Result Model을 중심으로 이야기해보겠습니다.
Refacrtor 전 Code
package racingcar.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Result {
private List<String> winnerNameList;
private int winnerDistance;
public Result() {
winnerNameList = new ArrayList<>();
}
public void findWinnerDistance(RacingCars cars) {
for (Car car : cars.getAllCars()) {
winnerDistance = findMaxDistance(car.getCurrentPosition());
}
}
private int findMaxDistance(int currentPosition) {
return Math.max(currentPosition, winnerDistance);
}
public List<String> winnerNameList(RacingCars cars) {
for (Car car : cars.getAllCars()) {
if (winnerDistance == car.getCurrentPosition()) {
winnerNameList.add(car.getName());
}
}
return Collections.unmodifiableList(winnerNameList);
}
}
추가된 요구 사항
- indent(인덴트, 들여 쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
- 예를 들어 while문 안에 if문이 있으면 들여 쓰기는 2이다.
- 힌트: indent(인덴트, 들여 쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
- 3항 연산자를 쓰지 않는다.
- 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.
이와 같은 요구사항이 있었기 때문에 findMaxDistance 같이 이상한 코드도 생겼던 것 같습니다.
제가 실력이 부족해서 아직 명확하게 코드를 짜지 못했던 것 같네요.
먼저 이와 같은 코드 때문에
Controller에서 이렇게 코드 수가 길어지고 메서드 이름을 통해 무엇을 하는지는 알 수 있지만 매우 난잡해 보였습니다.
Result는 결과를 반환해 주는 Model임으로 RacingCars가 가지고 있는 데이터가 필요했는데요.
다음과 같은 생각을 하며 코드를 바꿔 보았습니다.
- Controller에 동작을 깔끔하게 표시할 수 있도록 하자
- 데이터를 외부에서 바꿀 수 없도록 신경 쓰자
- 코드의 목적성과 책임을 명확히 할 수 있도록 신경 써 보자
Refacrtor 후 Code
package racingcar.model;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Result {
private final List<String> winnerNames;
private final int winnerDistance;
public Result(RacingCars cars) {
this.winnerDistance = findWinnerDistance(cars);
this.winnerNames = findWinnerNames(cars);
}
private int findWinnerDistance(RacingCars cars) {
int maxDistance = 0;
for (Car car : cars.getAllCars()) {
maxDistance = Math.max(car.getCurrentPosition(), maxDistance);
}
return maxDistance;
}
private List<String> findWinnerNames(RacingCars cars) {
List<String> winnerNames = new ArrayList<>();
for (Car car : cars.getAllCars()) {
if (winnerDistance == car.getCurrentPosition()) {
winnerNames.add(car.getName());
}
}
return winnerNames;
}
public List<String> getWinnerNames() {
return Collections.unmodifiableList(winnerNames);
}
}
리펙토링 한 코드이며 Controller는 이렇게 바뀌었습니다.
여기서 조금 고민이 있었는데
- 1. 변수할당 방식
List<String> winnerNames = result.getWinnerNames();
outputView.printWinnerResultMessage(winnerNames);
- 2. 직접 메서드 호출방식
outputView.printWinnerResultMessage(result.getWinnerNames());
둘 중 어떤 게 코드 가독성에 더 좋을까 고민했습니다. result.getWinnerNames라는 코드 자체가 명확하고 이미 깔끔해 보였고 복잡하지 않고 비교적 간단한 상황이었기에 코드간결성을 증가시키며 가독성을 유지하는 방향으로 설정하였습니다.
자 다시 본론으로 돌아와서
리팩토링의 근거를 이야기해드리겠습니다.
- 의존성 주입
- 생성자를 통해 RacingCar에 대한 의존성을 주입하였습니다. Result는 결과를 내는 메서드이기에 Model을 주입받아 결과를 내는 동작이 더욱 자연스럽고 직관적이라고 생각했습니다.
- 메서드와 변수명의 명확도
- 코드 컨벤션에 부합하도록 리팩터링 했습니다.
- findMaxDistance 삭제
- 너무 효율성 없는 분리라고 생각했습니다.
이렇게 생각하고 리팩토링 하게 되었는데 꽤,,, 만족스러운 것 같기도,,,? 해서,,,? 글로 남기게 되었습니다.
더욱 발전시킬 사항이 있다면 이야기해 주시면 감사하겠습니다. 감사합니다!