[크리스마스 프로모션] 코드
3주차 과제를 진행한 repo 주소이다.
https://github.com/Dreaming-J/java-christmas-6-Dreaming-J
4주차 회고
정말 역대급 미션이었다.
과제를 해결하기 위해 며칠동안 아침부터 자기 전까지 코드만 보면서 지내왔다.
이번에는 과제를 통과하기 위해 급급했기에 나를 돌이켜 볼 시간이 많이 부족했다.
사실 졸업논문과 시기가 겹쳐 얼른 끝내고 졸업논문을 처리해야 한다는 조급한 마음도 있었다.
정말 어려웠지만 그만큼 최종 테스트가 통과했을 때는 굉장히 뿌듯했다.
확인해보니 40개가 넘는 코드 파일에 라인 수는 1,700줄이 넘어갔다.
이번 과제를 하며 기능 목록 작성, 객체 역할 분리 이 키워드를 중심적으로 생각하며 구현을 해나갔다.
그리고 입력 예외 처리, 상속과 인터페이스 이 키워드들은 나에게 고민을 던져 준 키워드이다.
기능 목록 작성
그 동안 과제를 하며 기능 목록은 프로그램의 설계도 역할이었다.
그렇기에 잘 작성해야 목표로 하는 기능을 만들고 이어붙여 프로그램이 될 수 있다고 생각했다.
즉, 기능 목록 작성의 중요도가 아주 높다고 생각하고 좋은 기능 목록으로 작성하려 많이 노력했다.
기능 목록을 완벽하게 작성하는 것은 어려운 일이라고 생각했지만, 기본적인 골자는 튼튼하고 꼼꼼하게 만들고 싶었다.
하지만 이번 과제를 하며 내 설계도에 아주 큰 문제 있음을 깨달았다.
문제점은 바로 설계도의 핵심 내용 "조립 방법"이 누락되어 있다는 점이다.
설계도에는 2가지 필수 요소가 있다고 생각한다.
바로 "필요 부품"과 "조립 방법"이다.
필요 부품이 적혀 있어야 해당 부품들을 준비할 수 있고, 조립 방법이 있어야 부품들을 조립할 수 있기 때문이다.
하지만 내가 작성한 기능 목록에는 필요 부품만 있고 조립 방법에 대한 내용이 적혀 있지 않았다.
그러니 기능을 다 만들어도 어떻게 이어붙일 것인가를 고려하지 않았기에 길을 잃고 말았다.
다리가 되어 줄 클래스가 없으니 모든 기능들이 유기적으로 연결되지 못하고 독립된 섬으로 둥둥 떠다니고 있었다.
뒤늦게 설계해서 지어줬지만, 급하게 지은 다리라 튼튼하지 못함을 스스로 느꼈다.
앞으로는 어떻게 연결해줄 것인지도 같이 생각하며 설계를 해야 된다고 생각했다.
또한, 이렇게 아무리 꼼꼼히 작성했다고 생각하더라도 문제점이 생기기에 기능 목록의 또 다른 중요한 점은 살아 있는 문서로 만들어야 한다고 생각했다.
코드를 작성하다 생기는 문제점을 해결하기 위해 변경된 블록을 설계도에도 기록해주어야 다른 블록들에 이격이 생길 가능성을 줄여준다고 생각한다.
객체 역할 분리
매주 나오는 단골 키워드인 듯 하다.
객체의 역할을 분리해주기 위해 꾸준히 고민을 하게 된다.
이게 매주 나오는 이유는 바로 분리에 답이 없어서라고 생각한다.
이 역할은 해당 객체가 짊어져도 괜찮은가?를 스스로에게 물어보고 스스로의 기준으로 판단해야 하기에 너무 어려운 것 같다.
이번 과제에서 느낀 역할 분리의 어려움을 하나 설명해본다.
입력된 주문 문자열을 EnumMap으로 가공하는 역할은 주문 객체가 진행하는 것이 옳은가?를 생각해보았다.
처음에는 주문 객체에서 가공을 진행했으나 계속 코드를 작성하다보니 생각이 바뀌었다.
EnumMap으로 가공하는 것을 처음에는 단순 저장이라고 생각했으나, Map으로 변환하는 과정이 생각보다 복잡하여 하나의 기능을 하고 있다고 생각하게 됐다.
주문 객체는 메뉴와 관련된 정보를 제공하는 역할이지 주문을 가공하는 역할은 따로 있다고 생각이 들었다.
그래서 최종적으로는 OrderMapGenerator라는 객체를 생성하여 주문된 메뉴의 유효성 검사 후 가공하는 역할을 지어주었다.
이 판단에 정답은 없다고 생각이 든다.
하지만 더 좋다고 느끼는 또 다른 해결방안은 있다고 생각한다.
아직 내 수준에서는 여기까지 생각했지만 더 좋은 방안을 생각할 수 있는 개발자가 되고 싶다고 생각했다.
입력 예외 처리
이번 과제에 입력은 날짜와 주문 2가지 뿐이었다.
그리고 예외 상황 메시지를 제시해주어 쉬울 것이라 생각했다.
하지만 입력 문자열을 숫자로 변환하는 과정에서 예상치 못한 변수가 생겼다.
나는 형 변환 기능을 TypeConverter 객체로 따로 분리하여 util 패키지에 보관하는 걸 좋아한다.
날짜와 주문 메뉴의 개수의 입력으로 숫자가 아닌 값을 입력했을 때 출력되는 에러 메시지에 문제가 생겼다.
숫자로 변환하다 문제가 생겼을 때, 어떤 입력이든 동일한 메시지를 출력했다.
이를 해결하고자 고민하다 결국 정규표현식을 활용하려 했다.
정규표현식으로 유효성 검사를 하여 적합한 입력인지 판단한 후, 형 변환을 진행하는 것이다.
이렇게 하면 형 변환을 하는 시점에선 숫자임이 보장되기에 좋은 판단이라고 생각했다.
그러나 Date를 record로 선언해주어 문제가 생겼다.
record에서 생성자에서 형 변환이 불가능하다고 알고 있어 해당 부분을 적용하지 못했다.
그냥 평범한 클래스로 생성하는 것도 생각했으나 시간이 촉박하여 힘들었다.
다음에는 특정 클래스를 만들 때, class인지 enum인지 record인지 잘 고민해보고 선택하는 것이 좋겠다.
상속과 인터페이스
이벤트 종류가 5개가 있어 기능 목록을 작성할 때, 인터페이스를 활용하자고 생각했다.
그렇게 하면 하나의 리스트로 관리가 가능하니 코드짜기가 훨씬 수월해질 거라 판단했다.
그러나 직접 코드를 작성해보니 예상치 못한 문제에 직면했다.
인터페이스 사용이 어색해서 어떤 함수를 미리 선언해놔야 할지 결정하는 것에서도 어려움이 있었다.
그래서 클래스 하나를 먼저 작성하고 해당 클래스에서 공통으로 활용될 것 같은 부분을 인터페이스에 선언하는 식으로 구현했다.
그리고 공통 변수가 있으면 좋겠다는 판단이 들어 결국 추상 클래스로 변경했다.
도메인에 대한 이해도가 더 높았다면 어려움이 크지 않았을텐데 하는 생각이 들었다.
그리고 여러 이벤트 객체를 하나의 리스트로 관리하려니 특정 클래스를 꺼내오는 것에도 어려움이 있었다.
그래서 각 이벤트에 해당하는 enum 클래스를 생성 후, Map을 활용하여 관리하니 코드가 더욱 간결해졌다.
4주차 아쉬웠던 점
도메인의 이해도가 높을수록 더 깔끔한 구현이 나온다는 생각이 들었다.
지금까지의 과제의 도메인은 이미 알고 있는 내용이거나 쉬웠기에 구현을 하며 혼란을 겪은 적이 적었다.
하지만 복잡한 도메인이 들어오니 이해도가 낮아지고 기능목록이 작성에 어려움을 겪었다.
도메인을 이해하기 위해 더 시간을 투자하는 방향은 좋은 것 같다.
코수타를 늦게 본 점이 아쉬웠다.
조금 바쁜 일이 있어서 과제를 마무리하고 코수타를 시청했는데 많은 팁을 얻을 수 있었다.
프로그램의 핵심 기능을 파악하고 그 기능부터 만들자!
동작 가능한 가장 작은 단위부터 기능을 구현하자!
이 두 가지 얘기가 아주 와닿았다.
다음에는 이렇게 구현할 수 있도록 노력해야겠다.
프리코스를 종료하며
4번의 과제를 진행하며 프로그래밍에서 레고를 조립하는 듯한 느낌이 들어 아주 재밌게 구현을 했다.
일반 레고 조립과 다른 점이 있다면 레고 설계(기능 목록 작성)부터 블록 생성(기능 구현)까지 직접한다는 점이었다.
설계하고 기능을 만드는 과정은 어려웠지만 뿌듯했으며, 조립하며 하나씩 이어붙일 때는 재밌었다.
이 점이 더욱 매력적으로 다가오는 시간이었다.
이제 1차 합격자 발표를 기다리며 최종 코딩 테스트를 준비하는 수순이 남았다.
(1차 합격이 되야 최종 코딩 테스트를 칠 수 있지만...! 꼭 붙게 해주세요!!!)
비록 1차 합격이 되지 않더라도 4주동안의 시간에 너무 많은 성장을 해서 아주 유익한 시간이었다.
그래도 더 유익해지고 싶으니 제발 최종 코딩 테스트 기회를 얻고 싶다.
(기왕이면 최종 합격까지 ㅎㅎ)
한 달동안 나를 포함하여 함께 달려온 프리코스 참가자들 모두에게 수고했다는 말을 하고 싶다.
다들 수고했습니다 :)