[회고] 우아한 테크코스 5기 프리코스 2주차 회고

TAEYONG KIM·2022년 11월 9일
0

우아한 테크 코스

목록 보기
3/3

참고링크는 하단에 작성하였습니다


이번 미션을 시작하기 전에 요구사항을 먼저 파악했는데, 넘어가고 아래 회고에서부터 읽어주셔도 감사합니다.

❗꼭 기억해야 할 것 기록하기️❗

기능 목록


  1. 1 ~ 9 까지 랜덤으로 임의의 수 3개를 선택하는 메서드 추가

    camp.nextstep.edu.missionutils에서 제공하는 Randoms 및 Console API를 사용하여 구현

  2. 사용자 값을 입력하는 메서드 추가

    camp.nextstep.edu.missionutils.Console의 readLine()을 활용

  3. 잘못된 값을 입력했을 때 예외처리하는 메서드 추가(정규식 활용)
    1. 숫자가 입력되지 않는다면 예외처리 -> IllegalArgumentException
    2. 입력된 숫자 길이가 3이 아니라면 예외처리 -> IllegalArgumentException
    3. 서로 다른 숫자들이 아니라면 예외처리 -> IllegalArgumentException
  4. 스트라이크 or 볼 or 낫싱을 판단하는 메서드 추가
    1. 숫자와 위치가 같다면 strike 개수 + 1
    2. 숫자는 존재하는데 위치가 다르다면 ball 개수 + 1
    3. 일치하는 숫자가 하나라도 존재하지 않는다면 낫싱
  5. 게임을 새로 시작할지, 종료할지 선택하는 메서드 추가
    1. 게임 중이 아니라면, 1 or 2를 입력받도록 해서 새로 시작하는지, 종료하는지 실행시키는 메서드 추가
    2. 1 또는 2 숫자가 아니라면 예외처리 -> IllegalArgumentException
  6. 사용자의 입력에 따른 결과를 출력하는 메서드 추가

    strike 개수, ball개수에 따라 출력하는 메서드 생성


class Computer { // 컴퓨터 클래스
  private List<Integer> numbers;
  private static final int MAX_SIZE = 3;
  
  public Computer(){}
  public makeRandomNumbers(){}
  public getNumbers(){}
}

class Player { // 플레이어 클래스
  private List<Integer> numbers;
  
  public Player(){}
  public inputNumbers(){}
  public inputGameStatusData(){}
  public decideNumbers(){}
  public getNumbers(){}
}

class Judge { // 게임 진행자 클래스
  
  public Judge(){}
  public decideGameStatus(){}
  public getPlayerNumbers(){}
  public getComputerNumbers(){}
  public compareBalls(){}
}

class CheckException { // 예외 처리 클래스
    private static final int MAX_SIZE = 3;
    public static final int RESTART = 1;
    public static final int EXIT = 2;
    
    public validateConsistsOfNumber(){}
    public validateNumberLength(){}
    public validateOverlap(){}
    public validateGameStatusData(){}
}

class Application {
    public static void main(String[] args){}
    public static void printMessage(){}
    public static void decideResult(){}
}

📝 기능 분석 변경 사항

  • Player라는 클래스가 하는 일만 메서드로 등록하기 -> 하나의 클래스에서의 기능이 너무 많으면 유지보수가
    힘들다는 것을 이해했다.
  • CheckException 클래스를 통해서 예외 사항을 체크하는 메서드를 Player에서 분리하여 추가
  • GameStatus Enum Class에서 Magic Number 관리하도록 리팩토링



👨‍💻 본격적인 회고 첫 번째 내용

Java언어를 이용해서 테스트 코드를 작성하는 법은 처음이었다. 그래서, 공부한 내용을 기록해두었는데 AssertJ와 JUnit에 대해 공부를 해야했다. 메서드와 활용법을 바로 가기를 통해 필요한 자료들, 테스트 코드 이외 내용들 또한 확인하실 수 있습니다.

메서드는 하나의 행위를 하도록 지향하자 라는 말이 처음에는 크게 와닿지 않았다. 코드를 작성하면서 몸으로 와닿는 부분이 있었는데 테스트 코드를 실행하기 위해서는 메서드가 하나의 기능을 가지고 있어야 편리하다는 것을 느끼게 되었다.
Ex)

처음 작성한 코드
public String inputData() {
	String input = Console.readLine();
    String pattern = "^[1-9]*$";

    boolean result = Pattern.matches(pattern, input);

    if (!result) {
        throw new IllegalArgumentException("숫자만 입력할 수 있습니다.");
    }
}

