Activities/우아한 테크 프리코스

[회고록] 우아한테크 프리코스 회고록2-2

발달중인 망고 2023. 11. 2. 00:02

작성일 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 같이 이상한 코드도 생겼던 것 같습니다.

제가 실력이 부족해서 아직 명확하게 코드를 짜지 못했던 것 같네요.

먼저 이와 같은 코드 때문에  

RaceGameController 코드

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는 이렇게 바뀌었습니다.

RaceGameController 코드

여기서 조금 고민이 있었는데

  • 1. 변수할당 방식
List<String> winnerNames = result.getWinnerNames();
outputView.printWinnerResultMessage(winnerNames);
  • 2. 직접 메서드 호출방식
outputView.printWinnerResultMessage(result.getWinnerNames());

둘 중 어떤 게 코드 가독성에 더 좋을까 고민했습니다. result.getWinnerNames라는 코드 자체가 명확하고 이미 깔끔해 보였고 복잡하지 않고 비교적 간단한 상황이었기에 코드간결성을 증가시키며 가독성을 유지하는 방향으로 설정하였습니다.

 

자 다시 본론으로 돌아와서

리팩토링의 근거를 이야기해드리겠습니다.

  • 의존성 주입
    • 생성자를 통해 RacingCar에 대한 의존성을 주입하였습니다. Result는 결과를 내는 메서드이기에 Model을 주입받아 결과를 내는 동작이 더욱 자연스럽고 직관적이라고 생각했습니다.
  • 메서드와 변수명의 명확도
    • 코드 컨벤션에 부합하도록 리팩터링 했습니다.
  • findMaxDistance 삭제
    • 너무 효율성 없는 분리라고 생각했습니다.

이렇게 생각하고 리팩토링 하게 되었는데 꽤,,, 만족스러운 것 같기도,,,? 해서,,,? 글로 남기게 되었습니다.

더욱 발전시킬 사항이 있다면 이야기해 주시면 감사하겠습니다. 감사합니다!