티스토리 뷰
지난 회고 보기
이번 과정을 통해 객체지향의 이론을 실전에서 적용하는 것은 굉장히 어렵다는 걸 느꼈습니다.
한 것
객체지향 학습
이번 학습 목표인 객체를 분리하는 연습, UI와 비즈니스 로직을 분리하는 연습인 만큼 다시 한번 객체지향과 디자인 패턴 그중에서 MVC 패턴을 학습하는 계기가 되었습니다.
객체를 어떻게 하면 잘 분리할 수 있을 까 고민하다가 객체지향의 핵심인 SOLID 원칙을 학습하고, 이 중에서 단일책임의 원칙(SRP)을 이번 미션에 최대한 적용하려고 노력했습니다.
단일책임의 원칙(SRP):
클래스는 단 한개의 책임을 가져야한다. (여기서 책임은 변경하려는 이유를 의미)
즉, 클래스를 변경하는 이유는 단 하나여야 한다.
이를 지키지 않으면, 한 책임의 변경에 의해 다른 책임과 관련된 코드에 영향을 미칠 수 있다
→ 이렇게 되면 유지보수가 매우 비효율적
이 과정에서 클래스를 최대한 작게 만들고 클래스끼리의 의존성을 낮추기 위한 많은 고민을 하였습니다.
도메인 클래스의 의존성을 낮추다 보니, 도메인을 결합해주는 로직이 필요했는데 이 부분을 MVC패턴의 Controller를 만들어서 View의 입력을 받고, 도메인의 비즈니스 로직을 실행시켜, 애플리케이션을 동작하게 하였습니다.
- Model은 Controller와 View에 의존하지 않아야 한다.
- View는 Model에만 의존해야 하고, Controller에는 의존하면 안된다.
- View가 Model로부터 데이터를 받을 때는, 사용자마다 다르게 보여주어야 하는 데이터에 대해서만 받아야 한다.
- Controller는 Model과 View에 의존해도 된다.
- View가 Model로부터 데이터를 받을 때, 반드시 Controller에서 받아야 한다.
(의존이란 의미는 쉽게 말해 A, B 파트가 있을 때, A 코드에 B 코드가 존재한다면 A는 B를 의존한다고 말한다.)
또한, 이 과정에서 DTO 사용을 고려해봤지만, 이렇게 하면 해당 프로젝트가 더 복잡해질 것 같았기에 반환값을 자바의 기본 자료형을 반환할 수 있도록 노력하였습니다.
아쉬웠던 부분은 핵심 도메인인 Lotto와 당첨 순위를 나타내는 LottoRanking(Enum)은 조금 노출되었다는 점입니다.
(나름대로 이를 보완하기 위해 클래스 내의 메소드들을 최대한 private으로 만들었습니다.)
참고자료:
SOLID 원칙, 어렵지 않다!
MVC(Model, View, Controller) Pattern
(10분 테코톡) 🧀 제리의 MVC 패턴
미션 과정
3주 차 미션은 "로또" 구현이였습니다. 기존과 마찬가지로 기능 요구 사항, 프로그래밍 요구 사항, 과제 진행 요구 사항 세 가지를 지키면서 미션을 완료하면 됩니다.
3주 차에서는 추가로 클래스(객체) 분리, 도메인 로직에 대한 단위 테스트 작성, UI와 비즈니스 로직 분리 연습을 목표로 하고 있습니다.
또한, 저번 2주 차 피드백으로 아래 3가지 사항을 유의하며 이번 미션을 진행했습니다.
1. 기능 목록을 재검토한다
"2주 차 때, 기능 목록에는 클래스명을 기록했는데, 이 부분은 바뀔 수 있기 때문에 제거하고 정상적인 경우 말고 예외 상황을 기능 목록에 정리한다."
위 피드백을 적용해 이번 미션때는 구현 기능 목록을 작성할 때, [예외처리] 라는 키워드를 사용하여 예외 상황을 구분하였습니다.
2. 값을 하드 코딩하지 않는다
"문자열, 숫자 등의 값을 하드 코딩하지 마라. 상수(static final)를 만들고 이름을 부여해 이 변수의 역할이 무엇인지 의도를 드러내라."
public static final int EMPTY_COUNT = 0;
private int getTotalReward(Map<LottoRanking, Integer> result) {
return result.keySet()
.stream()
.mapToInt(ranking -> ranking.getReward() * result.getOrDefault(ranking, EMPTY_COUNT))
.reduce(Integer::sum)
.orElse(EMPTY_COUNT);
}
지난 미션에서는 큰 틀에서만 상수를 사용하고 있었는데, 나중에 보면 헷갈릴거 같은 부분들은 상수를 만들고 사용하였습니다.
3. 테스트를 작성하는 이유에 대해 본인의 경험을 토대로 정리해본다
이 피드백을 통해, 제가 생각한 테스트를 작성하는 이유는 "단순히 생각한 기능 목록에 대해 방향성을 알 수 있고 잘못된 부분이 있으면 빠르게 수정할 수 있기 때문" 이라고 생각 합니다.
(이에 대한 생각의 이유는 아래 배운점에 포함되어 있습니다.)
배운 점
기능 목록을 통해 테스트를 작성하고 기능 설계에 빠른 수정이 가능하다는 걸 배웠습니다.
처음 설계할 때, 입/출력 담당 부분에서 모든 예외 처리를 계획했습니다.
#구현 기능 목록
## 로또 판매원
- [ ] 고객에게 로또 구입 금액에 맞는 로또 개수를 반환한다.
## 로또 자동 발행기
- [ ] 로또 개수만큼 로또를 발행한다.
- [ ] 로또 발행은 개수만큼 자동으로 발행한다.
## 로또 통계
- [ ] 구매한 로또의 당첨 통계를 계산한다.
- [ ] 구매한 로또 번호의 당첨 내역을 계산한다.
- [ ] 구매한 로또의 수익률을 계산한다.
## 입력
- [ ] 로또 구입 금액을 입력 받는다.
- [ ] [예외처리] 입력이 숫자가 아닌 경우 예외 처리한다.
- [ ] [예외처리] 1,000원보다 작은 경우 예외 처리한다.
- [ ] [예외처리] 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다.
- [ ] 당첨 번호를 입력 받는다.
- [ ] 입력받은 번호를 쉼표(,)를 기준으로 구분한다.
- [ ] [예외처리] 쉼표로 구분 되지 않으면 예외 처리한다.
- [ ] [예외처리] 구분된 숫자가 6개가 아니면 예외 처리한다.
- [ ] [예외처리] 숫자가 1~45의 수가 아니면 예외 처리한다.
- [ ] [예외처리] 숫자가 중복 되면 예외 처리한다.
- [ ] 보너스 번호를 입력 받는다.
- [ ] [예외처리] 숫자가 1~45의 수가 아니면 예외 처리한다.
- [ ] [예외처리] 숫자가 당첨 번호와 중복 되면 예외 처리한다.
처음 설계한 기능 목록
그러나, 테스트를 작성하는 과정에서 2가지 문제점을 발견하였습니다.
1. 예외 처리에 대한 로직을 검증하기 힘들다.
2. View를 담당하는 입/출력에서 비즈니스 로직과 관련된 부분이 노출이 발생한다.
이를 해결하기 위해, 도메인에 대한 예외 처리와 View에 대한 예외 처리 부분을 따로 추출하여 해당하는 클래스에서 담당하게 하였습니다.
#구현 기능 목록
## 로또
- [ ] 1~45 사이의 서로 다른 6개의 숫자로 이루어진다.
- [ ] [예외처리] 구분된 숫자가 6개가 아니면 예외 처리한다.
- [ ] [예외처리] 숫자가 1~45의 수가 아니면 예외 처리한다.
- [ ] [예외처리] 숫자가 중복 되면 예외 처리한다.
## 보너스 번호
- [ ] 1~45 사이의 당첨 번호와 중복되지 않는 숫자 하나이다.
- [ ] [예외처리] 숫자가 1~45의 수가 아니면 예외 처리한다.
- [ ] [예외처리] 숫자가 당첨 번호와 중복 되면 예외 처리한다.
## 로또 판매
- [x] 고객에게 로또 구입 금액에 맞는 로또 개수를 반환한다.
- [ ] [예외처리] 1,000원보다 작은 경우 예외 처리한다.
- [ ] [예외처리] 1,000원으로 나누어 떨어지지 않는 경우 예외 처리한다.
## 로또 발행
- [ ] 로또 개수만큼 로또를 발행한다.
- [ ] 로또 발행은 개수만큼 자동으로 발행한다.
## 로또 통계
- [ ] 구매한 로또의 당첨 통계를 계산한다.
- [ ] 구매한 로또 번호의 당첨 내역을 계산한다.
- [ ] 구매한 로또의 수익률을 계산한다.
## 입력
- [ ] 로또 구입 금액을 입력 받는다.
- [ ] [예외처리] 입력이 숫자가 아닌 경우 예외 처리한다.
- [ ] 당첨 번호를 입력 받는다.
- [ ] [예외처리] 숫자와 쉼표로만 구성되어야 한다.
- [ ] [예외처리] 쉼표로 구분 되지 않으면 예외 처리한다.
- [ ] 보너스 번호를 입력 받는다.
- [ ] [예외처리] 숫자로만 구성되어야 한다.
예외처리를 분리한 기능 목록
위 과정을 통해, 테스트를 작성함으로서 변경(코드 로직 변경)과 구상한 설계에 대한 빠른 피드백을 얻을 수 있다는 걸 배웠습니다.
느낀 점
이제 마지막 한 주가 남았다는 게 믿기지 않을 정도로 시간이 정말 빠르게 지나가는 것 같습니다.
리뷰를 작성하면서 현재까지 했던 과제들을 살펴보았는데, 많은 변화가 있었습니다.
기능 목록을 작성하는 것도 기존에는 기능 요구 사항과 차이가 없었다면 현재는 그래도 기능별로 나누어져 있고, 예외 처리도 잘 작성되고 있는 것 같습니다.
또한, 한 주마다 블로그에 회고를 작성하고 있는데, 첫 주차 때는 미션을 하면서 정리한 것을 토대로 회고를 작성하는데 3일 정도가 걸렸지만, 이제는 하루 만에 쓸 수 있을 정도로 글 쓰는 것도 익숙해지고 있습니다.
프리코스 과정이 생각보다 쉽지 않고 부족한 부분을 미션과 피드백을 통해 많이 알게 되었습니다.
남은 한 주도 배운 것을 토대로 부족한 점을 개선할 수 있도록 최대한 노력해보겠습니다.
개선점
회고를 작성하면서 슬랙을 확인해보니 수익률의 출력양식이 다음과 같았습니다.
"기능 요구 사항의 소수점 둘째 자리에서 반올림한다." 이 부분에만 관심을 두고 보니
예시에 수익률이 세자리 수가 넘어가는 경우 1,000,000.0% 이렇게 ',' 표시를 놓쳤습니다.
미션을 수행하면서 나중에 해야지.. 하고 기록을 해두지 않으니 이런일이 발생한 것 같습니다.
마지막 주차에서는 기능 요구 사항의 예시도 꼼꼼히 확인하고
구현 기능 목록에 예시까지 확실히 기록해둬야할 것 같습니다..
시간이 지난후 결과
다음주 미션 후 작성 예정..
'Experience & Projects' 카테고리의 다른 글
[우아한 테크코스 5기] 지원 후기 (+결과) (4) | 2023.01.01 |
---|---|
[우아한 테크코스 5기] 프리코스 4주차 회고 (제약사항 준수하며 코딩) (0) | 2022.11.22 |
[우아한 테크코스 5기] 프리코스 2주 차 회고 (구현 기능 목록 작성) (0) | 2022.11.09 |
[우아한 테크코스 5기] 프리코스 1주차 회고 (Convention과 Clean Code) (2) | 2022.11.04 |
면접 피드백과 15개월 간의 1일 1커밋 종료 및 후기 (2) | 2022.09.29 |