나의 독학은
[프리코스 4주차] 크리스마스 프로모션 회고 본문
😊4주차 목표
- 1, 2, 3주차에 학습한 모든 것들을 코드에 녹여내서 아쉬움이 남지 않도록 최선을 다하기!
😊4주차 목표
✅ 어려울 수록 빛났던 테스트 코드
이번 주차도 <구현 → 테스트코드 → 커밋> 을 지키면서 테스트 코드의 장점인 코드에 대한 피드백을 빨리 받고자 했다.
그렇게 다음과 같은 것들을 누리게 되었다.
- 람다식으로 예외를 터뜨리거나 map 을 순회하는 람다식을 올바르게 사용할 수 있었던 이면에는 초록불이 들어올 때까지 테스트 코드를 돌려봤기 때문이었다.
- 테스트 코드를 처음 학습했던 2주차에서 알게된 "코드를 작성하면서 '어떻게 테스트를 할 것인가?' 를 자문하기" 를 지키게 되었다. 구현 전에 어떻게 테스트를 작성할지 미리 생각하게 되었고, 이는 테스트 코드를 작성하기 어려운 기능을 더 작은 단위의 기능으로 세분화할 수 있었고, 이는 살아있는 README로도 이어졌다.
- 잘못된 케이스를 검사하는 테스트코드를 발견해서 올바르게 수정할 수 있었다.
- 함수분리와 테스트코드의 코드가 많아질수록 하나의 테스트가 어떤 기능을 테스트했는지 구분하기가 어려워졌다. 이러한 문제를 해결할 수 있게 리팩토링전에도 구현 로직과 테스트 코드에게 적절한 이름을 부여할 수 있도록 충분한 시간을 갖게 되었다.
- 요구사항을 잘못 이해해서 총 메뉴의 개수를 구하는 기능에서 디저트 메뉴만 구하는 기능으로 변경해야했다. 이 때, 미리 작성했던 테스트 코드들 덕분에 재사용할 수 있는 함수를 구별해낼 수 있었습니다.
- 요구사항을 잘못 이해하는 바람에 미션을 진행하며 필요없는 필드를 구현했었다. 예를 들면 Order객체에는 Map<String, Integer> 의 자료구조 뿐만 아니라 Map<MenuBoard, Integer> 도 있었던 만큼 스스로 구현 난이도를 올려버렸었다..ㅎ 그래도, 테스트 코드를 작성한 덕분에 구현한 코드를 신뢰하며 미션을 원활하게 진행할 수 있었다.
✅ 객체 분리 : 테스트 코드에도 영향을 끼치다
이번 4주차를 통해 객체 분리는 명확한 테스트 코드를 작성하는데에도 매우 유용하단 사실을 알게 되었다.
사용자 입력 (ex.초코케이크-3,제로콜라-4) 를 이용해 주문을 생성하는 Order 객체의 생성자에는 - 와 , 를 이용해 메뉴와 개수를 나누고, 나눈 값들이 오류는 일으키지 않는지 검증하고, 타입도 변환하는 등 별의별 기능이 다 있었다.
이 기능들을 테스트 하는 코드에서는 @DisplayName을 이용해서 어떤 기능을 테스트 하는지만 나타낼 뿐,
@DisplayName이 없다면 어떤 기능을 테스트 하는지 알 수가 없었다.
그러나, Order(메뉴와 개수를 필드로 갖고있음)를 객체분리하자 OrderValidator(사용자 입력을 검증), OrderGenerator( Order 객체를 생성), OrderCalculator(String타입에서 Map으로 변환) 로 기능에 따라 분리되었다.
그러자 private 메서드가 public 으로 바뀌게 되었고, 이는 테스트 코드에서 호출할 수가 있었다.
이러한 깨달음은 마지막 날에 여러 개의 테스트도 추가하고, 테스트 하지 않는 기능들을 찾는 쏠쏠한 재미를 주었다.
✅ 중복제거를 위한 추상클래스 사용
크리스마스 디데이, 평일, 주말, 특별 할인들은 주문 금액이 10000원 이상일 때만 할인되는 조건을 갖고 있었다.
공통된 조건을 가지고 있었기 때문에 코드의 중복이 생겼고, 나는 이 중복을 없애고 싶었다.
뿐만 아니라 혜택내역을 담당하는 한 메서드에게 전달되는 매개변수가 6개였는데, 이를 줄이고 싶었다.
그래서, 오브젝트 책을 읽으며 답을 찾고자 했고, 추상클래스와 인터페이스를 이용하는 방법이 있다는 것을 알게 되었다.
이 2가지 방법을 이용하면 유연하고, 쉽게 재사용 하고, 추가 요구사항이 있을 때, 확장이 가능한 객체 지향 설계를 할 수 있다는 것이었다. 나는 설계할 때, 할인혜택들이 이벤트 기간중에 변동될 가능성이 있다고 생각했다.
그 이유는 12월의 이벤트 목표는 5년이란 기간에서 최고 주문 금액을 달성하고, 12월의 참여 고객의 5%가 1월에도 참여하도록 하는것이었다.
이 목표를 달성하기 위해서 이벤트 기간 중에 할인혜택들을 변동 시킬 가능성이 있다고 생각했고, 할인 혜택들을 변동시켜야 하는지에 대해 기준을 세울 수 있도록 아래와 같은 필드를 추가했었다.
즉, 나는 확장이 가능한 설계를 했었다.
나는 인터페이스와 추상클래스 중 추상클래스를 다음과 같은 이유로 선택했고, 이 글(추상클래스 vs 인터페이스)에 많은 도움을 받았다.
1. 중복멤버통합
- 할인조건들은 할인혜택이라는 내역(금액)을 출력하기 위해 포함하고 있어야 한다.
2. 의미적인 관계
- 클래스와 의미있는 연관관계를 구축할 때, 즉 단어 그 자체에 논리성과 의미성이 있는 연관관계이면 추상클래스를 사용한다. 특별할인, 평일할인,주말할인, 보통할인은 "날짜에 대한 할인"이라는 공통된 논리성과 의미성이 연관있다고 생각했다.
✅ 3주차 피드백 적용
[@ParameterizedTest 학습]
4주차에서는 3주차 피드백에서 테스트 코드도 코드이니 파라미터만 반복되는 경우는 아래 코드 처럼 테스트 할 수 있다고 한다.
그래서 나는 Parameterized, ValueSource, CsvSource를 사용하기 위해 이 글을 계속 보며 사용법을 익혀서 적용시켰다.
[그 외]
- 필드의 수를 줄이고자 노력했다.
- 객체는 객체스럽게 사용하기 위해 View 에서 도메인의 값을 가져올 때 빼고는 get 을 사용하지 않고, 객체에게 메시지를 보냈다!
- get 에 의해 값이 꺼내지는 변수들은 final 키워드를 이용해 값의 변을 막았고, 2주차에 미리 알게 되었던 불변컬렉션도 이용해서 값의 변경을 막아보았다!
😊한달 간의 프리코스를 마치며 : 주간의 노력들이 모여 만들어낸 성장
미션을 진행했던 날들을 복기하며 지난 한달을 되돌아 보았다.
프로젝트 경험도 없고, 백준이나 프로그래머스에서만 문제를 접했던 내게 프리코스 미션 중 쉬운 미션은 단 하나도 없었다.
객체지향? MVC? 테스트 코드? 깃? README? 모든 것이 처음이었다. 뿐만 아니라 매주의 목표와 피드백도 처음이었다.
그렇지만, 프리코스에서 배운 모든 것을 체화하고 싶었다. 코드에 다 적용하고 싶었다.
1,2,3주차마다 배운 것은 엄청 많았지만 모든 것을 체화하지 못해 항상 아쉬움이 남았었다.
매 주마다 최선을 다했음에도 아쉬움이 남자 프리코스도 체화하지 못하는데 본 코스 가더라도 잘 할 수 있을까란 생각도 하게 되었다.
그래서, 4주차 목표를 어떤 아쉬움도 남기지 않는 것으로 설정했었다.
그렇게 4주차도 최선을 다 했고, 미션을 제출하면서 느낀 것은 그 동안의 노력들이 전혀 헛되지 않았음을 느꼈다.
정말 그 동안 했던 노력에 대해 보상받는 기분이 들어 너무너무 뿌듯했다.
[첫 번째 보상]
1주차의 나의 코드는 객체에는 상태가 없고, 모든 메서드는 static이었다. 원인을 찾고자 4일을 투자했고, 이 덕에 객체라는 존재와 친해질 수 있었다. 객체는 메시지를 통해 협력하고, 메시지에 응답하기 위해 스스로 일을 하는 존재임이란 것을 기억 하게 되었다.
이 기억은 3주차에 일급컬렉션을 이해하고, 객체안에 또 다른 객체가 포함되어있는 객체를 이해하는데 큰 힘이 되었다.
또한, 이것을 깨달을 때까지 구현했던 코드들을 3번이나 뒤엎었던 경험은 객체를 다룰 수 있다는(수정 할 수 있다는) 자신감이 되었다.
이 자신감은 4주차에서 객체를 분리하는데 도움이되었다.
1주차에는 static 메서드를 지우다가 에러를 만나서 미션에 실패할 것같은 두려움 때문에 기존 코드는 보존하고 다른 곳에 처음부터 다시 구현했지만 4주차는 기존 코드를 바로 수정할 수 있었고, 성공적으로 객체 분리를 할 수 있었다.
[두 번째 보상]
2주차에서 캡슐화에 위반되는 로직인 값을 꺼내오는 코드를 발견했었고, 이를 해결하고자 했다.
이 과정에서 불변컬렉션을 알게 되어 불변의 역할을 미리 알수 있었고, 값을 전달한다는 의미를 명확하게 파악하게 되었다.이는 3주차의 도메인 로직과 UI 로직의 분리를 위해 읽었던 글과 MVC패턴을 이해하는 데에도 큰 도움이 되었다.
결국 값들을 불변으로 만들라는 3주차 피드백을 큰 어려움 없이 수용했고, 4주차에 적용시켰다.
[세 번째 보상]
1주차에 테스트 코드의 장점을 알게 되었고, 이 장점을 누리고자 구현과 테스트 코드를 함께 작성하는 것을 2주간(2, 3주차) 노력했다.
이 덕에 4주차 미션의 구현과 테스트 코드를 함께 작성하는데 어려움이 없었고, 미션을 원활하게 진행할 수 있었다고 생각한다.
뿐만 아니라 2주차에는 @Test 만을 활용한 테스트 코드 작성에도 버거웠지만, 4주차에는 JUnit의 다양한 어노테이션을 점진적으로 사용해서 테스트 코드를 작성할 수 있었다고 생각한다.
[네 번째 보상]
2주차와 3주차에 함수분리를 하려고 노력했던 덕분에 함수를 쪼개고, 어떤 것을 기능으로 봐야할지를 알게 되는 눈이 생겼다.
이는 다양한 요구사항이 많은 4주차 README 를 작성 할 때, 구현해야 할 기능들을 이전과 다르게 작성할 수 있게 되었고, 바뀐 README 덕분에 어려운 구현 속에서도 길을 잃지 않고 미션을 완주할 수 있었다고 생각한다.
이렇게 매 주마다 노력했던 행동들이 하나 둘 모여 4주차 미션을 완성시키는 데 도움을 줬다.
지금 이 글을 쓰면서 미션에 대해 아쉬움이 전혀 없다. 정말 이토록 후련할 수 있을까 싶다. 너무 후련하다.
이 글을 볼 때마다 내가 느끼고 있는 이 감정을 기억하고 싶기에 오글거릴 수 있겠지만 남겨본다.
어떤 마음으로 독학 해왔고, 프리코스에 참여했는지 스스로가 알기에 나는 지금의 내가 자랑스럽다.
후련하며 벅차다.
😊앞으로의 계획
3주차 코수타에서 코치님이 말씀하신 핵심 기능을 파악해서 핵심 기능부터 구현하기를 4주차에 적용하고자 2일 동안 노력했으나, 실력 부족으로 인해 기존에 했던 방식인 입력부터 구현해 나갔다.
그래서, 1~4주의 미션들을 핵심 기능부터 다시 구현해 보려고 한다.
프리코스의 요구사항을 지킬때 마다 성장과 배움을 얻었었기에 이 가르침에도 분명히 성장할 수 있는 발판이 있다고 확신한다.
성장하고 후기를 남겨보도록 하겠다😊 -> 클릭
'회고 > 우아한테크코스 6기 프리코스 회고' 카테고리의 다른 글
[프리코스 3주차] 로또 게임 회고 (1) | 2023.11.09 |
---|---|
[프리코스 3주차] - 좋은 네이밍을 위한 규칙 (0) | 2023.11.09 |
[프리코스 2주차] 1주차 공통 피드백 학습 (0) | 2023.11.02 |
[프리코스 2주차] 자동차 경주 게임 회고 (0) | 2023.11.01 |
[프리코스 1주차] 자바 코딩 컨벤션(해설) (1) | 2023.10.26 |