이번엔 리팩토링 챕터3 부분을 읽어보겠습니다!
저자는 프로그래밍 미학이라는 모호한 개념보다 악취라는 표현이 낫다고 표현함.
악취가 나는 코드도 패턴이 있음
1. 기이한 이름
이름만 보고도 각각이 무슨 일을 하고 어떻게 사용해야하는지 명확히 알 수 있도록 엄청나게 신경 써서 이름을 지어야 한다.
네이밍이 프로그래밍 활동의 많은 부분을 차지하는 것을 알고 있었지만, 경험이 많은 개발자들도 동일한 어려움을 겪는다는 사실에 조금 위로가 되기도 함...
마땅한 이름이 떠오르지 않는다면 설계에 더 근본적인 문제가 숨어 있을 가능성이 높다.
이 문장은 새로웠음! 아무리 노력해도 적당한 이름이 나오지 않는다면 설계가 잘못되지 않았나 돌아보는 것도 좋은 방법. 적절한 관심사 분리를 해야 좋은 이름도 지을 수 있을 것 같다.
2. 중복 코드
3. 긴 함수
우리는 주석을 달아야 할 만한 부분은 무조건 함수로 만든다. 그 함수 본문에는 원래 주석으로 설명하려던 코드가 담기고, 함수 이름은 동작 방식이 아닌 '의도(intention)'가 드러나게 짓는다.
주석을 달기전에 한 번 머뭇거리자. 함수를 지을 때 동작 방식을 설명하려고 했던적이 많았다. 하자만 해당 객체에서 함수가 존재하는 이유, 의도를 명확하게 드러내는 이름을 짓는것이 더 도움이 된다는 걸 알게되었다. 외부에서 해당 객체를 호출하는 관점으로 보면 구체적인 구현 내용은 알 필요 없고, 의도만 알고 싶기 때문인 것 같다.
아래는 여기서 나오는 방법들인데, 현재는 구체적인 내용을 몰라서 일단 필기만 해두고 넘어가겠다.
- 함수 추출하기
- 임시 변수를 질의 함수로 바꾸기
- 매개변수 객체 만들기
- 객체 통째로 넘기기
- 함수를 명령으로 바꾸기
- 조건문 분해하기
- 조건문을 다형성으로 바꾸기
- 반복문 쪼개기
4. 긴 매개변수 목록(Long Parameter List)
- 매개변수를 질의 함수로 바꾸기
- 객체 통째로 넘기기
- 매개변수 객체 만들기
- 플래그 인수 제거하기
- 여러 함수를 클래스로 묶기
5. 전역 데이터
전역 데이터는 코드베이스 어디에서든 건드릴 수 있고 값을 누가 바꿨는지 찾아낼 메커니즘이 없다는 게 문제다.
어디서든 변경할 수 있는데, 변경 주체를 찾기 어려움. 디버깅 하기가 어려움!
변수 캡슐화하기 (중략) 데이터를 함수로 감싸는 것만으로도 데이터를 수정하는 부분을 쉽게 찾을 수 있고 접근을 통제할 수 있게 된다.
데이터를 함수로 만들어보면 어디서 호출하고 있는지 알 수 있음
6. 가변 데이터 (Mutable Data)
함수형 언어에서는 Immutable Data 만을 다룬다고 함. 하지만 함수형 언어가 아닌 곳이 더 많다.
세터 제거하기 도 방법일 수 있음
7. 뒤엉킨 변경 (Divergent Change)
코드를 수정할 때는 시스템에서 고쳐야 할 딱 한 군데를 찾아서 그 부분만 수정할 수 있기를 바란다.
옮긴이_ (중략) 여기서 '변경의 이유'의 뜻이 잘 와닿지 않는다면 로버트 마틴이 '클린 아키텍처'에서 정당한 '단일 모듈은 오직 하나의 액터(actor)에 대해서만 책임져야 한다'라는 표현으로 이해하자.
단일 책임을 잘 모르겠다면, 외부 인터페이스 관점으로 바라볼 때 단일한 책임을 가지고 있는지 보면 되는걸까?
여전히 명확한 답을 내리지는 못하겠다. 클린 아키텍처를 읽어보면 도움이 되려나...
8. 산탄총 수술 (Shotgun Surgery)
뒤엉킨 변경 | 산탄총 수술 | |
원인 | 맥락을 잘 구분하지 못함 | |
해법(원리) | 맥락을 명확히 구분 | |
발생 과정(현상) | 한 코드에 섞여 들어감 | 여러 코드에 흩뿌려짐 |
해법(실제 행동) | 맥락별로 분리 | 맥락별로 모음 |
옮긴이가 표로 정리해줘서 이해하는데 많은 도움이 되었다.
개념을 비교해야할 때는 표로 만들어봐야겠다
9. 기능 편애 (Feature Envy)
이거는 아직 이해를 제대로 못함ㅜㅜ
10. 데이터 뭉치 (Data Clumps)
- 데이터 뭉치인지 확인하려면 값 하나를 삭제해보기
- 레코드 구조가 아닌 '클래스'로 만들기: 좋은 향기를 흩뿌릴 기회가 생김. 생산성에 기여하는 정식 멤버로 등극
11. 기본형 집착
- 자신에게 맞는 기초타입 정의. ex) 화폐, 좌표, 구간 등
- 물리량을 계산할 때 밀리미터나 인치 같은 단위를 무시하고, <- 이거는 이해했는데
- 범위도 if (a < upper && a > lower) 처럼 처리하는 코드는 안좋음 <- 이 범위 연산은 어떤 부분이 문제일까?
값 객체에 해당 단위를 처리할 수 있는 범위 연산을 포함하는 것이 좋을까?
12. 반복되는 switch 문
switch문 자체가 나쁜 것은 아님.
현대 언어의 switch 문은 다양한 기능이 있음
똑같은 조건부 로직 (switch/case, if/else) 이 반복해서 등장하는 경우 악취라고 할 수 있음
13. 반복문
14. 성의 없는 요소
역할이 너무 줄어든 객체, 불필요한 함수를 인라인 하거나 계층 합치기를 적용할 수 있음
15. 추측성 일반화
'나중에 필요할 거야' 라는 생각으로 만들어둔 것들이 이에 해당 함
16. 임시 필드
특정 상황에서만 값이 세팅되는 경우가 있음.
하지만 객체를 가져올 때는 당연히 모든 필드가 채워져 있으리라 기대하는 것임 보통임. <- 여기에 대한 생각이 없었음...
덩그러니 떨어져 있는 필드를 발견하면 클래스 추출하기 시도
17. 메세지 체인
위임 숨기기로 해결
메세지 체인이 무조건 나쁜 것은 아님. 경우에 따라 허용
18. 중개자 (Middle Man)
지나치게 쓰면 문제가 됨.
클래스가 제공하는 기능 절반 이상이 위임되고 있으면 실제로 일하는 객체와 직접 소통하게 해주기.
19. 내부자 거래 (Insider Trading)
이건 제대로 모르겠음
20. 거대한 클래스 (Large Class)
클래스 추출하기
슈퍼클래스 추출하기
타입 코드를 서브클래스로 바꾸기
21. 서로 다른 인터페이스의 대안 클래스들
22. 데이터 클래스
23. 상속 포기
24. 주석
주석은 악취가 아닌 향기를 입힌다.
문제는 주석을 탈취제 처럼 사용하는데 있다.
주석을 남겨야겠다는 생각이 들면, 가장 먼저 주석이 필요 없는 코드로 피랙터링해본다.
'CS > Refactoring' 카테고리의 다른 글
[Refactoring] Chapter 3, 4 과제 (0) | 2021.04.17 |
---|---|
[Refactoring] Chapter4를 Swift로 따라해보기 (0) | 2021.04.17 |
[Refactoring] Chapter 4. 테스트 구축하기 (0) | 2021.04.17 |
[Refactoring] Chapter2 과제 (0) | 2021.04.13 |
[Refactoring] Chapter2 요약 (0) | 2021.04.13 |