우아한 테크코스 최종 미션
최종 미션은 pair-matching 으로,
개발 파트별로 함께 프로젝트할 크루를 매칭해주는 미션이었습니다.
시작에 앞서 미션에 대한 요약을 우선하자면,
진짜 진짜 진짜
30분만 더 있었으면 완성할 수 있겠다....
라는 생각이 강했습니다.
기능 구현은 다해놓고, I/O 로직(콘솔)을 처리하는데 시간이 부족해서
결국 TestApplication을 통과하지 못했습니다.
그럼 이제 제가 미션을 수행한 과정과 시행착오, 해결방안에 대해서 이야기 해보겠습니다.
1. 미션에 대한 이해, 기능 요구사항, 예외 사항 작성 및 대략적 클래스 설계
시간을 약 한시간 정도 투자해서 첫번째 단계를 완성한 것 같습니다.
제공해야할 기능은 페어 매칭, 페어 조회, 페어 초기화 였으며,
제가 구현할 부분을 정리해둔 사항은 이렇게 됐습니다.
위의 README를 바탕으로
저는 D&C 하여 작개 쪼개서 초기 설계를 진행했습니다.
사용자 기능 선택 -> 미션 -> 페어 -> 크루
연관관계를 가지고, 이런 흐름으로 데이터가 이동하여 Application이 돌아간다고 판단했고,
저는 그래서 크루 -> 페어 -> 미션 -> 사용자 기능 선택 순으로 설계와 구현을 했습니다.
2. TDD를 기반으로 하여 작은 기능별로 구현을 시작
사실 TDD를 3주간 연습했음에도, 이번에 5시간만에 과연 제가 TDD를 적용해서 완성할 수 있을까 의문이 들었습니다.
(결국에는 못했지만..)
그래도 저는 이번 프리코스를 어떻게든 완성해서 평가받자 가 아니라
3주간 연습한 부분을 적용해서 구현해보자 라고 생각돼서
무모한 도전이였지만 TDD를 적용했습니다.
따라서 현재부터 각 기능을 구현하고 커밋한 순서대로
제가 고민했던 점, 부족했던 점을 이야기 해보겠습니다.
- 크루원 생성
사실 이때 좀 많이 방황을 했습니다.
요구사항에는
파일을 로드하여 과제를 수행하라고 했습니다.
하지만 제가 정적인 파일 I/O와 관련돼서 java를 구현해본게 처음 배울때 말고는 없었고,
그것마저 gradle 프로젝트 위에서가 아니라 실제 pc의 정적주소를 넣어서 수행했었습니다.
제가 여기서 고민한 사항은
- 정적으로 불러오는 파일의 path가 프로젝트를 루트로 두고 해야지 다른 pc에서도 올바르게 동작할텐데
- File을 읽어오고 구분자 처리를 어떻게 진행하지?
위 두 사항이였습니다.
하지만 해당 미션을 진행하는 중에는 시간이 촉박하다 판단하여,
로드하는 형식이 아니라 직접 하드 타이핑하여 해야겠다고 생각했습니다.
그런데 결국 위에서 걱정한 부분은 결국 I/O와 관련된 부분이였고,
따라서 크루를 생성하는 기능 자체에는 영향을 미치지 않는다는다고 판단되어
이름과 코스를 넣어주면 크루가 생성되는 기능 구현에는 어려움이 없었습니다.
(파일을 불러오든, 하드코딩을 하든 결국 이름만 주어지면 크루가 생성되어지는 방식입니다)
( File I/O 해결 방법은 다음 게시글에서 작성하겠습니다.)
- 페어 생성
Pair 는 크루 두명이 준비가 되어지면 생성이 되게 구현을 했습니다.
구현 자체에는 어려움이 없었고,
후에 3명이 된 경우에 어떻게 페어를 생성할지에 대해 과제를 남긴체 다음 구현으로 넘어갔습니다.
- 랜덤으로 페어 생성
위에서 File I/O 와 연관된 부분이 있다면 해당 부분이 되겠습니다.
이유는 Pair를 이름 리스트로 부터 랜덤으로 추출하기 위해서는
이름 리스트 가 필요하기 때문입니다.
하지만 저는 File I/O 부분을 넘어갔기 때문에,
우선 구현을 위해서 하드하게 작성한 이름리스트를 input으로 넣어주었습니다.
여기서 중요한 점은,
File I/O를 후에 구현한다면 List<String> 형식으로 추출만 한다면,
갈아 끼어만 주면 그대로 동작한다는 점 입니다.
(이렇게 기능별로, 역할별로 종속, 의존 관계를 줄여 나가는데 신경을 썼기에,
일부 구현이 어려운 부분을 임시로 대체하면서 구현이 가능했습니다.)
- 미션 생성
미션을 생성하고, 미션 내에서 페어를 생성하며, 최종적으로 Controller에서 미션이 생성되도록
구현하는 과정입니다.
약 30분정도 투자했었네요.. 지금 보니까
미션의 생성은 이전 크루나 페어가 생성되듯이 정보만 입력되면 생성이 되도록 구현하였으며,
미션의 페어 생성 역시 기존에 페어를 생성하는 기능이 구현되었기 때문에,
이름 리스트만 주어지면 손쉽게 생성할 수 있었습니다.
Controller 에서는 생성된 Mission들을 MissionSet이라는 일급 컬랙션을 활용하여 Pair Application 이 수행이 됩니다.
(MissionSet은 mission 들을 Set 자료구조에 담아 보관합니다.)
위에서 구현된 기능들을 합치면 손쉽게 missionSet에 mission을 넣을 수 있는 구현입니다.
- 중복되는 페어 확인
다른 분들의 후기 블로그도 여럿봤고,
PR도 봤을때 가장 많은 시간이 투자된 부분이 이 기능 구현이었고,
저도 마찬가지 였습니다.
(거의 한 시간이 투자되었습니다.)
MatchingController에는 MissionSet으로 Mission들이 관리되어지고있어서,
저는 Mission들이 각자 가지고 있는 Level 과 Course를 바탕으로 Mission을 구분하고,
같은 Level과 Course일때 중복되는 Pair가 존재하는 로직을 구성했습니다.
Controller에서 MissionSet에 메시지를 보내 결과를 기다립니다.
missions 라는 Set자료구조에서 mission들을 각각 뒤져가면서
주어진 미션과 중복된 pair를 가진 mission이 있는지 확인하는 메시지를 각 mission에 보냅니다.
각 Mission들은 주어진 Mission (target이 되는 미션) 과 같은 Level인지 판단하며,
각 Mission들이 가진 PairSet에서 중복되는 것이 있는지 확인하는 메시지를 전송합니다.
이런식으로 Layering을 거쳐 모든 과정이 진행이됩니다.
3. 구현된 기능들을 바탕으로 console I/O 구현
이 부분이 제가 주어진 테스트가 통과가 안되는 부분이였습니다.
왜냐하면 우선 while 을 돌리면서 사용자로 부터 입력을 지속적으로 받아야했고,
예외처리를 구현하면서 I/O를 진행해야했기 때문입니다.
기능에 대한 구현은 완성된 저는,
이 부분에서 시간이 부족해서 완성을 못한점이
초반에 이야기하는 30분의 차이입니다.
4. 부족하고 채워가야할 점
많은 분들의 PR을 보니까 정말 깔끔하고 구현도 잘된 코드를 여럿 봤습니다.
그에 비해 저는 테스트를 통과도 못하고 시간 배분이 잘못된 계획을 짰다고 생각도 들긴합니다.
따라서 저는 branch를 현재 새로 파서 이어서 미션을 수행하고 완성해볼 예정입니다.
- File I/O 처리
- console I/O 처리
계속해서 지켜봐주시면 감사하겠습니다 ㅎㅎ
(다음 게시글에서 정리하도록 하겠습니다)
5. 결론
최종 테스트에 무리하게 TDD를 적용한것에 대해서 저는 후회는 없습니다.
정말 지난 3주간 제가 성장했다고 느낀점이
"기능을 구현하기 위해 이걸 만든 후에 저걸 만들고 (top down)" 가 아니라,
"기능을 구현하기 위해 이것이 필요하니까 먼저 이거부터 만들고 (bottom up)" 라는 방식으로
코딩을 하는 연습이 되었습니다.
이렇게 하면 가장 큰 장점이
위 프로젝트에서도 여럿 내포 되었지만,
기능 별로 구분이되며 서로간의 의존이 낮아지고, 디버깅과 유지보수에 강하다는 것 입니다.
머 쨋든
정말 후회없이 많은 것을 배우고 느끼고 깨달은 최종미션이었습니다.
부족한 점이 있다면
언제든 지적 부탁드리겠습니다.
긴 글 읽어주셔서 감사합니다.
"daehwan2yo" contact
software, soongsil univ < now
udsward@gmail.com < email
https://github.com/daehwan2yo< git
daehwan2yo - Overview
daehwan2yo has 19 repositories available. Follow their code on GitHub.
github.com