지난 1주차 미션에 이어 2주차 미션도 열심히 했다..!
-> 1주차 미션 회고
-> 우테코 프리코스 2주차 java-baseball
-> 필자의 결과물
-> 새로 배운 내용 - JUnit5
-> 새로 배운 내용 - AssertJ
1주차 미션 때는 Java 언어에 익숙해지는 것이 나만의 목표였고, 2주차 미션은 함수 분리와 테스트 코드 작성에 익숙해 지는 것이 미션의 의도이자 나의 목표였다.
2주차 미션을 시작하기 전, 코수타(코치님과의 수다 타임..? 맞나..?) 시간에 코치님께서 TDD에 대해 언급하신 것을 보고 테스트 위주 개발 방식에 대해 알아봤다.
장점이 많고 중요한 개발 방식인 것을 확인한 후, 2주차 미션에서 직접 실천해보고자 했다.
그리고 함수 분리에 대해서도 알아보았고, 이와 더불어 가독성에 대해서도 이런 저런 자료들을 찾아보며 2주차 미션에서 실천해 볼 개발 방식을 정리해 보았다.
- 프로그래밍 요구 사항을 준수하며 개발한다.
- TDD 방식에 맞추어 개발을 진행한다.
(1) 테스트 코드 먼저 작성 및 실패
(2) 테스트 통과할 만큼만 구현
(3) 리팩토링- 개발을 진행하며 TDD의 장단점에 대해 생각해 본다.
- 각 기능은 본인의 역할에만 충실한다.
- 다른 클래스 혹은 메소드에 영향을 주지 않도록 한다.
- 다른 테스트 코드에 영향을 주지 않도록 한다. (수정 발생 시, 수정한 메소드 외 다른 테스트들은 문제가 없도록 개발)
- 메소드 분리 과정에서 또 다른 클래스로 분리가 가능한지 고민해 본다.
- 메소드 매개변수 개수를 최소화 한다.
이렇게 나만의 개발 방식을 한 번 만들어 보았고, 최대한 지키고자 했다.
그리고 개발하면서도 네이밍이나 깃 커밋 메세지 컨벤션 등 이런 저런게 떠올랐고, 해당 내용들은 회고에 적었다.
회고 내용이 좀 길어서 아래와 같이 정리해 보았다.
❗️회고 내용은 필자가 개발하면서 느꼈던 지극히 매우매우 개인적이고 주관적인 생각들을 끄적인 것들이며, 소감문 혹은 경험담에 가까우니 지식과 경험이 부족해 잘못된 내용이 다수 존재할 수 있다.❗️
(반박 시 내 말이 틀림ㅠ 피드백 부탁드립니다.)
조금 억지스러울 수 있지만.. 테스트 코드를 먼저 작성할 때 빨간줄이 계속 뜨는게 조금 거슬렸다.
구현되지 않은 기능에 대한 테스트 코드를 작성하려니 모호한 면이 있었다.
내가 지금 작성하고 있는 테스트 코드가 내 의도대로 동작될지 의심되었다.
(JUnit 5와 AssertJ를 처음 활용해 봐서 더 그랬던 것 같다.)
구현되지 않은 허구에 대해 테스트하는 과정 자체에서 모호한 면이 많았다.
하지만 이러한 단점들은 테스트 코드 작성을 더 많이 해보며 지식을 쌓고, 기능 목록을 좀 더 자세하게 설정하면 보완될 수 있을 것이라 생각한다.
매개변수를 없애려는 과정에서 로직이 수정되는 경우도 있었지만(가장 좋은 방법이라 생각한다.), 멤버 변수가 늘어나기도 했다. 이에 대해 조금 염려가 되기도 했다.
멤버 변수가 늘어나는 것은 클래스를 분리하는 것으로 이어질 수 있어 오히려 좋은건가? 싶다가도 마냥 좋은 것은 아닌 것 같다는 생각이 들었다. 결국 상황에 맞추어 최선의 방안을 선택하는 것이 가장 중요한 것 같다.
가독성을 위해 이름을 설정할 때 다양한 방법이 있겠지만 이번에는 특정 방식에 초점을 맞추어보았다.
-> 로직에 초점을 맞춘 것이 아닌, 기능에 초점을 맞추어 이름을 결정한다.
이는 이번에 AssertJ에 대해 알아보다가 생각하게 되었다.
AssertJ의 메소드는 하나의 문장을 만들듯 지어진다.
assertThat(string)
.isNotNull()
.isNotEmpty()
.startsWith("Woowa")
.endsWith("Course")
.contains("Tech")
.isEqualTo("Woowa Tech Course")
.isNotEqualTo("abcd");
->Assert that 'string' is not null / is not empty / ...
assertThatThrownBy(() -> {
GameExceptionHandler.handleNotNumberException(alphabetInput);
}).isInstanceOf(IllegalArgumentException.class);
-> Assert that thrown by 'Method' is instance of 'illegal argument exception'
결국 코드의 가독성에 대해 중요하게 생각해야 하는 것 중 하나가 코드를 작성한 개발자의 의도를 파악하는 것인데, 이를 이름으로 표현할 때 "로직을 담는 것"과 "기능을 담는 것"에 대해 고민한 적이 많았다.
이 전까지는 '로직을 담는 것'에 좀 더 초점을 맞추어 왔었는데, 본 미션에서는 "기능을 담는 것"에 한번 초점을 맞추어 보았다.
직접 실천해 본 결과, 다음과 같은 결론을 얻을 수 있었다.
(1) 상위 메소드(타 메소드를 호출하며 기능을 이루는 메소드)는 "기능을 담는 것"이 더 도움될 수 있다.
(2) 하위 메소드(타 메소드에 의해 호출되는 메소드)는 주로 로직을 담고 있으므로, "로직을 담는 것"이 더 도움될 수 있다.
물론 구현해야 하는 기능에 따라 달라지고, 사람마다 가독성을 받아들이는 것에 차이는 있겠지만, 상기 내용과 같이 이름을 설정하면 좀 더 도움이 될 수 있지 않을까 생각해 본다.
본 미션에서 커밋 메세지 컨벤션을 고려하며 커밋 메세지를 작성했는데, 'scope' 내용에 대해 고민이 있었다.
기능의 범주를 넣는거라 그래도 자세할 수록 좋을 것 같아 클래스 단위를 입력하였다.
하지만 클래스 단위로 입력해보니, 커밋 메세지 내용이 중복되기도 하고, subject line(첫번째 줄)이 너무 길어졌다ㅠ
Ex)
feat(GameOperator):GREEN 게임 운영 기능 구현
사용자 입력 및 게임 안내문, 결과 출력 기능 구현
GameOperator.java 구현
...
따라서 좀 더 큰 범주인 패키지 단위로 입력하는 것이 더 좋을 것 같다는 생각을 하게 되었다. (자세한 내용은 body나 footer를 열어보면 되니까!)
Ex)
feat(domain): ...
test(exception): ...
만약 이 미션이 팀 단위 미션이었다면 본 방식을 의견으로 제시할 것 같다..!
다음 주차부터 적용해 보면 좋을 것 같다.