우테코 첫 과제로는 프리코스때 진행 했던 자동차 경주를 페어프로그래밍 하는 것이었다.
초반에 구조를 잡지 않고 시작해서 중간에 많이 애먹었지만 구현을 목적으로 코딩하여 시간 안에 완성할 수 있었다.
move() {
if (Random.randomNum() >= 4) {
return this.#moveTrace.push(true);
}
return this.#moveTrace.push(false);
}
->
move(random) {
if (random >= 4) {
return this.#moveTrace.push(true);
}
return this.#moveTrace.push(false);
}
move 라는 함수를 테스트 하기 위해 randomNum
이라는 함수를 모킹해야했는데, 그렇게 하기 위해 *번거로운 작업을 거쳤다. 모킹함수를 없애기 위해 random 을 인수로 넘겨 모킹하지 않도록 수정했다.
Random.randomNum = jest.fn();
randomNum is readOnly
라는 에러 발생한 이유가 무엇일까?(해당 함수를 클래스로 수정 후 내부에 static 함수로 만들어주어 겨우 테스트를 통과시킬 수 있었다..)Random.randomNum = jest.fn();
와 같이 특정 함수만 모킹함수로 대체하는 방법은 허용하지 않는다고 함. 😊 💬 모킹하기 위해서는 import 해주는 모듈 전체를 함께 모킹해야 동작할 것 같아요
stackoverflow 참고하기!
😊 💬 입출력, 특히나 콘솔기반으로 입력을 받고 출력을 하는 부분은 자바스크립트 노드 환경 자체의 기능이기 때문에, 테스트를 하는 의미가 없어 보임. 입출력의 책임을 온전히 노드 환경에 맡기려면 입출력(UI)과 도메인의 책임이 완전히 분리되어야 할 것.따라서 개발자가 테스트해야 할 대상은 개발자가 직접 작성한 도메인 영역 뿐이라고 생각함.
-> 외부환경과 내가 작성한 코드의 분리!!내가 작성한 코드만 테스트!!
경계값 테스트
테스트 할 때는 범위 내의 숫자 모두를 사용하기보다 경계값만 테스트 해줘도 충분하다고 생각.
추후 확장 가능성이 있는 부분은 함수로 나눠주기~
(페어가 받은 리뷰) map은 배열의 각 요소를 변환하여 새 배열을 생성할 때 사용함. 그래서 단순 순환을 할 때는 forEach 사용하기!
패키지 매니저 통일하기.
기존에 설치되어 있던 패키지 매니저는 yarn 이었는데 npm 을 사용해서 섞여있었음. -> packagelock.json 지우고 yarn 으로 통일
yarn, npm , pnpm 비교하기
boolean 값이 반환되는 함수의 경우 앞에 is, has, should, can
등의 접두사 붙이기
리스트 네이밍 고민해보기
ㄴ 멘토님이 보여주신 토스페이먼츠 테크피드에서 올라온 논의 내용
내가 네이밍 한 것을 보면 -List 와 -s 둘 다 사용하고 있어서 하나로 통일해야겠고, api 만큼 타입 변경이 큰 영향을 미치지는 않겠지만 도메인 관점에서 네이밍을 하는게 좋다 라는게 인상깊었던것같다.
😊 💬 현재는 해시의 input 클래스가 컨트롤러의 역할까지 일부분 부담하고 있는 것 같아보입니다.
저는 컨트롤러의 역할은 말그대로 UI 와 도메인을 연결해주는 역할이라고 생각하고 UI 클래스들의 역할은 단순히 사용자 인터페이스와 관련된 역할(입,출력)에만 제한되어야 한다고 생각합니다.
view 에서 도메인 하위 모듈에 접근하고 있는 부분도 잘못된 방향의 참조인 것 같고 , 어찌보면 input 의 유효성 검증도 도메인 영역과 관련된 것이기 때문에, 유효성 검증 처리는 외부에서 해주도록 리팩토링 해보면 좋을 것 같다고도 생각이 들어요.
그래서 input 에 있던 유효성검사를 raceController 의 input 메소드에서 검사할 수 있도록 수정해주었다.
// input 클래스
class Input {
static carNameInput = async () => {
const carList = await ReadLine.readLineAsync(INPUT_CAR_NAMES);
return carList;
};
...
// raceController 클래스
async race() {
const { cars, tryNumber } = await this.#input();
this.#controlCarMove(cars, tryNumber);
const raceWinner = new RaceWinner(this.#carsMoveInfoList).getRaceWinner();
this.#print(tryNumber, raceWinner);
}
async #input() {
const cars = await this.#carsInput();
const tryNumber = await this.#tryNumberInput();
return { cars, tryNumber };
}
async #carsInput() {
try {
const carList = await Input.carNameInput();
const cars = this.#carsValidation(carList);
return cars;
} catch (error) {
console.log(error.message);
return this.#carsInput();
}
}