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

 

2주차 돌아보기

어느정도 시간의 여유가 생겨서 2주차는 1주차와 다르게 바로 작성하게 되었습니다.

벌써 프리코스를 반 정도 진행하게 되었고, 좀 더 잘하고 싶다는 후회와 아쉬움으로 회고를 작성하게 되었습니다.

1주차가 끝나고 2주차가 시작되면서 1주차 공통 피드백 메일을 받게 되었습니다.

다른 참가자 분들께 1주차 코드 리뷰를 받고 코드를 수정했었는데요.

공통 피드백을 확인해보니 고쳐야 할 부분이 상당히 많았습니다.

 

 

이전 미션의 개선점 찾기

공통 피드백을 통해서 내 코드에 문제점을 찾는 시간을 가지게 되었습니다.

중요하다고 생각하는 피드백을 뽑아서 코드 수정을 하였습니다.

 

1. 커밋 메시지 작성의 필요성

 

가장 중요한 점으로, 커밋 메시지를 기능별로 적절하게 관리했어야 했습니다.

첫 미션부터 큰 실수를 한 것 같아서 마음이 아팠지만 다음미션부터 빼먹지 않도록 다짐했습니다.🥲

 

2. 축약 : 이림이 길어지더라도 의도 들어내기

 

요 부분은 코드를 보는 사람에 따라서 애매할 수도 있다고 생각했습니다.

저는 코드를 작성할 때 한 줄에 최대한 적은 코드가 들어가도록 신경쓰는데요,

코드를 다시 확인해보니 너무 축약하여 의도를 알기 힘들수도 있을 것 같은 변수명이 있었습니다.

개선해야 할 부분인 것 같아서 뽑게 되었습니다.

 

3. 의미 없는 주석 : 의도를 들어내기 힘든 경우만 주석 작성하기

 

저는 코드를 작성할 때 주석을 최대한 많이 활용했는데요.

어쩌다보니 코드보다 주석이 더 많은 부분도 있고.. 보는 사람 입장에서 코드를 찾기 힘들 수도 있다는 생각을 했습니다.

의도가 들어난 변수 명에도 굳이 주석을 작성하는 등의 너무 친절한 코드를 작성하였습니다.

오히려 코드량이 많아져서 리딩하는 입장에서 불편할 수 있다는 생각에 코드 수정을 하였습니다.

 

4. Kotlin API & Collection 적극 활용하기 : 메소드를 구현하기 전에 코틀린에서 제공하는지 확인하기

 

이미 코틀린에 있는 API를 직접 코드로 구현하게 되면 큰 낭비를 하게 됩니다.

내가 작성한 코드가 코틀린 API보다 느리고 복잡할 확률이 크니까요.

 

2주차 과제를 진행하면서 Pair와 map을 활용한 클래스에서 필요한 부분만 추출하는 기능을 사용해 봤습니다.

위의 API를 알고는 있었지만, 코테를 파이썬으로 공부하는 탓에 map을 사용할 기회가 적었던 것 같습니다.

이번 미션에서 사용하고 보니, 지금 진행하고 있는 프로젝트에도 분명 적용하면 효율이 오를 것 같다는 생각을 했습니다.

다양한 API를 숙지하고 적용하는 습관을 들여야 할 것 같습니다.

 

 

추가 요구사항 점검하기

 

2주차 과제에 들어가기 전에 추가 요구사항은 없는지 확인하였습니다.

이전과 다른 총 3가지 요구사항이 있었으며, 리스트를 만들어 정리하였습니다.

 

1. indent(들여쓰기) depth를 3이 넘지 않도록 구현

 

요 경우는 잘지키고 있는 것 같아서 따로 확인할 사항이 없었습니다.

항상 들여쓰기를 통해서 depth를 확인하고, 최대한 기능을 나누어 작성하는 습관을 가지고 코드를 작성하였습니다.

 

2. 함수를 적극 활용하고, 하나의 함수는 한 가지 일만 하도록 최대한 작게 작성

 

요 경우도 대부분 지키고 있는 것 같았습니다.

최대한 함수를 쪼개어 활용하였고, 비슷한 기능을 하는 함수끼리 모아두어 가독성이 좋게 하였습니다.

 

3. JUnit 5와 AssertJ를 이용하여 본인이 정리한 기능 목록이 정상 동작하는지 테스트

 

테스트 케이스 작성은 자바에서 해보고 코틀린에서는 처음 경험게 되었는데요.

어떻게 구현해야 할지 막막하였지만, 다행히 study.StringTest에서 예시를 두어 참고할 수 있었습니다.

 

기능 구성하기

 

기능을 위와 같이 작성하였습니다.

테스트 코드는 위의 코드가 정상적으로 동작하는지 작성하였는데요.

사용자가 잘못 된 값을 입력했을 경우를 중점으로 테스트 코드를 작성하였습니다.

 

기능은 크게 4가지 부분으로 나누어서 구현하였습니다.

 

GameConsole

게임 진행과 데이터를 관리하는 오브젝트로 자동차 리스트를 생성하고 반환하며 우승자를 선별하는 기능을 하고 있습니다.

뿐만 아니라 레이싱 시도 횟수와 자동차 이름을 사용자로부터 입력받는 기능을 하고 있습니다.

 

Manager( MessageManager, RacingManager)

각 메시지를 출력하는 기능과 레이싱의 진행을 돕는 클래스 입니다.

