본문 바로가기

강의/TDD, Clean Code with Java 12기

4단계 자동차경주 (우승자) (8일차) - 피드백 반영

 

피드백 1

그리고 구조 변경 된 부분에 대한 테스트 코드가 하나도 없는데요 😨
이 부분도 추가 보완 요청 드립니다 🙇


피드백 2

굳이 이렇게 array로 변환하여 반환하신 이유가 있을까요?? 🤔
이렇게 되면 requestInput을 호출하는 RacingCarMain에서도 이와 같이
어렵게(?) 값을 꺼내야 합니다 😄

int numOfCar = raceInfo[0]; 
int numOfCycle = raceInfo[1];

저나 재영님 같은경우 코드 전체를 다 봐서 이해를 할 수 있겠지만 😄
이 코드를 개선하기 위한 다른 개발자나 동료들이 이 부분을 본다면
raceInfo에 0번째에는 무슨 값이 들어있는지, 1번에는 무슨 값이 들어있는지
더더욱 알 수 없습니다 😨

차라리 명시적으로 getNumOfCar(), getNumOfCycle() 두번 호출 하는 편이
가독성 측면에서도 더 괜찮아 보입니다 😄
이 부분 개선 검토 부탁 드립니다 🙇

그리고 반환 하실 일이 생기시더라도 array보다는 java의 좋은 Collection 들이 많이 있습니다 😄
이 부분도 참고해주시면 감사하겠습니다 🙇


피드백 3

1만 봐서는 1이 무슨 의미인지 알 수 없을 것 같습니다 😄
매직넘버 추출 부탁 드립니다 🙇

정리한번 하고 가시면 좋을 것 같아서 도움되실 만한 내용 공유 드립니다 😄

