Search

리팩터링 2판 스터디 - 5

리팩터링 2판을 회사 팀 내 스터디로써 진행한다. 스터디에선 따로 책 내용을 정리를 하지 않고 주마다 정해진 분량까지 읽고 감상을 나눈다. 여기선 개인적으로 매 분량에 대한 정리와 짧은 감상을 올린다.

03 코드에서 나는 악취

악취 → 리팩터링은 언제 시작할 지 시점을 알려줌
언제 그만둘지는 더 어려운 문제
아래 하위 챕터에선 악취, 어떤게 리팩터링 해야할 안 좋은 코드인지, 에 집중하여 정리했다. 특히 아직 읽지 않은 리팩터링 기법을 사용한 설명은 배제했다 (아마 이 부분에 “경험”이 중요하다고 한걸 보아 어떤 수정을 할지 알아야 보일거 같기도 하다).

3.1 기이한 이름

“이름만 잘 지어도 나중에 문맥을 파악하느라 헤매는 시간을 크게 절약할 수 있다”
잘못 지으면 남이나 나나 개고생시킨다
이름이 떠오르지 않는다 → 설계에 문제가 있는 것일 수도

3.2 중복 코드

반복을 하나로 모으는 것

3.3 긴 함수

짧은 함수로 잘 구성된 코드는 계속하여 위임한다; 간접 호출
코드의 위치가 나뉘어 지는 점 → lsp의 선언과 호출(참조)를 넘어다니는 기능을 활용하자
함수의 긴 주석
의도(목적): 함수 이름 짓기로 해결; 무엇을 하는 함순지 이름으로 설명할 수 있어야 함
동작(구현): 길면 쪼갤 수 있어야 하고 그 동작을 계속 위임하는 함수들이 많아야 한다(작아질테니)

3.4 긴 매개변수 목록

객체나 클래스로 만들어 통째로 넘기는 것을 생각해보자

3.5 전역 데이터

가장 지독한 악취
변경 시 이력을 추적할 수 있게 함수로 감싸고 호출로 참조한다
그 함수를 모듈이나 클래스에 넣어 접근 범위를 제한한다

3.6 가변 데이터

함수형 프로그래밍을 이젠 적절히 섞어 쓸 수 있지 않나
(리팩터링 기법이 이름만 보곤 아직 잘 이해가 안감)

3.7 뒤엉킨 변경

변경을 할 때(e.g. 기능 추가) 딱 한군데만 수정할 수 없는 상황
SRP가 지켜지지 않았을 때, 단일 모듈 여러 이유로 여러 방식으로 변경될 때
SRP: 단일 모듈은 변경의 이유가 오직 하나여야만 한다.
클린 아키텍처 - 단일 모듈은 오직 하나의 액터에 대해서만 책임져야 한다

3.8 산탄총 수술

변경을 할 때, 여러 클래스에 자잘한 수정을 많이 할 때 뒤엉킨 변경과 반대
변경되는 부분을 한 모듈로 묶자
함수, 클래스를 작게 쪼개는 것만큼 필요에 따라 뭉칠줄도 알아야 한다

3.9 기능 편애

모듈 바깥, 다른 모듈끼리의 상호작용을 최소화해야 한다
다른 모듈과 너무 많이 소통하는 함수는 그쪽 모듈로 보내준다
반대되는 디자인 패턴; 전략 패턴, 방문자 패턴
“함께 변경할 대상을 한데 모으는 것”
오버라이드해야 할 동작 코드를 각각 클래스로 격리하여 수정이 쉬워짐(간접 호출은 늘어남)

3.10 데이터 뭉치

몰려다니는 데이터를 뭉쳐주자
클래스(객체)로 뭉치기
메서드 시그니처를 매개변수 객체로 뭉치기 또는 통째로 넘기기
판별법: 뭉쳐 있는 데이터 중 값 하나를 삭제해서 문제가 된다면

3.11 기본형 집착

기본형 대신 객체 쓰기, 특히 문자열에서 “문자열화된 타입”이 문제(e.g. 타임스탬프를 그냥 string으로 쓴다)

