GYUD-TECH

[우테코 프리코스] 2주차 회고 본문

후기

[우테코 프리코스] 2주차 회고

GYUD 2023. 11. 1. 15:33

우테코 프리코스 2주차 과제는 자동차 경주 게임 구현하기이다.

 

과제 설명은 아래 깃허브 링크에서 확인할 수 있다.

https://github.com/Gyu-won/java-racingcar-6

 

GitHub - Gyu-won/java-racingcar-6

Contribute to Gyu-won/java-racingcar-6 development by creating an account on GitHub.

github.com

 

2주차의 목표는 1주차 목표 + 함수를 분리 +  함수별로 테스트를 작성하는 것이다. 목표를 달성하기 위해서 했던 고민들을 아래 글에 자세하기 정리하였다.


과제를 수행하면서 했던 고민들

1. 코드리뷰를 통한 피드백

과제와 함께 1주차 과제에 대한 공통 피드백도 받을 수 있었다. 그래서 2주차 과제를 시작하기 전에 과제 피드백을 점검하고, 다른 사람의 코드를 리뷰하는 시간을 가졌다. 

 

코드 리뷰를 하면서 내가 했던 고민들을 같이 하고 있는 동료들이 많다는 것을 알 수 있었다. 고민들을 리뷰하고 내용에 대해서 토론하면서 답을 찾아 나갈 수 있었다. 코드 리뷰를 처음 진행하였는데 이 과정에서 느낀 것이 많아서 느낀점을 아래 블로그에 자세히 정리하였다.

 

https://gyuwon-tech.tistory.com/8

 

[우테코 프리코스] 1주차 피드백

GYUD-TECH [우테코 프리코스] 1주차 피드백 본문 후기 [우테코 프리코스] 1주차 피드백 GYUD 2023. 10. 31. 16:48

gyuwon-tech.tistory.com

 

2. 단위 테스트 작성

 2주차 과제에는 테스트 작성 요구사항이 포함되어 있어, 이번 기회에 Junit과 AssertJ 문법을 학습하고 과제에 적용해 보았다.

 

간단한 테스트 코드를 작성하는 것은 쉬웠지만, 랜덤값 생성, private 메서드, 일급 컬렉션 등 다양한 조건을 생각하면서 테스트를 하는 것은 어려웠다.

 

2주차 과제에서는 랜덤값을 생성하고 생성된 값에 의해 자동차가 이동한다. 그래서 랜던값의 결과를 예상해서 이동 여부를 테스트하는 부분을 고미하였다. 랜덤 값 생성을 Car 객체 외부로 빼는 방법도 생각해 보았지만, 각 자동차 마다 랜덤값을 생성하여 이동여부를 결정하는 것이기 때문에 아래와 같이 테스트가 가능하도록 메서드를 분리하여 moveOrStop 메서드를 테스트하였다. 

    protected RaceResultDTO move() {
        moveOrStop(generateRandomNumber());
        return RaceResultDTO.create(carName, carLocation);
    }

    protected void moveOrStop(int randomNumber) {
        if (randomNumber >= MOVE_FORWARD_NUMBER) {
            carLocation++;
        }
    }

    private int generateRandomNumber() {
        return Randoms.pickNumberInRange(MIN_RANDOM_NUMBER, MAX_RANDOM_NUMBER);
    }

moveOrStop() 메서드는 move() 메서드에서만 호출되기 때문에 private으로 선언하고 싶었지만 test를 위해서 protected로 선언하였다. move()를 테스트 하기에는 랜덤값에 의해 결과가 달라지기 때문에 테스트를 할 수 없었다. 

 

뿐만 아니라 Car들의 리스트를 저장하는 일급 컬렉션 클래스 Cars에는 아래와 같이 테스트만을 위한 메서드가 필요했다.

    //test만을 위한 코드
    protected Car getCarForTest(int i) {
        return cars.get(i);
    }

다른 메서드와 독립적으로 해당 메서드의 결과만 확인하기 위한 테스트를 작성하다보니 test만을 위한 메서드를 생성하였다. 

 

