
발자국 2주차: 읽기 좋은 코드 == 쓰기 좋은 코드
읽기 좋은 코드, 쓰기 좋은 코드
이번 주의 발자국 회고. Readable 코드에 대한 이야기가 마무리되는 주간이다.
이번에는 강의 듣기와 함께 미션을 토대로, 내가 실제로 코드를 구현해 보는 시간을 가져갈 수 있었는데, 중간 점검 타임에서 과제에 대해서 조금 더 짚어주시면서 내 코드를 돌이켜보는 기회를 얻을 수 있었다.
사실 Spring과 JPA를 사용하는 평소 개발 방식은 많은 부분 "이미 모듈화된" 것들을 사용하는 경우가 많다.
특히 어노테이션을 쓴다든지 하는 케이스의 런타임 객체 관리 위임과 같은 상황에서 우리는 책임의 분리를 덜 고려하고도 편안한 개발을 할 수 있다.
단적인 예만 해도 Dispatcher Servelt은 우리의 xml 등록을 대리해 주고, 스프링은 Bean을 대신 관리해서 DL을 말려준다. (ㅋㅋ)
이런 것들이 감춰져 있기 때문에 우리는 서비스 로직을 조금 더 경량화할 수 있다.
그런데 기껏 스프링이 열심히 도와준 걸 망치면 안 되지 않을까?
필드를 얼마나 넣을 것인지, 이 객체의 책임 = 변경 가능 요소는 몇 개인지와 같은 것들을 잘 고려해 보면서 리팩토링 과제를 진행해 보았다.
그리고 이러한 미션을 점검하는 중간 회고.
중간 점검 회고
우선 중간 점검에서 했던 질문 시간이 꽤 재미있었던 기억이 난다.
멘토님의 커피 사랑 ㅋㅋㅋ 을 알 수 있는 좋은 기회이기도 했고... 나중에 게이샤 커피 꼭 먹어 보겠습니다.
공통 리뷰와 함께 개별 신청자에 대한 리뷰를 진행하는 2시간 가까이의 시간이었다.
목이 아프셨다고 했는데, 다음날 출근해서 말 한마디 못하시는 건 아니었는지 염려가 된다.
주요 내용은 장표를 공유해 주셨는데, 내가 이 내용 외에도 다른 분들 코드 피드백을 들으면서 인상깊었던 부분들을 정리해 보았다.
사물함 사용 가능 여부 등의 ENUM 처리: 추천
컬렉션을 가공하는 로직이 생기면 일급 컬렉션을 고민해 볼 것
Get / Set이 아닌 연상되는 단어 선택한 점이 좋음
if-else보다 if-early return을 추천
Mutable 컬렉션보다는 한번에 Immutable 컬렉션을 만들 것
많은 클래스에서 사용한다 == 하나의 객체에 책임이 과도하게 몰려 있는 것은 아닌가? : 객체 분리의 신호탄
IO 로직이 변경되어도 우리의 도메인 로직은 순수하게 보존되어야 함
이런 이야기가 있으면 나는 이중에서 나에게 도움이 가장 많이 된 것들을 꼽고는 하는데, 이번 글에서는 꼽을 수가 없다.
정말 모든 관점이 큰 도움이 되었던 것 같다.
강의 회고
하고 싶은 것
현재 진행 중인 실무 프로젝트에 배운 내용을 점진적으로 적용해보기
"능동적 읽기" 방식으로 오픈소스 코드를 분석하며 좋은 패턴 학습하기 (TOBE -
진짜?)
이번 주간으로 <Readable Code: 읽기 좋은 코드를 작성하는 사고법>에 대한 강의가 끝이 났다.
사실 강의는... 진짜 솔직하게 말하면 아는 내용이 많다고 생각하면서 봤었는데.
실제로 코드를 리팩토링 하는 과정에서 그 생각이 제법 오만이라는 생각을 계속해서 하게 되었다.
역시 이론과 실제는 다르고, 이상과 활용은 천지차이다.
이번 강의와 미션을 통해 클린코드와 객체 지향 설계의 중요성을 실제로 체감할 수 있었다.
특히 회사에서 가장 의식적으로, 많이 노력하려고 했던 것. "코드는 작성하는 시간보다 읽는 시간이 훨씬 많다"는 강의 내용을 들었던 것을 염두에 두고 코드를 작성하고자 노력을 많이 했다.
사실 가장 어려운 부분은 적절한 추상화 레벨을 결정하는 것인 것 같다.
어떻게 인터페이스를 나누고 책임을 나눠야 하는지... 너무 세부적으로 메서드를 분리하면 오히려 코드 흐름이 파악하기 어려워질 것이고, 너무 크게 묶으면 단일 책임 원칙을 위반하게 될 것이다.
이러한 관점에서 하나 인상깊었던 것이 떠올랐는데, 멘토님이 예로 들어 주셨던 조건 분기문에 대한 코드 분리가 그것이다.
예를 들면, if(type.equals("blahblah"))
일 때 if(isEditable())
으로 코드를 바꾸고, isEditable에 대한 함수를 하나 더 빼는 형식이다.
이 조건일 때 이런 행위를 한다는 분기를 하나의 함수로 표현하는 것.
사실 객체의 상태를 객체 안에서만 넣는 바람에 밖에서 나눠 볼 생각을 못했던 것 같은데....
결국 코드는 1줄이나 2줄인 게 중요한 게 아니라, 들이는 공수를 대비해서, 로직을 망가뜨리지 않는 범위에서의 효율을 추구하는 일이라는 것.
이 균형을 맞추는 것이 클린코드의 핵심이라는 것을 조금 더 깨달았다.
읽기 좋은 코드 == (나중에) 쓰기 좋은 코드
따라서 이번에 정립하게 된 것.
읽기 좋은 코드는 동시에 쓰기 좋은 코드이다.
사실 읽기 좋은 코드를 짜다 보면 옆에서 "왜 굳이?" 라는 표현을 들을 수 있다는 생각이 든다.
그런데 나는 읽기 좋은 코드가 오히려 쓰기 좋은 코드라고 생각한다.
보다 정확하게 말하면, "내가 나중에 쓰기 좋은 코드"라고 생각한다.
단적인 예로 일급 컬렉션. 일급 컬렉션은 개발자의 책임을 줄여 로직이 망가질 확률을 최소화하는 일이다.
만약 특정 변수를 주입해서 판단하는 로직이 있다면, 그 로직은 변수에 종속적이며, 추후 개발자의 판단에 종속된다.
우리는 판단을 최소화함으로써 행동을 제약하고, 제약한 행동은 나중에 내가 쓰기 좋은 코드를 낳는다.
행복한 선순환이다.
하지만.
"오만"을 참는 법
처음부터 완벽한 코드는 오만이다
이번 중간점검 때 멘토님이 하신 말씀이 있다.
우리는 개발자고, 회사에 고용되어 일하는 것은 프로라는 뜻이다.
그리고 프로가 가장 중요하게 여겨야 할 것은 시간 관리다.
즉, 코드 퀄리티를 우선하다 주객이 전도되는 상황을 일으키는 것은 옳지 않다는 이야기다.
이러한 코드에 대해서는 추후 반영 시 가능하다면 리팩토링을 하는 식으로 점진적 개선을 할 수 있어야 한다.
이상적인 클린코드를 추구하다가 실용성을 간과한 경우를 자주 접하게 된다.
가령 진짜 if문 하나로 해결되는 문제를 객체로 분리했을 때 생기는 문제라든지.... 최신 트렌드의 개발에서 개념을 이해하는 것이 아니라 해당 개념을 적용하고만 싶어서 처리하는 케이스가 그런 상황을 발생시키는 것이 아닐까.
아주 자주 나오는 격언. "은탄환은 없다."
멘토님을 통해서 이번 기회에 또 한 번 상기할 수 있었다.
완벽한 동그라미의 바퀴를 만들고자 하지 말고, 굴러가게 만드는 것이 1번이다. 그 다음 세공하면 된다.
상황에 맞는 적절한 수준의 클린코드 적용을, 리팩토링을 위한 리팩토링을 계속해서 경계해야 한다고 또 한 번 다짐.
댓글을 작성해보세요.