https://hoonmaro.tistory.com/44

 

    public void prepareCars() {
        carManagers = new CarManager[numOfCar];
        for (int i = 0; i < numOfCar; i++) {
            Car car = new Car(1);

피드백 4

이 부분도 한번만 초기화 될 수 있도록 정적 상수로 선언 되면 좋을 것 같습니다 😄

    private Scanner sc = new Scanner(System.in);
    private static final Scanner SC = new Scanner(System.in);

피드백 5

validInputConfirm()를 호출하기 전까지는 값에 대한 검증이 이뤄지지 않습니다 😄
값에 대한 검증은 중요한 부분이므로 객체가 생성 되는 시점에 검증이 이뤄져야 더 강한 구속력(?)을 갖게 되는데요 😄
만약 다른 개발자 분들이나 동료분들이 이 Race 객체를 가져다가 사용하면서 해당 부분들을 잊게(?) 된다면
정상동작은 기대하기 어려울 것 같습니다 😄

이 부분도 한번 개선 검토 해주시면 감사하겠습니다 🙇

public void validInputConfirm() {

피드백 6

전체적으로 array 를 사용하여서 array 컨트롤을 하기 위해 반드시 for (int i = 0; 등이 반복 되고 있습니다 😄
물론 array 도 나쁘지 않지만 아무래도 for (int i = 0 로 제어를 하다보니 반복적으로 for 문이 등장하고
index를 잘못 넣거나 하는 사람 실수(?) 등을 유발 할 수도 있습니다 😄

    private CarManager[] carManagers;
    private List<CarManager> carManagers

 for-each를 이용하여 한번 개선해보시면 좋을 것 같습니다 😄
이 부분도 검토 부탁 드립니다 🙇


validInputConfirm()를 호출하기 전까지는 값에 대한 검증이 이뤄지지 않습니다 😄
값에 대한 검증은 중요한 부분이므로 객체가 생성 되는 시점에 검증이 이뤄져야 더 강한 구속력(?)을 갖게 되는데요 😄
만약 다른 개발자 분들이나 동료분들이 이 Race 객체를 가져다가 사용하면서 해당 부분들을 잊게(?) 된다면
정상동작은 기대하기 어려울 것 같습니다 😄

이 부분도 한번 개선 검토 해주시면 감사하겠습니다 🙇

 

모든 피드백이 이해가 갔지만 validInputConfirm()을 객체가 생성할 때 검증을 하라는 것이 나에게 와 닿지 않았다.

validInputConfirm() 부분을 input 받을 때 바로 검증하는 것이 더 좋지 않을까 라는 생각이 들었다.

 

다시 생각해보니 input값을 받는 메소드도 다른 것을 사용하는 경우, 그 메소드에는 input값을 받기만 하고 validInputCheck를 진행하지 않는다면 코드 검증을 할 수 있는 방법이 없어지기 때문에 객체를 생성하는 시점에서 input값을 확인하는 것이 좋을 것 같습니다.

 

피드백을 반영한 오늘의 코드입니다.

 

package step4;

public class Car {
    private int position;

    public Car(int position) {
        this.position = position;
    }

    public void moveForward() {
        this.position++;
    }

    public int getPosition() {
        return position;
    }
}
package step4;

public class CarManager {
    private Car car;
    private RaceManager raceManager = new RaceManager();

    public CarManager(Car car) {
        this.car = car;
    }

    public void canIGo() {
        if (raceManager.judge()) {
            car.moveForward();
        }
    }

    public int getCurrCarPosition() {
        return car.getPosition();
    }
}
package step4;

import java.util.Scanner;

public class InputView {
    private static final String HOW_MANY_CAR = "자동차의 대수는 몇 대 인가요?";
    private static final String HOW_MANY_CYCLE = "시도할 횟수는 몇 회 인가요?";
    private static final int MIN_ROUND = 0;
    private static final int MIN_CAR = 0;
    private static final String CYCLE_ERROR_MESSAGE = "시도할 횟수는 0보다 커야 합니다.";
    private static final String CAR_ERROR_MESSAGE = "자동차 대수는 1대 이상이어야 합니다.";
    private static final Scanner sc = new Scanner(System.in);

    public int getNumOfCar() {
        System.out.println(HOW_MANY_CAR);
        return getInput();
    }

    public int getNumOfCycle() {
        System.out.println(HOW_MANY_CYCLE);
        return getInput();
    }

    private int getInput() {
        return sc.nextInt();
    }

    public void inputCarCheck(int numOfCar) {
        if (numOfCar <= MIN_CAR) {
            throw new IllegalArgumentException(CAR_ERROR_MESSAGE);
        }
    }

    public void inputRoundCheck(int numOfCycle) {
        if (numOfCycle <= MIN_ROUND) {
            throw new IllegalArgumentException(CYCLE_ERROR_MESSAGE);
        }
    }
}
package step4;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Race {
    private static int numOfCar;
    private static int numOfCycle;
    private static final int INIT_CAR_POSITION = 1;
    private InputView inputView = new InputView();
    private ResultView resultView = new ResultView();
    private List<CarManager> carManagers;

    public Race(int numOfCar, int numOfCycle) {
        this.numOfCar = numOfCar;
        this.numOfCycle = numOfCycle;
        validInputConfirm();
        prepareCars();
    }

    public void prepareCars() {
        carManagers = new ArrayList<>();
        for (int i = 0; i < numOfCar; i++) {
            Car car = new Car(INIT_CAR_POSITION);
            carManagers.add(new CarManager(car));
        }
    }

    public void validInputConfirm() {
        inputView.inputCarCheck(numOfCar);
        inputView.inputRoundCheck(numOfCycle);
    }

    public void playRace() {
        for (CarManager carManager: carManagers) {
            carManager.canIGo();
        }
    }

    public void printResult() {
        for (CarManager carManager: carManagers) {
            resultView.showCurrCarPosition(carManager.getCurrCarPosition());
        }
    }
}
package step4;

import java.util.Random;
import java.util.Scanner;

public class RaceManager {
    private static final int DICE_THRETHOLD = 4;
    private static Random rd = new Random();

    public boolean judge() {
        int rdNumber = rd.nextInt(10);
        if (rdNumber >= 4) {
            return true;
        }
        return false;
    }
}
package step4;

import step3.model.Car;

public class ResultView {
    public void showCurrCarPosition(int location) {
        for (int i = 0; i < location; i++) {
            System.out.print("-");
        }
        System.out.println();

    }
}
import step4.InputView;
import step4.Race;

import java.util.Scanner;

public class RacingCarMain {
    public static void main(String[] args) {
        InputView inputView = new InputView();
        int numOfCar = inputView.getNumOfCar();
        int numOfCycle = inputView.getNumOfCycle();

        Race race = new Race(numOfCar, numOfCycle);

        for (int i = 0; i < numOfCycle; i++) {
            race.printResult();
            race.playRace();
            System.out.println();
        }
        race.printResult();
    }
}