티스토리 뷰

지난 회고 보기
[우아한 테크코스 5기] 프리코스 1주차 회고 (Convention과 Clean Code)

한 것

Git 학습

출처: 우테코 프리코스 Git 특강

프리코스에서 제공해준 자료등을 토대로 학습했습니다.

여기서는 Git의 용어 관계와 기본 명령어(add, commit, push)를 나눈 이유를 Git 객체를 통해 알 수 있었습니다.

그 후에도, 미션을 조금 미뤄두고 Git의 용어 정리와 Git의 명령어에 따른 흐름을 이해하면서 모르는 부분을 채워나갔습니다.

참고 자료:
- [10분 테코톡] 오리&코린의 Merge, Rebase, Cherry pick
- [10분 테코톡] 🎲 와일더의 Git Commands
- git - 간편 안내서
- git과 github

Test 학습

1주 차 테스트 코드

1주 차에서 테스트 코드를 작성할 때 공통적인 부분을 추출하지 못 했습니다.

2주 차에서는 테스트 코드를 잘 작성하는 것도 목표로 했기 때문에 위의 문제점을 개선하려고 노력했습니다.

2주 차 테스트 코드

1주 차 테스트 코드와는 달리 테스트에 이름을 부여하고, 반복되는 코드를 @CsvSource 어노테이션을 통해 변수와 예상값을 주어 테스트하였습니다.
추가로 이렇게 하니 코드를 작성하고 나서도 어떤 테스트인지 알기 쉽고, 추가 검증할 데이터도 코드 작성없이, value 값에 추가만 해주면 되어 확실히 더 나은 테스트 코드라고 느껴집니다.

참고 사이트 : https://www.baeldung.com/parameterized-tests-junit-5

미션 과정

2주 차 미션은 "숫자 야구 게임" 구현이고 추가로 해당 미션에 맞게 기능 요구사항, 프로그래밍 요구 사항, 과제 진행 요구 사항을 지키면서 미션을 완료하면 되었습니다.

 

2주 차에서는 1주 차에 학습한 것과 추가로 함수를 분리, 함수별로 테스트를 작성 하는 것에 목표를 하고 있습니다.

기능 요구 사항을 토대로 구현 기능 목록, 작성 테스트 코드 작성, 기능 구현 순으로 과제를 완성했습니다.

난수 생성기 기능 작성

기능 목록을 토대로 테스트 코드 작성

class RandomGeneratorTest {

    private RandomGenerator randomGenerator;

    @BeforeEach
    void init() {
        randomGenerator = new RandomGenerator();
    }

    @RepeatedTest(value = 10, name = "{currentRepetition}: 1에서 9까지의 난수 생성 검증")
    public void 난수_1_9_생성_검증() {
        //given
        int randomNumber = randomGenerator.generateNumber();
        //when
        boolean validResult = randomNumber >= 1 && randomNumber <= 9;
        //then
        assertThat(validResult).isTrue();
    }

    @RepeatedTest(value = 10, name = "{currentRepetition}: 서로 다른 3개의 난수 생성 검증")
    public void 서로_다른_3개_난수_생성_검증() {
        //given
        List<Integer> randomNumbers = randomGenerator.generateNumbers();
        //when
        int num1 = randomNumbers.get(0);
        int num2 = randomNumbers.get(1);
        int num3 = randomNumbers.get(2);
        boolean actual = num1 != num2 && num1 != num3 && num2 != num3;
        //then
        assertThat(randomNumbers.size()).isEqualTo(3);
        assertThat(actual).isTrue();
    }
}

테스트 코드를 토대로 기능 구현

public class RandomGenerator {

    public static List<Integer> generateNumbers() {
        List<Integer> numbers = new LinkedList<>();
        return generateNumbers(numbers);
    }

    private static List<Integer> generateNumbers(List<Integer> numbers) {
        if (numbers.size() == Constants.NUMBER_SIZE) {
            return numbers;
        }
        int number = generateNumber();
        if (!numbers.contains(number)) {
            numbers.add(number);
        }
        return generateNumbers(numbers);
    }

    static int generateNumber() {
        return Randoms.pickNumberInRange(Constants.MIN_NUMBER, Constants.MAX_NUMBER);
    }
}

자바 코드 같은 경우에는 좋은 이름을 짓기 위해 노력했습니다.
클래스명이나 변수명 등을 정할 때 실제 ‘야구’라는 도메인을 참고하여 작성했습니다.
이후 보기 힘든 로직을 메소드로 분리해서 바로 알아볼 수 있도록 신경 썼습니다.
예를 들어, 기존에 if 문에 서로 다른 수를 검증하는 로직을 바로 썼다면, 검증 로직을 메소드로 분리하고 메소드 명으로 이해할 수 있게 작성했습니다.
변수도 클래스와 상관없이 자주 메인 로직에 사용되는 값들을 Constants라는 클래스를 만들어 상수로 사용하였습니다.

public class Constants {

    public static final int MAX_NUMBER = 9;
    public static final int MIN_NUMBER = 1;
    public static final int NUMBER_SIZE = 3;

    public static final String NUMBERS_REGEX = "^[1-9]{3}$";

    public static final String STRIKE_MSG = "스트라이크";
    public static final String BALL_MSG = "볼";
    public static final String NOTHING_MSG = "낫싱";