inputData() 메서드에서 "입력하는 행위" 이외의 정규표현식을 통해 숫자가 아닌 입력값은 예외를 throw 해주는 행위가 추가되어 있다.
첫 번째, 메서드를 테스트 하고 싶은데 입력하는 메서드에서 예외가 발생하는 것을 테스트 해야할까?
두 번째, inputData("123"); -> 이러한 방향으로 임의로 테스트하고 지우면서 할까?

고민을 하다가 inputData()에서는 Console.readLine()을 통해 입력값만 Return해주고
예를 들어 validateConsistsOfNumber(String input){} 을 통해, 메서드를 Test하는 것이 올바르지 않을까? 라는 판단이 섰다.

메서드가 하나의 행위를 하고, Indent 2이상 잡지 않는다는 말을 이해할 수 있는 계기가 되었다.


👨‍💻 본격적인 회고 두 번째 내용


- validateConsistsOfNumber(){} : 숫자로만 이루어져있는지 검증
- validateNumberLength(){}: 길이가 올바른지 검증
- validateOverlap(){}: 중복된 숫자가 있는지 검증
등등등...

검증 메서드를 Player Class에 전부 실행했었다. 코드를 조금 더 Clean하게, Player라는 클래스가 하나의 행위를 하도록 한다 라는 의미가 떠올라서 의문점이 들었다.
Player가 하는 행위는 숫자를 입력하는 것인데, 검증까지 해야 할까?

따라서, 로직을 분리한 내용이 CheckExeption Class를 생성하여 입력한 숫자를 검증하는 코드를 작성하였다.
메서드를 코드로 보자면,

public void decideNumbers(String input) { // check instance를 통해서 검증하는 과정
	check.validateConsistsOfNumber(input);
    check.validateNumberLength(input);
    addNumber(input);
    check.validateOverlap(this.numbers.size());
}

분리하면서 나름 괜찮다고 판단했다.

👨‍💻회고의 마지막...

클린 코드 및 객체지향 원칙을 오늘 읽어봤는데

  • 모든 원시값과 문자열을 포장한다
  • 일급 컬렉션 사용
    에 대해 이해할 수 있었다. 처음에는 Player의 Ball을 Player 자체의 메서드에서 검증하는 단계, 리팩토링을 하고 나서는 CheckExeption 클래스를 이용해서 검증하였다.

원칙의 내용 중, 프로그래밍에서 변수는 '상태'로 쓰일 수 있기에 단순히 값을 나타내는 것도 있지만 비즈니스적으로 생각을 해보라는 의미를 갖는 것 같다. 변수를 객체로 포장해 사용하면 얻는 이점 을 생각해보자.

처음에는 이 말이 와닿지 않을 수 있는데, 필자가 처음에 생각한 클래스는 사람, 제품, 물건(?) 등등 ... 같은 말이긴 하나 한눈에 아 이건 객체지! 라고 생각하는 것들을 클래스로 생각하였다.

이런 범위가 아니라 변수를 -> 클래스처럼 활용해보자는 것이다.
위에 작성한 decideNumbers() {} 를 통해 검증하는 과정은 Player라는 객체가 스스로 자신의 상태를 관리하지 못한다는 것이다. 쉽게 말해서 CheckExeption 클래스를 통해서만 검증을 한다는 것이다.

다른 클래스에서도 입력하는 행위를 한다면 CheckException을 통해서 다시 검증을 해야하는 추가적인 행위가 필요하다. 다음 내용에 집중해보자!

숫자를 입력받는다 -> Player가 Ball들을 입력한다라는 행위이다. 이 Ball들을 클래스로 생성해보는 것이다. 이러면 Player의 Input행위에 대해 따로 검증하는 코드를 추가하지 않고 유지보수할때 클래스를 관리하면 편할 것이다.

public class Ball {
	private String ball;
    
    public Ball(String ball){
    	String pattern = "^[1-9]*$";
    	boolean result = Pattern.matches(pattern, this.ball);

    	if (!result) {
        	throw new IllegalArgumentException("숫자만 입력할 수 있습니다.");
    	}
}

머리가 띵하다. 이러면 Ball에 대해 검증하는 부분이 Ball 자체가 생성될 때 검증하기에 안전하게 관리하고 유지보수 할 수 있다고 느꼈다.
많은 것을 배우게 된 미션이었습니다.

자바 스타일 가이드 링크
내용 참고 링크
클린코드 참고 링크

profile
백엔드 개발자의 성장기

1개의 댓글

comment-user-thumbnail
2022년 11월 10일

잘보고갑니다!

답글 달기