본문 바로가기
생각정리

[우아한테크코스 5기] 프리코스 4주차 다리 건너기 미션 학습 내용 및 회고

by greeng00se 2022. 11. 23.

우리는 확실성이 아닌 정반대에서 즐거움을 찾기로 선택할 수 있다.

- 소크라테스 익스프레스

완벽한 정답이 존재하지 않는 상황에서, 지속적으로 더 나은 방법을 계속 생각했기 때문에 프리코스를 진행하면서 몰입의 즐거움을 느낄 수 있었습니다.

클래스(객체)를 분리하는 연습

2, 3주차와 다르게 4주차는 클래스를 분리하기 더욱 어려웠던 것 같습니다.

4주차는 클래스 간 협력에 대해 더 많은 고민을 많이 했습니다.

이상하게 다리 건너기 게임은 이전 주차와 다르게 협력하는 부분이 어려웠습니다. 중간에 생각했던 설계를 4 ~ 5번정도 수정하면서 클래스를 분리하는 부분에서 부족함을 많이 느꼈습니다.

최종적으로는 응집도를 높이고 너무 많은 클래스에 의존하지 않도록 최대한 노력했던 것 같습니다.

리팩터링

단위 테스트를 작성하면서 코드를 작성하니 리팩토링할 때 안정감이 느껴졌습니다.

코드의 작은 수정이 있어도 테스트 코드가 있다 보니 스트레스를 덜 받으면서 수정을 할 수 있었습니다.

게임 결과를 두 개의 HashMap(라운드, 방향 + 라운드, 성공여부)을 가진 클래스에 저장을 했는데 방향과 성공 여부 필드를 가지고 있는 클래스를 생성하여 일급 컬렉션을 만들었을 때 단위 테스트가 있기 때문에 안정적으로 리팩터링 한 것 같습니다.

또한 입력에서 오류가 발생할 때 반복적으로 받는 부분에서 3번의 중복이 발생하기에 제네릭과 Supplier를 사용하여 반복을 하나의 메서드에서 처리하도록 리팩터링 한 부분이 개인적으로 마음에 들었습니다.

3주차의 피드백에 테스트 코드도 코드라는 내용이 언급되었습니다. 그 부분을 잊지 않고 꾸준하게 반복되는 부분을 개선하려고 하니 테스트 코드도 점점 발전하는 것을 느낄 수 있엇습니다.

4주차 미션

마지막 프리코스 미션은 다리 건너기 미션으로 추가된 요구사항은 다음과 같습니다.

  • 메서드가 한 가지 동작을 하도록 구현하고, 길이가 10라인을 넘어가지 않도록 구현한다.
  • 메서드의 파라미터 개수를 최대 3개까지 허용한다.

이외에도 클래스가 기본적으로 제공되고 해당 클래스를 사용해야 되는 추가적인 요구사항들이 있었습니다.

클래스 분리하기

image

요구사항이 많아서인지 2, 3주차보다 클래스 분리가 더 어려웠습니다.

클래스를 세세하게 나누었고, 메서드도 하나의 기능만 하도록 일단 분리했습니다.

3주차의 피드백을 참고하여 최대한 객체스럽게(해당 객체에게 메시지를 보내도록) 사용하려고 노력했습니다.

세세하게 분리를 하니 추가 요구사항인 메서드 길이 10라인 이하로 유지하는 것은 자연스럽게 따라오는 것 같습니다.

게임 결과, 사용자의 시도 횟수, 현재 진행중인 단계에 대한 정보를 어떤 클래스와 의존해야 할 지 고민을 많이 했습니다. 사용자가 가지고 있는게 확장성 면에서 더 좋을 것 같다고 생각되어 Player의 필드에 추가하였습니다.

반복적으로 받는 입력 중복 제거하기

사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.

처음에는 요구사항을 만족시키기 위해 다음과 같은 코드를 3개를 중복으로 구현했습니다.

private int readBridgeSize() { ... }

private String readMove() { ... }

private String readGameCommand() {
    try {
        return inputView.readGameCommand();
    } catch (IllegalArgumentException e) {
        outputView.printError(e.getMessage());
        return readGameCommand();
    }
}

입력의 경우 3가지 모두 매개변수가 없이 값을 반환하는 Supplier<T> 형태를 띄고 있기 때문에 다음과 같이 리팩터링하여 사용할 수 있었습니다.

int size = repeat(inputView::readBridgeSize);
String move = repeat(inputView::readMoving);
String command = repeat(inputView::readGameCommand);

private <T> T repeat(Supplier<T> inputReader) {
    try {
        return inputReader.get();
    } catch (IllegalArgumentException e) {
        outputView.printError(e.getMessage());
        return repeat(inputReader);
    }
}

프리코스를 마치며

프리코스를 진행하면서 목표를 향해 나아가는 순수한 기쁨을 얻은 것 같습니다.

의식적으로 학습하고, 의도를 담긴 코드를 작성하려고 노력하다 보니 성장하는 것을 느낄 수 있었습니다.

독학을 할 땐 클린코드와 객체지향에 관해서는 이론적으로 학습만 할 뿐 실제로 토이 프로젝트에 적용하기 어려운 부분이 많았지만 미션을 진행하면서 내가 가지고 있는 지식들을 체화 시키면서 공부했던 것을 리마인드하고 그동안 몰랐던 부분, 부족한 부분을 채울 수 있었습니다.

우테코에 합류하고 싶어서 오랫동안 준비했고, 4주동안 후회없이 다 쏟아냈던 기간이었던 것 같습니다.

마지막으로 프리코스를 준비해주신 우테코 코치님, 같이 함께한 지원자분들 정말 감사합니다.