우아한테크코스 프리코스 1주차 후기

Y·2023년 10월 26일
0

우테코 프리코스

목록 보기
1/4

우아한 테크코스 프리코스 1주차

1주차 미션 깃허브

나는 취준을 하면서도 과제 전형을 진행해본적은 없었기 때문에, 과제라는 것을 진행해본것은 우테코가 처음이었다! 작년과 동일한 (작년에는 프리코스만 해볼까 하다가 안했었다..ㅎㅎ) 숫자야구게임인데, 별도의 클린코드 규칙은 없는듯하고 코드 컨벤션만 정해져 있었다. 그래도 클린코드를 얼마전에 스터디도 했으니! 클린코드 규칙도 지켜서 한 번 코드를 짜봐야겠다 싶었다.

  • 입력 검증은 어디에서 해야할까?
  • 결과값 생성 로직은 어떻게 개선할 수 있을까?
  • SRP에서 역할의 기준은 뭘까?
  • 접근 제한자는 어떻게 설정해야할까?
  • 랜덤값의 테스트는 어떻게 해야할까?

이러한 부분들을 주로 고민해서 코드를 짰던 것 같다. 평소에는 무심코 지나쳤던 부분도 많은데, 프리코스를 진행하면서 사소한 부분 하나하나도 고민해보는 과정을 거쳐서 공부가 많이 됐던 것 같다.

우선 객체를 나눴는데, 나는 크게 Game/Computer/Player의 세 객체로 나누었다. 게임을 진행하는데에 있어서 1)컴퓨터 2)플레이어의 두 객체가 있고, 전체 게임을 진행하는 게임 객체 하나가 있다고 판단해서였다. 나중에 다른 분들의 코드를 보고나니 내가 고정관념에 빠져있었구나 느끼게 됐다.. 그래서 우선 객체를 나누고 각 객체가 하는 일들을 고민해보면서 메서드를 크게 크게 짜기 시작했다. 그 과정에서 위에서 언급한 고민들을 시작했다.

입력 검증은 어디에서 해야할까?

이번 주차 미션에서는 사용자의 입력을 받고/입력을 검증해서 잘못된 입력이면 오류를 return하는 로직이 있었다. 이 부분에 대해서 입력을 검증하는 부분을 어떻게 해야할지에 대한 고민은 처음부터 계속 있었다. 처음에는 전체 게임을 진행하는 영역은 Game의 일이니까 Game 클래스에 넣었었는데, 코드를 다 짜고나서 생각해보니 Game 클래스가 하는 일이 너무 많은 것 같았다. 그래서 다시 한 번 생각해보니 '입력'과 관련된 것은 Player의 일이 아닌가? 라는 생각이 들었던 것이다.

  • Game : 게임 시작/종료/재시작, 입력 검증
  • Computer : 랜덤 숫자 생성/결과 판정
  • Player : 입력받기

각 객체가 하고 있는 일은 위와 같았기 때문에, 입력 검증은 Player단에서 입력을 받을때 같이 이루어지는 것이 맞겠다는 생각이 들어서 Player단으로 해당 검증 로직을 옮겼다.

그런데, 미션이 끝난 후에 다른 분들의 코드를 살펴보니 입/출력 로직 자체를 아예 다른 객체로 분리하신 분들도 꽤 계셨다. 일종의 View의 분리라고 생각할 수 있었는데, 나는 'Game' 객체의 역할을 너무 넓게 봐서 이 생각은 전혀 하지 못했었다. 이제와서 다시 생각해보면 Game 객체가 출력 역시 모두 담당하고 있었기 때문에 이 부분까지 분리했으면 좀 더 객체지향의 의도에 맞는 코드가 되었을 것 같다. (다음 주차 미션은 객체 분리에 좀 더 신경을 써보려고 한다.)

결과값 생성 로직은 어떻게 개선할 수 있을까?

결과값이 n볼 n스트라이크, n볼, n스트라이크, 낫싱의 4개가 있었는데, Computer 객체에서 입력값에 따라서 결과를 판정하고 출력해야 했다. 이 과정에서 if문을 계속 쓰고, String 변수에 +를 하는 코드를 쓰니 일단... 코드가 너무 지저분해보였다. 그래서 최대한 메서드를 쪼개고 if문을 간결하게 하는 방식으로 코드를 리팩터링했는데, 다른 분들의 코드를 보니 StringBuilder를 사용하는 방법도 있었다. 이 부분은 내가 자바 공부가 부족해서 잘 몰랐던 부분인 것 같고, 이번 기회에 배우게 됐다!

