온보딩 problem1 리팩토링

MINJU·2022년 12월 4일
0

문제 1

기능 정의

[ 기능 ]
- [ ] 홀수, 짝수 임의의 숫자 2개 가져오기 
- [ ] 각 페이지의 각 자리 숫자를 모두 더하기
- [ ] 각 페이지의 각 자리 숫자를 모두 곱하기 
- [ ] 위 두 개의 값 중 가장 큰 값 반환하기
- [ ] 최종 점수 구하기


[ 예외 ]
- [ ] 왼쪽 페이지가 홀수가 아닌 경우
- [ ] 오른쪽 페이지가 짝수가 아닌 경우
- [ ] 모든 페이지에 번호가 적혀 있지 않은 경우
- [ ] 왼쪽 페이지와 오른쪽 페이지가 이어지지 않는 경우 (숫자가)
- [ ] 두 가지의 숫자가 주어지지 않는 경우

구현

단순히 1, 2, 0, -1을 반환하는 solution 메소드를 완성하는 미션이었는데, 최대한 4주차 미션과 비슷하게 구현해보고 싶어서 내용을 조금 바꿨다!!

MVC 패턴을 도입했고 사용자에게 왼쪽, 오른쪽 페이지를 직접 입력받을 수 있게 구현했다.
그리고 예외가 발생하면 예외를 출력하고 그 부분을 다시 입력 받을 수 있도록 구현했다.

커밋 기록

https://github.com/JoungMinJu/java-onboarding/commits/refactor

문제가 단순하고, 이미 해봤던 로직이라 그런지 커밋 기록이 처음으로 깔끔하게 나와줬다ㅠㅠ

Book 엔티티

package onboarding.problem1.model;

import onboarding.problem1.util.Validator;

import java.util.ArrayList;
import java.util.List;

public class Book {
    private final List<Integer> pages;

    public Book(List<Integer> pages) {
        Validator.validatePages(pages);
        this.pages = new ArrayList<>(pages);
    }

    public int getSumScore(int index) {
        int tmp = pages.get(index);
        int answer = 0;

        while (tmp > 0) {
            answer += (tmp % 10);
            tmp /= 10;
        }
        return answer;
    }

    public int getMultiScore(int index) {
        int tmp = pages.get(index);
        int answer = 1;
        while (tmp > 0) {
            answer *= (tmp % 10);
            tmp /= 10;
        }
        return answer;
    }
}

페이지 번호인 List<Integer> pages를 관리하는 Book 클래스를 만들었다.

지금 생각해보니까 Pages가 더 직관적인가??하는 생각은 든다.🙂

해당 클래스는 일종의 일급컬렉션이므로 pages를 건드리는 로직은 해당 클래스 내부에 있어야한다는 생각이 들어서 getSumScoregetMultiScore 메소드를 클래스 내부에 배치했다.

이 메소드들은 전부 index를 받아와서 그 페이지의 숫자 값을 반환하는 메소드인데, 이 부분을 어떻게 관리해야하는지에 대한 고민이 들었다.

pages가 두 장이라는 것을 Book 클래스만 알아야하나?는 생각이 들었는데, 어차피 페이지가 두 장인것은 Validator도 아는 정보라는 생각이 들어 Player 클래스에서 해당 로직을 관리하도록 만들었다.

근데 회고록을 쓰면서 생각난 부분인데, 그냥 아예 Book 클래스 내부에서 sumScore의 최대값을 반환해주는게 더 맞는듯??싶다. 회고록을 쓰고 해당 부분을 리팩토링 해야겠다😭

Player 엔티티

package onboarding.problem1.model;

import java.util.List;

public class Player {
    private String name;
    private Book book;
    private int score;

    public Player(String name, List<Integer> pages){
        this.name = name;
        this.book = new Book(pages);
        this.score = 0;
    }

    private void updateScore(){
        int maxSumScore = Math.max(book.getSumScore(0), book.getSumScore(1));
        int maxMultiScore = Math.max(book.getMultiScore(0), book.getMultiScore(1));
        score = Math.max(maxSumScore, maxMultiScore);
    }

    public int getScore(){
        updateScore();
        return score;
    }

    public String getName(){
        return name;
    }
}

Book 필드를 가지고 있는 Player 엔티티인만큼, 자체적으로 Player의 최고 점수를 update하고 그 점수를 반환하도록 getScore 메소드를 만들었다!

로직이 분리되었지만, 결국 getScore() 메소드를 활용하면 되기 때문에 숨길 부분은 숨기고, 테스트가 필요한 부분은 테스트가 용이하게(?) 코드를 작성한 것 같아 나름 맘에 든다 ~ ~


가장 처음 있었던 미션의 첫 번째 문제였음에도, MVC 패턴을 적용해서, 그리고 이전 미션을 하면서 적용했던 조건들을 고려하면서 구현하자니 꽤나 어려웠던 ㅠㅠ 리팩토링 과정이었다.

그래도 고민하는 과정이 조금은 체화가 된 것 같아서 뿌듯하다:)

0개의 댓글