이 부분이 이번 2주차에서 가장 고민되었던 부분이다. "test만을 위해서 프로덕션 코드를 변경하여도 되는가?" 라는 질문에 아직 답을 찾지 못했다. 프로덕션 코드가 잘 돌아가는지 확인하기 위해서는 테스트 코드만을 위해 프로덕션 코드를 변경할 필요가 있었다. 하지만 test 코드는 프로덕션 코드를 잘 만들기 위한 코드인데 test 코드에 의해 프로덕션코드를 비효율적으로 변경하는 것이 옳은가에 대한 의문도 들었다. 2주차가 끝나면 크루원들과 내용을 공유하고 함께 이야기 해보고 싶다.

 

 

3. 가독성이 좋은 코드

1주차에 이어서 2주차에서도 코드의 가독성을 높이기 위한 방법을 고민하였다. 지난 주에서 사용하지 못했던 stream을 도입하여 코드를 작성해보았고, IntelliJ의 도움을 받아 자바에서 제공하는 API도 살펴보았다.

특히 stream을 사용하면 코드를 간단하게 짤 수 있을 거라고 생각해서 이번 기회에 stream API가 제공하는 다양한 메서드들을 찾아보고 직접 적용해 보는 연습을 하였다.

 

아래 블로그에 Stream을 과제에 적용한 과정과 느낀점을 자세히 작성하였다.

https://gyuwon-tech.tistory.com/7

 

Stream 적용기

GYUD-TECH Stream 적용기 본문 공부 정리 Stream 적용기 GYUD 2023. 10. 30. 22:49

gyuwon-tech.tistory.com

 

4. static 메서드

Effective Java 교재의 1장 "생성자 대신 정적 팩터리 메서드를 활용하라"를 읽고 이를 코드에 적용해 보았다. 책에서 소개한 많은 장점들 중 가장 크게 와닿았던 장점은 메서드 명을 통해서 가독성을 높일 수 있다는 점이었다. 단순히 new Car(carName)을 통해 Car 인스턴스를 생성하는 것 보다 Car.withName(carName) 형식으로 객체를 생성하는 것이 훨씬 명확하게 의미를 전달해 주었다.

또한 인스턴스를 생성할 필요없이 호출할 수 있는 메서드는 static으로 선언하고 불필요한 인스턴스의 생성을 최소화 하고자 하였다. 기존에 static 키워드를 사용하는 것에 어려움을 느꼈는데 이번 주차 과제를 통해서 static 키워드의 사용법을 익힐 수 있었다.

 

5. git 커밋 관리

2주차 과제에서는 기능별로 커밋을 진행하며, 1주차 과제에서 배운 커밋 메시지 작성법을 적용하였다. 그러나 아직 습관화가 되어 있지 않아 잘못된 커밋을 push를 하는 경우가 자주 있었다. 또한 refactoring 과정에서 일급 컬렉션을 적용하면서 많은 코드들이 연쇄적으로 컴파일 오류가 발생하였기 때문에 기능 단위 커밋을 지키지 못하였다. 협업을 위해서는 git 커밋 관리도 필수적이라고 생각하기 때문에 이 내용을 더 신경쓰면서 다음 주차 과제에 임하겠다고 다짐했다.


마무리

2주차에서는 1주차 피드백을 적극적으로 반영하려고 노력했고, 단위 테스트 작성에 많은 시간을 쏟았다.

처음에 일급 컬렉션을 고려하지 않고 설계 - 테스트코드 작성 - 프로덕션 코드 작성 - 테스트 - 리팩토링 - 테스트 순으로 코드를 작성했다. 하지만 일급 컬렉션을 적용하면서 test 코드도 모두 변경해야했고, 이 과정에서 테스트 코드를 위해 프로덕션 코드를 변경해야 하는지에 대한 의문도 들었다. 다음 주차에는 설계 단계부터 일급 컬렉션을 고려하여 설계를 해야겠다고 다짐했으며, 테스트 코드를 위한 변경에 대한 내용은 크루원들과 함께 토론해보며 내 생각을 정리하고 싶다.

 

우아한테크 프리코스를 시작하면서 몰입했던 경험을 기록하고 공유하고 싶어서 블로그를 작성하기 시작했다. 이전에도 개발 블로그를 작성한 적이 많았지만, 단순 개념 작성의 지루함 때문에 꾸준히 글을 작성하지 못했다.

그런데 경험 중심의 글을 작성하다 보니, 내가 겪었던 고민과 해결과정을 정리하면서 학습효과도 얻을 수 있었다. 앞으로도 블로그를 작성하면서 더 많이 성장하는 개발자가 되고 싶다.