워밍업 클럽 4기 백엔드 - 2주차 발자국
강의 내용
섹션 6에서는 코드를 조금 더 보기 좋게 다듬는 방법을 배웠다. 이전까지는 추상화에 초점을 맞추어 객체지향적인 코드를 작성하는 방법을 배웠다면, 섹션 6에서는 코드를 읽을 때 느낄 수 있는 불편함을 줄이기 위한 방법을 배웠다고 요약할 수 있을 것 같다.
주석에는 의사결정 히스토리 등 코드로는 도저히 녹여낼 수 없는 정보만 작성
자주 변하는 정보는 주석에 작성하지 않기
변수나 메소드의 경우 자연스러운 흐름으로 코드를 읽을 수 있도록 사용되는 순서나 중요한 순서에 따라 배치
패키지 구조 또한 의미를 담을 수 있는 요소이며, 특히 변경이 어려운 부분이므로 처음부터 숙고하여 설계
가장 좋은 코드는 상황에 맞는 코드, 클린 코드는 은탄환이 아니다.
그러나 비즈니스 환경에서 적절한 수준으로 클린 코드 원칙을 활용하려면, 한계까지 사용할 줄 알아야 한다.
이를 위해 때로는 극단적인 시도를 해보는 경험도 필요하다.
테스트의 필요성
새로운 기능 개발을 위해 기존의 코드를 변경할 일이 생긴다면, 코드 수정 후 기존에 테스트 했던 부분을 다시 테스트해야 하는 문제 발생
테스트 코드가 없다면 사람이 모두 테스트 -> 사람이 직접 테스트하기 때문에 발생 가능한 위험 동반
테스트 코드는 코드에 대한 올바른 검증이 이뤄질 수 있도록 잘 짜야 한다.
JUnit 5, AssertJ
테스트 케이스 세분화 -> 검증하고자 하는 로직의 해피 케이스 뿐 아니라 예외 케이스도 검증 e.g. 경계값 테스트
테스트 하기 어려운 영역은 테스트 영역 외부로 분리 -> 관측 시마다 다른 값에 의존하는 코드, 외부 세계에 영향을 주는 코드 등
TDD: 테스트 작성 후 기능 구현, Red-Green-Refactor
테스트는 프로덕션의 기능을 설명하는 문서이며, 팀 전체의 자산 -> 상세한 DisplayName 등 문서로서의 역할을 수잘 행할 수 있도록 작성
회고
Readable Code 강의를 들으면서 도메인 객체가 핵심 비즈니스 로직을 작성하는 방식을 처음 접했다. 강의 내용을 바탕으로 검색을 해보니, 이러한 코드를 Rich Domain Model이라고 한다는 사실을 알게 되었다. 국비학원에서 배웠고, 지금 다니는 회사에서 개발하는 방식, 서비스 클래스의 메소드에 절차적으로 로직을 쭉 작성하는 방식은 Transaction Script, Anemic Domain Model이라고 부른다고 한다. 올해 초에 읽었던 '함께 자라기'라는 책에서 비슷한 Rich Domain Model이라는 표현을 봤던 것 같은데, 사족에 가까운 문장이라 나중에 찾아봐야지 하고 넘겼던 것으로 기억한다. 진작에 좀 찾아볼 걸 그랬다는 생각에 약간 후회스러웠다. 그랬다면 좀 더 일찍 책임을 보고 인식하는 능력을 기를 기회가 있었을텐데.. 새삼 너무 준비가 안 된 상태로 섣부르게 취업한 게 아닌가 싶은 생각도 들었다.
이번주는 개인적으로 조금 아쉬운 느낌이 강하다. 강의도, 미션도 정말 좋았지만 회사 일로 야근을 하게 되어 스스로 고민하고 연습할 시간이 너무 부족했다. 다음주부터는 비슷한 일이 생기더라도 좀 더 시간을 효율적으로 활용해 스스로 아쉬움이 남지 않도록 하고 싶다. 스스로 칭찬하고 싶은 점은 용기를 내서 코드 리뷰를 신청한 것이다. 스스로 생각하기에도 부족함이 많은 코드라서 민망하기도 하고, 다른 분들의 시간을 뺏는 게 아닌가 싶어 미안한 마음이 없지 않았다. 단순히 리팩토링을 잘했다 못했다를 떠나서, 고민이 부족했다는 생각이 들어서다. 그럼에도 불구하고 코드 리뷰라는 것을 경험해보고 싶은 마음에 용기내어 신청을 했고, 결과적으로 정말 잘한 일이라는 생각이 들었다.
미션
Day 7
Day 7 미션은 강의에서 배운 내용을 바탕으로 주어진 코드를 리팩토링하는 것이었다. 처음 손을 대려고 하니 뭐부터 해야 할지 감이 오지 않아 막막했다. 우선은 서로 if-else 분기문에서 중복된 코드를 뽑아서 if문 밖으로 꺼내는 것부터 시작했다. 손을 대기 시작하니 코드 중복을 줄이고 메소드를 추출하는 부분까지는 그래도 큰 어려움 없이 할 수 있었다. 이 과정에서 가장 어려웠던 것은 메소드 이름을 짓는 것이었다. 메소드를 추출한 뒤에는 객체의 책임을 어떻게 나누는 것이 합당할지 고민하면서 새로운 객체를 정의하고, 인터페이스로 추상화를 시도하고, 메소드를 다른 객체로 옮기면서 이런 저런 시도를 해봤다. 나에게는 역시 이 과정이 제일 어려웠다. 단순히 DTO에 필드를 정의하고 getter, setter를 모두 만들어 놓고 시작하던 기존의 방식을 버리고 객체가 스스로 로직을 처리하도록 하는데 집중했다.
리팩토링 과정에서 놓친 부분이 많이 있었다. PassOrder 개념을 도출해 새롭게 정의한 객체가 가진 Nullable 필드에 대한 고민, 일급 컬렉션 객체의 메소드 이름을 너무 기존 로직에 특화하여 짓는 등이다. 한 번 직접 리팩토링을 해본 뒤 강의를 듣고, 내 코드에 대한 피드백까지 받아보니 확실히 많이 도움된 것 같다. 앞으로 더 깊이 고민하고, 다양한 시도를 해보면서 객체지향적인 사고와 감각을 많이 기르고 싶다.
댓글을 작성해보세요.