2주차는 간단하게 나열 형식으로 이번에 지켰던 것과 다음 3주차때 추가적으로 지켜야 할 것들을 정리해 보려고 한다.
이번주차의 문제는 자동차 경주 미션이었다.(문제 및 코드는 아래에)
새롭게 도전한 요구사항
- 일급컬렉션을 Circuit 클래스에서 적용
> 저번에도 지켰다고 생각했는 데 잘못 지켰다고 피드백을 받았다. 이번에는 잘 지켜 본것 같다 - 불변 객체 만들기 + 정적 팩토리 메서드 만들기
> 저번 리뷰때 DTO도 불변 객체로 만들 수 있다고 했다. 그래서 이번 자동차게임에서 RacingCar에 불변객체를 만들어보면서 같이 나오는 주제인 정적 팩터리 메서드도 만들어봤다. 확실히 불변 객체는 변하지 않음을 보장할 수 있으니 다른 클래스에서 변경될수도 있다는 복잡한 고민을 줄일 수 있었고 동시성 문제도 생각할 필요가 없어졌다. 참고자료는 밑에 적겠다. - 커밋 컨밴션 지키기 + 영어로 작성
> 굳이(?)라는 생각이 들지만 회사에서는 커밋메세지를 영어로 작성하며 외국인과도 협업을 진행하기 위함이라고 한다. - JUnit5와 AssertJ 차이점 이해
> JUnit5만을 이용했었는 데 AssertJ가 훨씬 가독성도 좋고 기능이 더 다양하다는 걸 알게됐다. 앞으로도 AssertJ를 적극 활용해야겠다. - String.matches는 성능이 안좋다
> Pattern 객체를 생성하는 것은 비용이 크다. 캐싱해두고 재사용해야 할 필요가 있다. 참고자료는 밑에 적어두었다.
현 시점에서 드는 TDD에 대한 생각
테스트 코드를 먼저 작성함으로써 얻는 이점들에 대해 말하고 싶다.
첫 번째 장점은 불필요한 로직 작성을 방지한다는 것이다. 실제로 리뷰를 받아본 후에야 더욱 정확한 판단이 가능할 것이지만, 1주차 때 비교하면 내가 짠 코드가 훨씬 읽기 쉬워진 것 같다. 그때는 코드를 한 곳에 모아 작성하고, 그 후 클래스를 분리하는 방식으로 진행했다. MVC 패턴을 적용하면서 최대한 클래스를 분리하려고 노력했다. 하지만 이번 2주차에는 TDD 방식으로 진행하니 코드가 더 개선된 모습을 보였다.
두 번째 장점은 특정 로직에만 집중할 수 있게 된다는 것이다. 지난 주에는 자꾸 전체적인 그림을 먼저 그리려고 했다. 그로 인해 여러 메서드와 객체 지향적인 코드 작성에 대해 고민하는 데 많은 시간을 소요했다. 그러나 이번에는 이런 부담이 없어졌다. 하나의 요구사항에만 집중하면서 테스트 코드를 작성하다 보니, 어느새 객체 지향적인 코드가 완성되었다.
세 번째 장점은 테스트 코드를 작성하기 어려운 로직을 만들지 않게 된다는 점이다. 1주차에는 구현을 먼저 하고 테스트 코드를 작성하다 보니 테스트하기 어려운 로직이 생겼다. 어디선가 읽었던 글에는 '테스트 코드를 작성하기 어려운 로직은 바로 지워야 한다'는 말이 있었다. 하지만 이미 작성한 로직을 모두 지우고 다시 작성하는 것은 큰 부담이었다. 테스트를 먼저 작성하니 이런 부담감이 사라졌다. 어려워보이면 더 쉬운 로직으로 변경해야겠다는 생각이 들고, 실제로 그렇게 구현하면 결과적으로 객체 지향적인 코드로 변화하는 경험을 했다. 즉, 테스트 코드를 작성하기 위한 노력이 자연스럽게 객체 지향적인 코드를 만들어냈다는 것이다.
이렇게 많은 장점 때문에 다음 주차에도 TDD를 연습해볼 계획이다. 그러나 테스트 코드에 어떤 요구사항을 넣을지 결정하는 고민이 메서드 분리와 비슷한 수준으로 어렵다는 단점도 느꼈다. 이것은 클린 코드, 즉 객체 지향적인 코드를 작성하는것을 구현부터 같이 고민해야 한다는 것을 의미한다. 이는 구현과 리팩토링이 동시에 이루어지기 때문에 시간이 많이 소요됐다. 만약 한정된 시간 내에 구현을 완료해야 하는 요구사항이 있다면, TDD보다는 바로 구현부터 시작해야 할 것 같다.
2주차 피드백 (공통 피드백 및 다른 코드 리뷰들 보고 개선해야 할 점)
- README.md를 상세히 작성한다.
> 미션 저장소의 README.md는 소스코드에 앞서 해당 프로젝트가 어떠한 프로젝트인지 마크다운으로 작성하여 소개하는 문서이다. 해당 프로젝트가 어떠한 프로젝트이며, 어떤 기능을 담고 있는지 기술하기 위해서 마크다운 문법을 검색해서 학습해 보고 적용해 본다. - 기능 목록을 재검토한다
> 기능 목록을 클래스 설계와 구현, 함수(메서드) 설계와 구현과 같이 너무 상세하게 작성하지 않는다. 클래스 이름, 함수(메서드) 시그니처와 반환값은 언제든지 변경될 수 있기 때문이다. 너무 세세한 부분까지 정리하기보다 구현해야 할 기능 목록을 정리하는 데 집중한다. 정상적인 경우도 중요하지만, 예외적인 상황도 기능 목록에 정리한다. 특히 예외 상황은 시작 단계에서 모두 찾기 힘들기 때문에 기능을 구현하면서 계속해서 추가해 나간다. - 구현 순서는 상수, 멤버변수, 생성자, 메서드 순으로 작성한다
- 테스트는 작은단위의 테스트부터 시작한다
- AssertJ의 활용법을 잘 써보자 (자료는 밑에 정리해두었다)
- 유효성 검사를 생성자에서 해보자
> 객체 생성 시점에 전달한 이름을 유효성 검사하는 방식이다. 즉 객체의 유효성 검사는 해당 객체에서 진행, 도메인(모델) 이라고 볼수 있는 로직은 View에서 검증한다. - 정적팩토리메서드 아니여도 인자에 전달없이 초기화하는 방법이 있다
- 원시타입 vs Wrapper 객체
> Wrapper 객체들은 16바이트나 된다. 굳이 안에 기능을 쓰지 않을거면 지양하는 게 좋을 것 같다 - 유효성 검사는 메서드명을 validate를 앞에 붙이고 반환타입을 void로 하자
우테코에서 요구하는 3주차 학습 방식
- 클래스(객체)를 분리하는 연습
- 도메인 로직에 대한 단위 테스트를 작성하는 연습
- 과제를 제출할 때 이번주 차 목표를 중심으로 학습하면서 느낀점을 소감문으로 작성하기 (학습한 과정을 잘 드러내기)
자료 모음집
StringBuilder 또는 StringBuffer보다 좋은 StringJoiner
정적 팩토리 메서드를 왜 사용하는가? 어떤 상황에 사용하는게 좋을까?
'공부방 > 프리코스' 카테고리의 다른 글
우테코 프리코스 최종테스트 후기 (1) | 2023.12.20 |
---|---|
우테코 프리코스 3주차 후기 + 피드백 정리 (0) | 2023.11.14 |
우테코 프리코스 1주차 후기 (0) | 2023.10.25 |