SRP에서 역할의 기준은 뭘까?

사실 이 부분은 클린코드 스터디를 하면서 팀원들과도 많은 의견을 나누었던 부분이다. 어찌보면 정말 단순한 원칙인데도 곱씹을수록 헷갈리는 부분이라고 생각한다. 사실 여러 의견을 나누고나서도 결론은 나지가 않았는데, 가장 명료한 설명은 수정을 할 이유가 하나여야 한다 였던 것 같다. 하지만 머리로는 이해가 되도 코드를 짜면서는 잘 실천이 안되는 원칙 중 하나인 것 같다🥲 이번 미션의 코드에서도 최대한 SRP 원칙을 준수하기위해서 고민을 했지만, 정확하게 지켜지지 않은 것 같다. 다시 한 번 객체를 쪼개보면 다음정도로 쪼갤 수 있을 것 같다.

  • 입력용 객체
  • 출력용 객체
  • 랜덤값 생성 객체
  • 결과 판정 객체
  • 게임 상태 객체(시작/재시작/종료)

이렇게 하면 정말 역할별로 객체를 쪼개게되는데, 그러면 게임 수행은 어디에서 하지?에 대한 고민이 생겼다🤔 이렇게 생각해보니 아마 이래서 MVC 패턴이 필요한 것 같은데, 이 부분을 간과하고 무작정 객체를 세개로 나눠서 코드를 짜서 SRP 법칙을 제대로는 준수하지 못했던 것 같아서 아쉽다. 내가 나눈 게임/플레이어/컴퓨터는 역할에 따라 객체를 나눴다기보다는 Actor의 개념으로 너무 좁게 보고 클래스를 나눴던 것 같다! 사실 역할이라는 건 사람마다 다르게 생각할 순 있지만.. 다음번 주차에는 이 부분에 대해 좀 더 개선해서 코드를 작성해봐야 겠다.

접근 제한자는 어떻게 설정해야 할까?

이 부분에 대해서는 사실... 처음부터 외부에서 알아도 되는 것/몰라도 되는 것(내부 로직)으로 나눠서 public/private으로 코드를 작성했는데, 테스트 코드를 작성하다보면 private 메서드/변수는 테스트를 할 방법이 없으니 이 부분에 대해서 고민이 생기면서 접근 제한자에 대해서도 고민하게 됐던 것 같다. 물론 reflection을 활용해서 테스트코드를 작성할수는 있겠지만 추천되는 방법은 아니라고 했고, 그렇다고 해서 해당 메서드가 외부에서 알아도 되는 동작인 것 같지는 않았다. 나는 최대한 보수적으로 접근 제한자를 설정했는데, 정보은닉의 목적으로는 이게 맞다곤 생각하지만 어느정도 수준으로까지 설정해야하는지에 대한 고민은 아직 남아있다.

랜덤값의 테스트는 어떻게 해야할까?

사실 위의 고민과 이어지는 고민인데, 랜덤값의 생성자체는 해당 라이브러리의 메서드가 정상적으로 동작할테니 그 자체의 문제는 아니었고, 숫자를 3자리를 생성했을때 중복되는 숫자가 없는지의 로직 점검이 문제였다. 왜냐면 해당 메서드를 private으로 만들었기 때문..🥲 (숫자를 생성하는 것은 private, 중복없이 생성해서 총 3개를 만드는 것은 public인데 return을 해줄 이유가 없기 때문에 void로 생성하고, Computer 객체의 내부 변수에 저장했다. 그런데 이 내부 변수도 당연히 private이다.) 이 로직을 점검은 해야하는데, private이라 할 방법은 없고, public으로 바꾸자니 외부에서 알면 안 되는 값이었고... 고민하다가 기존 테스트코드에 존재하는 assertRandomNumberInRangeTest를 활용해서 중복된값이 들어와도 서로 다른 3개의 값만 들어가는지를 테스트했다. 그런데 이 부분은 지금 다시 생각해보면 랜덤 숫자 생성 자체를 분리했으면 됐을 일인 것 같다...ㅎㅎ..

기타

이외에도 다른 분들의 코드를 보면서 enum의 활용, stream의 활용과 같은 부분에 대해 많이 배워갈 수 있었다. 아무래도 자바 공부를 더 해야겠다는 다짐을 다시 한 번 하게 됐다..ㅎㅎ

profile
개발자, 학생

0개의 댓글