RacingManager는 한 번의 레이싱 결과를 자동차 객체에 적용하며, 랜덤값 생성을 통해서 전진 과정을 적용합니다.

 

Car Model

자동차 데이터를 보관하기 위한 클래스이며, 레이싱이 진행되는 동안 progress 프로퍼티를 통해서 진행 상태를 저장합니다.

 

CheckValidation

올바른 값이 입력되었는지 검증하는 클래스이며, 요구사항에 따라 잘 못 된 값이 입력 된 경우

IllegalArgumentExcetion를 발생하도록 하였습니다.

 

테스트 케이스 작성해보기

study - StringTest에 작성 된 테스트 케이스를 보고 테스트 케이스를 작성해 보았습니다. 

총 2가지 테스트 케이스를 작성하였는데요.

사용자의 입력값을 받는 자동차 이름, 레이싱 시도 횟수에 대한 테스트 케이스를 작성 하였습니다.

 

class CarValidationTest {
    private val discriminator = CheckValidation()

    @Test
    fun `자동차 이름의 길이 유효성 검사`() {
        val input = "kona"
        val result = discriminator.checkCarLength(input)
        assertThat(result)
    }

    @Test
    fun `자동차 이름이 제한 문자열 길이보다 큰 경우 예외 발생`() {
        val input = "avante"
        assertThrows<IllegalArgumentException>("자동차 이름은 1자 이상, 5자 이하만 가능합니다.") {
            discriminator.checkCarLength(input)
        }
    }

    @Test
    fun `자동차 이름이 공백인 경우 예외 발생`() {
        val input = ""
        assertThrows<IllegalArgumentException>("자동차 이름은 1자 이상, 5자 이하만 가능합니다.") {
            discriminator.checkCarLength(input)
        }
    }

    @Test
    fun `자동차 이름의 정규표현식 검사`() {
        val input = "k7"
        val result = discriminator.checkCarNameValidation(input)
        assertThat(result)
    }

    @Test
    fun `자동차 이름이 정규표현식을 따르지 않을 경우 예외 발생`() {
        val input = "k@7"
        assertThrows<IllegalArgumentException>("올바른 자동차 이름을 입력해야 합니다.") {
            discriminator.checkCarNameValidation(input)
        }
    }

    @Test
    fun `자동차 이름 중복값 검사`() {
        val carNameList = listOf("kona", "k7")
        val result = discriminator.checkDuplicateCarName(carNameList)
        assertThat(result)
    }

    @Test
    fun `자동차 이름 중복값이 있을 경우 예외 발생`() {
        val carNameList = listOf("kona", "kona")
        assertThrows<IllegalArgumentException>("자동차 이름은 중복을 허용하지 않습니다.") {
            discriminator.checkDuplicateCarName(carNameList)
        }
    }

}

 

자동차 이름에 대한 validation을 검사하는 CarValidationTest 입니다.

요구사항에 따라 사용자가 잘못 된 값을 입력하는 경우에 대한 테스트를 작성하였는데요.

일반적으로 자동차 경주를 할 경우, 이름에 중복값이 있거나 정규 표현식이 따르지 않을 경우,

공백으로 입력된 경우에 대한 예외처리도 별도로 작성하였습니다.

처음에는 요구사항에 없어서 고민하였는데, 사소한 부분도 꽤 중요한 요소가 될 수 있을 것 같아서 작성해 보았습니다.

 

class RacingCountValidationTest {
    private val discriminator = CheckValidation()

    @Test
    fun `레이싱 시도 횟수 유효성 검사`() {
        val input = "5"
        val result = discriminator.checkInputRacingCount(input)
        assertThat(result)
    }

    @Test
    fun `사용자의 입력이 정수가 아닌 경우 예외 발생`() {
        val input = "다섯"
        assertThrows<IllegalArgumentException>("올바른 숫자를 입력해야 합니다.") {
            discriminator.checkInputRacingCount(input)
        }
    }

    @Test
    fun `사용자의 입력이 0인 경우 예외 발생`() {
        val input = "0"
        assertThrows<IllegalArgumentException>("양의 정수를 입력해야 합니다.") {
            discriminator.checkInputRacingCount(input)
        }
    }

    @Test
    fun `사용자의 입력이 음의 정수인 경우 예외 발생`() {
        val input = "-5"
        assertThrows<IllegalArgumentException>("양의 정수를 입력해야 합니다.") {
            discriminator.checkInputRacingCount(input)
        }
    }
}

 

다음으로는 레이싱 시도 횟수를 검증하는 RacingCountValidationTest를 작성하였습니다.

이전 1주차에서 실수한 부분에 대하여 테스트를 적용하였습니다.

사용자의 입력이 음수인 경우도 정수로 처리되어 잘못 된 값이 입력될 수도 있다는 생각을 하였습니다.

이전 베이스볼 게임에서 음수에 대한 예외처리를 안했었는데, 테스트 케이스 작성을 통해서 꼼꼼하게 확인해야 겠다는 생각을 했습니다.

 

빼먹는 부분이 있을 것 같아서, 2주차 과제가 끝나면 리뷰를 부탁해야 겠다는 생각을 하게 되었습니다.

 

 

리뷰

프로젝트와 코딩 테스트 준비를 병행하면서 프리코스 과정을 진행하고 있는데요.

최대한 많은 시간을 쓰려고 노력했음에도 부족한 점이 많은 것 같습니다..

다른 분들 회고도 읽어보고 꾸준한 코드 리뷰 요청과 소통을 해야겠다는 생각을 했습니다.