노트산탄총 수술과 뒤엉킨 변경
Shotgun Surgery and Divergent Change
설계#refactoring · 연결된 개념 12개
쉽게 말하면
산탄총 수술은 전화번호 하나 바꿨는데 은행, 통신사, 쇼핑몰 열 군데에 따로 알려야 하는 상황이에요. 반대로 뒤엉킨 변경은 한 서류철에 온갖 일이 섞여서 무슨 일이든 그 서류철을 고쳐야 하는 상황이고요.
비유가 깨지는 곳 두 냄새는 방향이 반대라 해법도 반대예요. 흩어진 건 함께 바뀌는 것끼리 한곳에 모으고, 섞인 건 맥락별로 떼어 내요. 결국 응집도를 높이고 결합도를 낮추는 일이에요.
맥락을 제대로 나누지 못해 생기는 쌍둥이 냄새. 산탄총 수술(Shotgun Surgery)은 변경 하나를 위해 여러 파일을 조금씩 고쳐야 하는 상태, 뒤엉킨 변경(Divergent Change)은 한 모듈이 서로 다른 이유로 이리저리 바뀌는 상태다.
| 뒤엉킨 변경 | 산탄총 수술 |
|---|
| 현상 | 여러 맥락이 한 코드에 섞임 | 한 맥락이 여러 코드에 흩어짐 |
| 해법 | 맥락별로 떼어 낸다 | 맥락별로 모은다 |
- 뒤엉킨 변경은 SOLID 원칙의 단일 책임 원칙(Single Responsibility Principle, SRP)이 깨졌다는 신호다. 순서대로 흐르는 일이라면 단계를 쪼개고, 아니면 맥락별 모듈을 만들어 함수를 옮긴다
- 산탄총 수술은 함께 바뀌는 것들을 함수·필드 옮기기로 한곳에 모은다. 어설프게 쪼개진 로직은 인라인으로 먼저 합친 뒤 다시 나누는 편이 빠를 때가 많다
- 같은 if 조건이 여러 곳에 퍼져 있는 것도 흔한 원인이다. 새 경우가 생길 때마다 모든 분기를 찾아 고쳐야 하므로 다형성으로 모은다
두 냄새 모두 응집도가 낮고 결합도가 높다는 이야기다. "함께 바뀌는 것은 함께 둔다"가 기본 원칙이다.
출처: 『리팩터링 2판』 마틴 파울러 (원서 Refactoring, 2nd Edition) · Refactoring.Guru: Shotgun Surgery · Refactoring.Guru: Divergent Change
연결된 개념
이 노트를 가리키는 문서
뜻이 가까운 노트
- 리팩터링
겉으로 보이는 동작은 그대로 둔 채, 코드를 이해하고 고치기 쉽게 내부 구조를 바꾸는 일. 기능을 더하는 일이 아니라 다음 변경을 덜 위험하게 만드는 정리다.
- 조건문 분해·통합
복잡한 조건문의 조건식과 각 분기 본문에 의도를 드러내는 이름을 붙이는 리팩터링(분해, Decompose Conditional), 그리고 결과가 같은 여러 조건 검사를 하나로 묶는 리팩터링(통합, Consolidate Conditional Expression). 조건 코드는 무엇이 일어나는지는 말하지만 왜 그런지는 잘 말하지 않는데, 이름이 그 "왜"를 채운다.
- 반복문을 파이프라인으로 바꾸기
for 반복문을 filter·map·reduce 같은 컬렉션 연산의 연쇄, 즉 컬렉션 파이프라인(Collection Pipeline)으로 바꾸는 리팩터링. 각 원소가 어떤 단계를 거치는지가 위에서 아래로 읽힌다.
- 병렬 수정 (팽창-수축)
호환되지 않는 변경을 한 번에 하지 않고, 새 것을 추가하고(팽창, Expand) 옛 것과 함께 쓰다가 옛 것을 걷어 내는(수축, Contract) 단계로 나눠 하는 방법. 각 단계가 배포 가능한 상태라 중간에 멈춰도 안전하다.
- 정리(Tidying)
동작을 바꾸지 않는 아주 작은 구조 변경. 켄트 벡은 리팩터링이라는 말이 "기능 개발 중간의 긴 공사"처럼 쓰이며 동작 보존 원칙이 흐려지자, 더 작고 겁나지 않는 단위를 정리라는 이름으로 따로 불렀다. refactoring의 부분집합이다.