    public static final String START_MSG = "숫자 야구 게임을 시작합니다.";
    public static final String INPUT_BALLS_MSG = "숫자를 입력해주세요 : ";
    public static final String INPUT_RESTART_MSG = "게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.";
    public static final String END_MSG = "3개의 숫자를 모두 맞히셨습니다! 게임 종료";

    public static final String BALL_NUMBER_ERR_MSG = "야구공의 숫자는 1~9 사이의 숫자입니다.";
    public static final String BALLS_VALIDATE_ERR_MSG = "공은 서로 다른 3개의 수로 구성되어야 합니다.";
    public static final String BALLS_STRING_ERR_MSG = "서로 다른 3개의 수를 공백없이 입력해주세요. ex) 123";
    public static final String RESTART_OPTION_ERR_MSG = "1, 2 만 입력할 수 있습니다.";
}

1주 차에서의 문제점 개선

1주 차 때 작성한 구현 기능 목록과 커밋 메시지를 돌아보니 많이 부족했습니다.
구현 기능 목록과 기능요구 사항은 별 차이가 없었고, 커밋 메시지는 한눈에 알아보기 어려웠습니다.

그래서 이번 2주 차 미션은 기존보다 구체적인 구현 기능 목록을 작성하는 것과 알아보기 쉬운 커밋 메시지를 작성하고자 했습니다.

(좌) 1주차 문제1 구현 기능 목록 / (우) 2주차 숫자 야구 게임 구현 기능 목록

구현 기능 목록을 가능한 작은 기능 단위로 작성하고 이를 토대로 기능을 테스트하고 개발하려고 신경을 썼습니다.

(좌) 1주차 커밋 메시지 / (우) 2주차 커밋 메시지

커밋 메시지는 범위를 설정해서 커밋 메시지의 "종류(범위) : 제목"만 보고 무엇을 커밋했는지 알 수 있게 작성했습니다.


느낀 점

구현 기능 목록을 작성할 때 처음에 굉장히 세세하게 작성하려다 보니 작성하기도 힘들었습니다.

또한, 개발에 들어갔을 때 기능 목록에 대한 수정 사항이 여러 로직에 많이 생겼습니다.

그 후, 다시 처음부터 개발하면서 구현 기능 목록을 큰 틀만 잡아놓고 시작했고 개발하면서 구현 기능 목록도 수정해 나갔습니다.
이렇게 구현 기능 목록을 작성하니 처음부터 세세하게 작성하는 것 보다 시간적인 부분에서는 조금 더 효율성이 있다고 느꼈습니다.


배운 점

아는 것을 연관지어 학습할 때, 효과가 크다는 걸 배웠습니다.
예를 들어, Git의 Commit과 DataBase의 스냅샷을 비교하면서 "Commit을 되돌려서 재해복구를 할 수 있겠다." 등
DataBase와 Git을 연관 지어 생각하니 집중도 잘되고 Git에 대한 호기심이 많이 자극됐습니다.

코드를 리팩토링 하면서 if문이 굉장히 많이 나왔습니다.

그래서, if문을 어떻게 하면 줄일 수 있을 지에 대한 생각으로 "Map 자료구조를 사용하자" 라는 결론을 얻었습니다.

예를 들어, 기존에 아래와 같은 코드가 있습니다.

private void checkBallStatus(BallStatus ballStatus) {
    if(ballStatus.equals(STRIKE)){
        this.strikeCount++;
        return;
    }
    if(ballStatus.equals(BALL)){
        this.ballCount++;
        return;
    }
}

위의 코드는 공의 상태를 확인해서, 해당 상태에 해당하는 멤버 변수(카운트 값)를 증가시켜주는 코드입니다.

그런데, Map 자료구조를 사용하게 되면, if문과 멤버 변수를 사용하지 않고 다음과 같은 코드를 얻을 수 있습니다.

private void checkBallStatus(BallStatus ballStatus, Map<BallStatus, Integer> ballStatusCount) {
    ballStatusCount.put(ballStatus, ballStatusCount.getOrDefault(ballStatus, 0) + 1);
}

이 예제는, 실제 이번 숫자 야구 게임을 진행하면서 사용한 코드이며, 더 많은 if문이 발생할 경우 Map을 사용함으로서 코드가 간결해질 수 있다는 걸 배웠습니다.

해당 Github : 숫자 야구 게임에 사용된 Referee 클래스


개선점

이번에 코드를 작성하면서, BaseBallGame이라는 클래스에서 모든 기능들을 조합 및 입/출력 기능을 작성했습니다.

그때, 당시에는 "굳이 다른 클래스를 만들어서 입/출력 기능을 하게하고, 다시 조합하는게 맞을 까?"라는 생각을 했습니다.

 

그러나, 지금 생각해보면 웹 어플리케이션도 MVC로 나누어 개발하는데, 입/출력도 하나의 View이니, 입력 받은 값만 넘겨주는게 맞다고 생각이 듭니다.

 

다음 미션을 진행할 때는 확실하게 객체지향적으로 클래스 분리에 신경을 써야할 것 같습니다.


시간이 지난후 결과

(좌) 2주 차 구현 기능 목록 / (우) 3주 차 구현 기능 목록

2주차에서 기능 별로만 클래스를 분리했다면

3주차에서는 도메인 로직과 사용자의 의존적인 입/출력 부분을 나누어서 구현해보았습니다.

 

MVC 패턴이 웹 프로젝트에 한정되 있는 패턴이 아니라 객체지향 코드를 작성할 때, 의존성을 낮추는 좋은 설계 방법이란 걸 깨달았습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함