2주차 프리코스 진행 후 마지막 3주차 미션과 함께 공통 피드백을 보내주셨다.
기능 목록은 언제든지 변경가능한 부분이다. 구현 시작 전에 모든 기능 목록을 완벽하게 작성할 수 없다. 따라서 너무 상세하게 작성할 필요가 없고 수시로 업데이트 해준다. 특히 예외 사항도 잘 정리해둬야한다.
필요한 기능을 java api에서 제공한다면 직접 구현하기 보다 가져다 쓰는게 좋다. 검색부터 해보자
List, Set, Map 등의 collection을 사용하면 데이터 조작에 필요한 다양한 api를 사용할 수 있다. 적극 활용하자.
상태 데이터를 가지는 객체에서 데이터를 꺼내(getter) 로직을 구현하지 말고, 객체에 메세지를 보내 객체가 스스로 작업할 수 있도록 해라!
인스턴스 변수가 많아지면 복잡해지고 버그도 발생할 수 있다. 중복이나 불필요한 인스턴스 변수는 없는지 체크
한 클래스에서 비지니스 로직과 UI로직을 모두 처리해서는 안된다. 단일 책임 원칙에 위배! view에서 사용하려면 getter를 통해 사용하기
3주차 프리코스는 지하철 노선도 미션이었다. 1주차, 2주차 미션에 비해 규모가 좀 커진 느낌이었다. 3주차 미션의 목표는 클래스를 분리하고 서로 관계를 맺어 하나의 프로그램을 완성해보는 것이었다.
문제 설명과 제출한 코드는 => 여기로 가시면 볼 수 있습니다!
3주차 미션은 아래와 같은 기본 틀이 주어졌다.
repository를 보니 spring을 사용해 프로젝트를 진행하던 생각이났고, MVC 패턴을 적용해보자는 생각이 들었다.
3주차쯤 되니 어느새 기능 목록 작성이 조금은 익숙해진 것 같다. 미션을 설명해주신 README가 기능별로 잘 적혀있어서 기능 목록 작성이 수월했다. 피드백 보내주신 것 처럼 처음부터 모든 예외 사항 같은 것을 생각해내려 하지 않고 바로바로 떠오르는 정도만 적어주고 수시로 업데이트 해주었다!
패키지 구조를 나누는 건 아직 조금 어렵다. 2주차 때 패키지 구조에 대해 공부했던 것을 바탕으로 package-by-feature 로 패키지 구조를 설정했다.
이번 미션은 크게 '지하철 역 관리', '노선 관리', '구간 관리', '노선도 출력'의 기능으로 이루어진 프로그램이었다. 처음에는 구간 관리와 노선도 출력은 어차피 '노선 관리'로 볼 수도 있지 않을까? 라는 생각을 하고 지하철 역 관리를 담당할 station
과 노선을 관리할line
패키지 2개로 나눠주려고 했다.
하지만 이렇게 하니 line
이 너무 커진다는 생각이 들었고, '구간 관리'와 '노선도 출력'도 하나의 큰 기능을 담당하는 부분이니 각각 패키지를 분리해주고 각각 controller를 만들어서 관리해주기로 했다.
각 기능들도 비슷한 요소가 있어서 공통적인 기능을 담당할 common
패키지도 만들어주고, 출력을 담당하는 view도 아에 분리시켜주었다.
그래서 최종적으로 아래와 같은 패키지 구조가 완성되었다.
클래스 분리도 패키지 구조와 마찬가지로 감이 완전히 오지는 않는 상태지만 나름대로 고민을 많이했다.
MVC패턴을 적용해보기 위해 각 패키지 별로 model
, controller
, service
, repository
를 두었다.
이 클래스 구조를 만족시키면서 코딩을 할 때 많은 시행착오가 있었다. 이 프로그램이 web이 아니어서 spring과 조금 차이점이 있어서 controller
와 service
를 나누는 것에서 생각을 많이했다.
그러고 스스로 기준을 잡고 controller
와 service
를 나누기 시작했다.
controller
: 사용자에게 화면을 보여주거나, 사용자의 입력을 받는 부분은 controller에서 모두 처리
service
: repository에 직접 접근하거나 데이터를 추가, 삭제하는 행위는 모두 service에서 처리
이 기준을 가지고 코드를 수정해나갔고 개인적으로 처음 코드에 비해 많이 정리가 됐다는 느낌을 받았다.
'예외처리를 어디서 해야할까?'도 이번 미션에서 많은 고민을 하게한 부분 중 하나이다.
코딩을 하다보니 어떤 패키지에서는 controller
단에서 검증 작업을 거친 후 service로 넘겨주는 부분도 있었고, 어떤 패키지에서는 service
에서 데이터를 받아서 검증 작업을 거쳐주는 식으로 코딩된 부분도 있었다. 일관성이 없다는 생각이들어서 너무 찝찝했다.
이부분도 계속 생각해보고 검색도 많이 해보고 내린 결론이 'controller
단에서 검증 작업까지 마친 후 service
로 넘겨주게 통일시키자'였다.
spring에서 클라이언트의 요청이 들어오면 검증 작업을 할 때, model
에 Validation anotation을 붙여주고 controller
에서 검증하듯이 controller
단에서 검증 작업까지 해주기로 결정했고 코드를 수정했다.
service
의 코드가 지나치게 짧아지는 것 같기도 하고 어떤 메소드는 repository를 호출하는 작업밖에 하지 않게 만든 것 같아서 '이게 맞나..?'하는 생각도 들긴 했지만 내 생각엔 이게 가장 맞다고 생각하였다.
기능 별로 controller
를 나눠 코딩을 하면서 든 생각이 '완전히는 아니어도 어느정도 구조가 중복되지 않나?' 라는 생각이 들었다.
1) 선택지 보여주기
2) 추가
3) 삭제
4) 출력
'팩토리 메소드 패턴'를 한 번 적용해 볼 수 있지 않을까? 라는 생각도 해봤지만 패키지 구조, 클래스 분리 등을 고민하면서 시간을 너무 많이 써서 아쉽게도 시도해보지 못했지만 이런 중복된 구조를 충분히 활용할 수 있을 것 같다는 생각이 들었다.
관련있는 상수를 처리할 때 static final로 사용할 수도 있지만 enum을 사용할 수 있다고 한다.
클래스 내에 상수를 선언해서 사용하는 경우 네이밍도 겹칠 수 있고, 불 필요한 상수가 많아질수도 있다고 한다.
이를 보완하기 위해 enum을 사용할 수 있는데, enum class를 생성하면 하나의 인스턴스로 생성되어 싱글톤으로 어플리케이션 전체에서 사용할 수 있다고 한다.
이번 미션에서 선택지 출력시 '추가, 삭제, 조회, 돌아가기' 이 부분을 enum을 적용해 볼 수 있지 않을까 했으나 마찬가지로 패키지 구조, 클래스 분리 등을 고민하면서 시간을 너무 많이 써서 아쉽게도 시도해보지 못했다.
3주차에 가장 많은 시간을 투자했는데, 중복 구조 처리, enum 활용 등을 적용해보지 못한채로 제출하게 된 것이 조금 아쉽다. 하지만 패키지 구조와, 클래스 분리가 그래도 어느 정도는 깔끔하게 되지 않았나 싶은 생각이 들기도 한다.(제 기준에서는..) 이번 과제를 하면서 1주차, 2주차 때 시간이 오래 걸렸던 컨벤션 적용이나, indent depth 맞추기, 함수 분리, else 쓰지 않기, setter 쓰지 않기 등이 생각보다 몸에 익은 것 같아 신기했다. 그만큼 경험치가 쌓였다고 생각한다. 실제로 자연스럽게 일상생활 중에도 계속 '어떻게 패키지를 나누지?', '어떻게 클래스를 분리하지?' 등의 생각을 계속하면서 지냈던 것 같고 재밌었다. 또 피드백을 받아서 보완해 나가고 싶다.
이번 과제를 끝으로 3주간의 프리코스를 모두 끝마쳤다. 가장 먼저 드는 생각은 재미있었다는 생각이다. 그냥 돌아가기만 하면 되는거지 했던 과거를 반성하게 되는 시간이었고, 컨벤션, git message, 객체 지향 생활체조, solid 원칙 등 여러 객체 지향 규칙들, 많은 피드백 등등 짧은 시간이지만 많은 것을 얻어간 가치 있는 시간이었어서 너무 감사하고 우테코에 붙고 싶다는 욕심이 더 커지게 된 시간인 것 같다. 이제 최종 테스트만 남았는데 3주차 미션 정도로 나온다면 5시간만에 다하긴 어려울 것 같다.(이번 미션에 시간을 굉장히 많이 썼기 때문..) 하지만 아직 시간이 남았으니 진짜 잘 준비해서 좋은 결과가 있길 바란다.