[우테코5기] 프리코스 모바일 2주차 회고록

sehyonii·2022년 11월 15일
0

우아한 테크코스

목록 보기
2/3

2주차 과제를 진행하면서 어려웠던 점이나 피드백을 통해 고쳐야할 점을 기록하고 싶어 작성하는 회고록

프리코스 2주차

기능 요구 사항

기본적으로 1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임이다.

  • 같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 낫싱이란 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방(컴퓨터)의 수를 맞추면 승리한다.
    -예) 상대방(컴퓨터)의 수가 425일 때
    - 123을 제시한 경우 : 1스트라이크
    - 456을 제시한 경우 : 1볼 1스트라이크
    - 789를 제시한 경우 : 낫싱
    위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다. 게임 플레이어는 컴퓨터가 생각하고 있는 서로 다른 3개의 숫자를 입력하고, 컴퓨터는 입력한 숫자에 대한 결과를 출력한다.
    이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.
    게임을 종료한 후 게임을 다시 시작하거나 완전히 종료할 수 있다.
    사용자가 잘못된 값을 입력할 경우 IllegalArgumentException을 발생시킨 후 애플리케이션은 종료되어야 한다.

프로그래밍 요구사항

  • indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
    - 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
    - 힌트: indent(인덴트, 들여쓰기) depth를 줄이는 좋은 방법은 함수(또는 메서드)를 분리하면 된다.
  • 함수(또는 메서드)가 한 가지 일만 하도록 최대한 작게 만들어라.

과제 repository를 fork&clone 하여 야구게임을 위의 기능요구사항, 프로그래밍 요구사항 그리고 과제 진행 요구사항을 만족하도록 구현한 뒤 pull request로 제출한다.

어려웠던 점

1. 예외 처리

예외가 일어날 수 있는 상황을 계속 생각하면서 처리해야 했기 때문에 그걸 찾아내는게 어려웠다. 예외를 많이 생각하고 찾았다고 생각했는데 테스트를 해보면 또 오류가 생기는 상황이 발생해서 힘들었다.그리고 예외 처리를 처음 해봤기 때문에 개념이 부족해서 언제 throw를 해야하는지 try~catch문을 사용해야하는지 등 개념을 먼저 공부해야했다.

2. 객체 지향 설계

1주차 과제와 달리 2주차에는 객체 지향적인 코드를 구현하겠다고 생각했다. 하나의 클래스나 메서드가 크다면 절차 지향과 동일한 문제가 발생한다. 알맞은 객체로 분리해서 하위 기능으로 분배할 필요가 있다.하지만 과제를 진행하면서 어떤 부분을 클래스로 분리하고, 설계를 진행해야하는지 어려움을 느꼈다.

3. 함수별로 테스트 작성

유닛 테스트는 컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차다. 즉, 모든 함수와 메소드에 대한 테스트 케이스를 작성하는 절차를 말한다.
-위키피디아

항상 main()으로 프로그램을 실행해서 전체적인 코드를 테스트 했었다. 기능 단위로 그것을 잘 구현했는지 확인하기는 쉽지 않았다. 테스트 코드를 통해 함수와 메소드에 대한 테스트를 할 수 있다는 것을 처음 알게 되었다. 테스트 코드 작성이 익숙하지가 않아 어려웠지만 기능 단위의 테스트를 할 수 있어서 구현할 때 편했다.

피드백을 통해 고칠 점

1.값을 하드 코딩하지 않는다.

문자열, 숫자 등의 값을 하드 코딩하지 마라. 상수를 만들고 이름을 부여해 이 변수의 역할이 무엇인지 의도를 드러내라. 구글에서 "kotlin 상수"와 같은 키워드로 검색해 상수 구현 방법을 학습하고 적용해 본다.

 while(computer.length < 3) {
        val randomNumber = Randoms.pickNumberInRange(1, 9)
        if(!computer.contains(randomNumber.toString())) {
            computer += randomNumber.toString()
        }
    }

하드코딩을 하면 의미를 파악하기 어렵고 유지하기 어려워진다. 이번 주차 과제에서 위와 같이 상수를 활용하지 않은 채 하드코딩을 한 경우가 많았다. 하드코딩을 하지 않도록 신경써서 코드를 구현하고 리팩토링 해야겠다.

2.변수 이름에 자료형은 사용하지 않는다.

변수 이름에 자료형, 자료 구조 등을 사용하지 마라.

fun mapBallList(ballList: String) : List<Ball> =
 ballList.mapIndexed { index, c ->  Ball(c.toInt() - '0'.toInt(), index + 1)}

위 처럼 변수명을 ballList로 자료형을 사용하여 코드를 구현하였다. 이를 지양하고 변수명을 더 고민하는 시간을 가져야겠다.

3.한 함수가 한 가지 기능만 담당하게 한다.

함수 길이가 길어진다면 한 함수에서 여러 일을 하려고 하는 경우일 가능성이 높다. 아래와 같이 한 함수에서 안내 문구 출력, 사용자 입력, 유효값 검증 등 여러 일을 하고 있다면 이를 적절하게 분리한다.

fun userInput(): List<Int> {
   println("숫자를 입력해 주세요: ")
   val userInput = Console.readLine().trim()
   val user = mutableListOf<Int>()
   for (c in userInput) {
       user.add(c.digitToInt())
   }
   require(user.size == 3) { "[ERROR] 숫자가 잘못된 형식입니다." }
   return user
}

입력함수, 출력함수, 유효값 검증함수로 분리함으로써 유지보수도 편하고 테스트 하기에도 편하게 만들 수 있다. 기능을 최대한 세분화하고 함수가 한가지 기능만 하도록 노력해야겠다.

느낀점

1주차 피드백을 생각하며 코드를 구현하였지만 부족한 점이 많다는 것을 느꼈다. 피드백을 계속 생각하며 문제점을 고쳐나가다보면 더 발전된 내가 될 수 있지 않을까..?
처음 1주차 과제를 했을 때는 구현만 생각해도 막막했는데 기능목록을 만들고 예외사항을 생각하고 구현하고 리팩토링하는 과정이 재밌어지고 있다. 다음 과제도 열심히, 최선을 다하자!!!

0개의 댓글