3.12 반복되는 switch 문

모든 조건문을 없애야 하는 건 아니다(과거엔 의도적으로 그런 의식을 심어줬고, 지금은 의도대로 객체를 통한 다형성이 잘 정착된거 같다)
비슷한 패턴이 반복되는 조건문은 문제다
중첩 조건문도 비슷하게 문제다

3.13 반복문

map filter를 쓰자

3.14 성의 없는 요소

메서드나 클래스가 아주 짧은게 지나치게 구조화된 객체(yagni?)

3.15 추측성 일반화

당장은 필요 없는 모든 종류의 후킹 포인트와 특이 케이스 처리 로직을 작성한 코드
한번도 사용한 적 없는 매개변수가 있을 수도

3.16 임시 필드

특정 상황에서만 값이 있는 필드를 위해 나머지 경우 임시 필드를 채운 경우

3.17 메시지 체인

함수 체이닝이 너무 길어지는 경우 → 위임으로 가리자

3.18 중개자

메서드 절반 이상이 중개(다른 클래스 구현을 위임)라면 → 제거

3.19 내부자 거래

(거래)결합도를 낮춰야 한다
그런 코드를 떼어 놓거나
중개자를 만든다
상속 구조에서 그렇다면 상속 구조로(서브/슈퍼클래스 위임) 해결하도록 바꾼다

3.20 거대한 클래스

클래스 쪼개기
접두, 접미사가 같은 필드들이 후보이다
클래스 안의 자체적인 중복을 줄이기
클래스가 사용되는 패턴에 따라 쪼갤 수도 있다

3.21 서로 다른 인터페이스의 대안 클래스들

인터페이스(메서드 시그니처)가 같아질 때까지 동작을 클래스(메서드?) 안으로 몰아 넣는다
중복되는 부분을 슈퍼클래스로 추출한다

3.22 데이터 클래스

의도한게 아닌데 게터/세터만 있는 클래스
게터/세터 없이 public 접근하고 있다면 더 문제이다
데이터가 불변이라면 예외이다

3.23 상속 포기

상속 받아 쓰지 않고 코드를 다시 만들어 쓰고 있다면 구조에 문제가 있는 것
(원리주의자?: 부모 클래스는 모두 추상클래스여야 한다)

3.24 주석

주석은 향기지만 탈취제처럼 쓰려하면 문제가 된다
주석을 남기기 전에 리팩터링을 해보자

느낀점

공감이 많이 가는 것
3.1 기이한 이름
이름이 기이한 줄 모르고 진행하다가 나중에 알게 된다
타입, 특히 서버 - 클라이언트처럼 코드 바깥으로 공유하는 것들의 이름을 바꾸기 어렵다 → protobuf 사용해봐야겠다
3.5 전역 데이터: vue의 pinia나 리액트 zustand 같은 전역 state
데이터도 코드도 오염되기 쉽다
불필요하게 메소드를 공유해서 쓰게 된다
서로 배타적인 경우
3.18 중개자 3.19 내부자 거래
3.8 산탄총 수술 3.9 기능 편애; 책에서도 콕 집어 그렇다고 말하지만 경험이나 사례에서 떠오르지 않는다
산탄총 수술은 대부분의 것, 쪼개고 구조화하는 리팩터링과, 반대처럼 느껴지기도 한다
이런 점이 리팩터링을 덜 원리주의로 빠지게 하는과 동시에 수정하기 좋은 코드의 절대적 지표를 만들기 어렵게 하는 것 같다.
주석 활용하기
주석을 남겨서 커밋을 하고 바로 다음 커밋에 다음 리팩터링을 적용하는 식으로 리팩터링 호흡을 짧게 해보았다
마침 HACK 과 TODO가 아~~주 잘보이는 구성으로 코딩 중이다.
gitlab MR은 선언/참조 점프해 다니기 좋은가?
브랜치에서 edit하면 모나코 에디터가 뜨는 것 같았다