1단계 미션을 진행하며, 로또를 만드는 역할을 하는 LottoFactory 라는 클래스에서 로또가 생성되는지 확인하는 테스트 1개를 진행했었다.
그런데 추후에 다른 테스트를 진행할 수 있을 것 같아서 LottoFactory 를 전역변수로 선언했었다.
public class LottoFactoryTest {
private LottoFactory lottoFactory;
//test 1개
}
여기에 루피가 책의 내용을 인용하여 리뷰를 주셨는데, 내용은 아래와 같다.
개발자는 "코드는 나중에 정리하면 돼. 당장은 시장에 출시하는게 먼저야!" 라는 흔해 빠진 거짓말에 속는다. 이렇게 속아 넘어간 개발자라면 나중에 코드를 정리하는 경우는 한 번도 없는데, 시장의 압박은 절대로 수그러들지 않기 때문이다. '시장 출시가 먼저'라는 생각을 하는 이유는 바로 뒤에 여러 무리의 경쟁자가 뒤쫓고 있고, 경쟁자보다 앞서가려면 가능한 한 빠르게 달려야 하기 때문이다. - 클린 아키텍쳐 11
루피 : 비즈니스 변화 속도가 빠르다면 코드를 작성하는 시점에 미래를 예측한 코드를 작성한다고 해도 미래의 어느 시점이 오면 예측하여 작성했던 코드도 의미가 없어질 가능성이 높아질 것 같다. 구현과 설계를 구분하여, 미래에 생길 변화 혹은 필요성에 대해서는 구현보다 설계로 대응하려고 하는편.
내가 이해한대로 요약하자면, 현실은 예측이 불가능한데, 아무리 미래를 예측하는 코드를 작성해도 나의 예상대로 현실이 흘러가지 않을 수 있다.
따라서 예측가능하다고 착각하는 코드보다는 현재 시점의 비지니스를 표현할 수 있는 코드들만 작성하자.
void generateLottoByMoney() {
String purchaseMoney = "14000";
Money money = Money.from(purchaseMoney);
LottoFactory lottoFactory = new LottoFactory();
assertThat(lottoFactory.generateLottoTicket(money).size()).isEqualTo(Integer.parseInt(purchaseMoney) / 1000);
}
then을 확인하는 줄에서 isEqualTo 메소드 내부에 Integer.parseInt(purchaseMoney) / 1000
이렇게 한눈에 볼 수 있는 값이 아닌 계산해야하는 값을 넣었다.
이렇게 하면 비교해야하는 값을 바로 알기 어렵다.
main 코드 뿐만 아니라, test코드를 내가 아닌 다른 사람들도 쉽게 알아 볼 수 있도록 작성하는 것도 명심하자! 🙂
아래와 같은 부분을 test할 때였는데, 로또 숫자가 6개인지 확인하는 테스트를 진행하는데 터무니없이 개수가 4개 막 이렇게 작성했던 적이 있었다...
@Test
@DisplayName("입력한 숫자의 수가 7개인 경우")
public void checkManualLottoSize_1() {
//given
int autoLottoCount = 0;
List<List<Integer>> inputManualLotto = Collections.singletonList(
Arrays.asList(8, 21, 23, 37, 41, 42, 45)
);
//when and then
assertThatThrownBy(() -> lottoFactory.generateLottos(autoLottoCount, inputManualLotto))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("로또 번호는 6개의 숫자여야 합니다");
}
validate할 때는 항상 무엇을 검사해야하는지 생각하고 그에 대한 경계값을 테스트하자!
public class Lotto {
private final List<Integer> lotto;
public Lotto(final List<Integer> lotto) {
this.lotto = new ArrayList<>(lotto);
}
public List<LottoNumber> getLotto() {
return Collections.unmodifiableList(lotto);
}
}
일급 컬렉션 보호를 위해 방어적 복사와 Unmodifiable Collection 모두 사용한다면 생성자에서 Collection.copyOf를 사용하자
public class Lotto {
private final List<Integer> lotto;
public Lotto(final List<Integer> lotto) {
this.lotto = List.copyOf(lotto);
}
public List<LottoNumber> getLotto() {
return lotto;
}
}