TL;DR
⭐️⭐️⭐️
- 리팩토링하기 전에 제대로 된 테스트부터 마련한다. 테스트는 반드시 자가진단하도록 만든다.
- 프로그램이 새로운 기능을 추가하기에 편한 구조가 아니라면, 먼저 기능을 추가하기 쉬운 형태로 리팩터링하고 나서 원하는 기능을 추가한다.
- 리팩터링은 프로그램 수정을 작은 단계로 나눠 진행한다. 그래서 중간에 실수하더라도 버그를 쉽게 찾을 수 있다.
- 컴퓨터가 이해하는 코드는 바보도 작성할 수 있다. 사람이 이해하도록 작성하는 프로그래머가 진정한 실력자다.
- 캠핑자들에게는 도착했을 때보다 깔끔하게 정돈하고 떠난다는 규칙이 있다. 프로그래밍도 마찬가지다. 항시 코드베이스를 작업 시작 전보다 건강하게(healthy) 만들어놓고 떠나야 한다.
- 좋은코드를 가늠하는 확실한 방법은 얼마나 수정하기 쉬운가다. (다형성을 활용해 계산 코드 재구성하기)
- 코드를 건강하게 관리하려면 프로그래밍 팀의 현재와 이상의 차이에 항상 신경 쓰면서, 이상에 가까워지도록 리팩토링해야한다.
예시로 접근해보기
- 다양한 연극을 외주로 받아서 공연하는 극단에서
공연 요청이 들어오면,
연극의 장르와 관객 규모를 기초로 비용을 책정하는데,
이때 발생했던 공연료와 포인트를 확인하는 프로그램이다.
최초 코드
발견부분
- 청구내역을 HTML로 출력하는 기능이 필요.
- 예측 가능한 기획 변경 대응
- 비슷한 함수를 복사할 경우 중복되는 부분의 수정이 일관되게 반영되도록 보장해야한다.
- 리팩터링이 필요한 이유는 변경때문이다.
리팩토링하기 전에 제대로 된 테스트부터 마련
한다.
테스트는 반드시 자가진단
하도록 만든다.
- 테스트코드들부터 마련해야한다.
- 리팩터링에서 테스트의 역할은 굉장히 중요하다.
- 리팩터링 기법들이 버그 발생 여지를 최소화하도록 구성됐다고는 하나,
실제 작업은 사람이 수행하기 때문에 언제든지 실수할 수 있다.
- 리팩터링 시 테스트에 상당히 의지할 필요가 있다.
- 테스트를 작성하는 데 시간이 좀 걸리지만,
신경 써서 만들어두면 디버깅시간이 줄어서 전체 작업시간은 오히려 단축된다. - 리펙터링 후에는 반드시 테스트하는 습관을 가져야한다.
프로그램이 새로운 기능을 추가하기에 편한 구조가 아니라면
,
먼저 기능을 추가하기 쉬운 형태로 리팩터링
하고 나서
원하는 기능을 추가한다.
프로그램이 잘 작동하는 상황에서 그저 코드가 ‘지저분하다‘는 이유료 불평하는 것은
프로그램의 구조를 너무 미적인 기준으로만 판단하는 건 아닐까- 코드를 수정하려면 사람이 개입되고,
사람은 미적 상태에 민감하다. - 설계가 나쁜 시스템은 수정하기 어렵다.
- 무엇을 수정할지 찾기 어렵다면 실수를 저질러서 버그가 생길 가능성도 높아진다.
- 코드를 수정하려면 사람이 개입되고,
수백줄짜리 코드를 수정할 때면,
먼저 프로그램의 작동방식을 더 쉽게 파악할 수 있도록
코드를 여러 함수와 프로그램 요소로 재구성한다.
리팩터링은 프로그램 수정을 작은 단계
로 나눠 진행한다.
그래서 중간에 실수하더라도 버그
를 쉽게 찾을 수 있다.
- 함수 추출하기
- 변수명 변경
- 변수 인라인으로 변경
- 반복문 쪼개기
함수 추출 이후에는 명확하게 표현할 수 있는 간단한 방법을 찾아보자.
- 변수명
- 접두어로 타입을 표현한다.
- 매개변수의 타입이 뚜렷하지 않으면 부정관사를 붙인다. (a/an)
- 캔트백 [Smalltalk Best Practice Patterns]를 참고했다고함
- 좋은 코드라면 하는 일이 명확히 드러나야하며, 변수 이름은 커다란 역할을 한다.
- 추출한 함수에는 그 코드가 하는 일을 설명하는 이름을 지어준다.
- 다음번에 코드를 볼때 다시 분석하지 않아도
코드 스스로가 자신이 하는 일이 무엇인지 이야기해줄 것이다.
- 다음번에 코드를 볼때 다시 분석하지 않아도
컴퓨터가 이해하는 코드는 바보도 작성할 수 있다.
사람이 이해하도록 작성하는 프로그래머
가 진정한 실력자다.
- 임시변수를 질의함수로 바꾸기(7장): 긴 함수를 쪼갤때마다 변수를 최대한 제거한다.
- 지역변수를 제거해서 얻는 가장 큰 장점은 추출 작업이 훨씬 쉬워진다는 것이다.
- 유효범위를 신경써야 할 대상이 줄어들기 때문이다.
변수 인라인하기(6장): 변수를 제거하고 바로 함수를 적용한다.
> 개인적으로 이건 잘 모르겠다.
> 함수 안에서 해당변수가 여러번 필요한 경우가 있는데 그때마다 호출하는거가 더 나은건지,
> 변수로 해서 레퍼런스만 호출하는게 좋은건지.라고 했지만, 책 마지막에는
“특별한 경우가 아니라면 성능이슈는 일단 무시하라는 것,
리팩토링때문에 성능이 떨어진다면,
리팩터링을 마무리하고 나서 성능을 개선하자”- 함수명 바꾸기(6장)
- 이름짓기는 중요하면서도 쉽지 않은 작업이다.
- 이름이 좋으면 함수 본문을 읽지 않고도 무슨일을 하는지 알 수 있다.
- 반복문 쪼개기(8장): 반복문안에서 여러 역할을 하는 것들을 반복분을 따로 만들어서 각각 수행하도록..
- 논리적인 요소를 파악하기 쉽도록 코드의 구조를 보강하는데 주안점을 두고 리팩터링.
== 복잡하기 얽힌 덩어리를 잘게 쪼개는 작업
- 논리적인 요소를 파악하기 쉽도록 코드의 구조를 보강하는데 주안점을 두고 리팩터링.
- 문장 슬라이드하기(8장): 문장 위치를 바꾸는것..?
캠핑자들에게는 도착했을 때보다 깔끔하게 정돈하고 떠난다
는 규칙이 있다.
프로그래밍도 마찬가지다.
항시 코드베이스를 작업 시작 전보다 건강하게(healthy) 만들어놓고 떠나야 한다.
- 단계 쪼개기(6장): 1. 필요한 데이터를 처리하고 => 2. 그 다음 단계 => …
- 함수 옮기기(8장)
- 반복문을 파이프라인으로 바꾸기(8장)
- 간결함이 지혜의 정수일지 몰라도, 프로그래밍에서만큼은 명료함이 진화할 수 있는 소프트웨어의 정수다.
좋은코드를 가늠하는 확실한 방법은 얼마나 수정하기 쉬운가
다.
다형성
을 활용해 계산 코드 재구성하기
1 | function amountFor(aPerformance) { |
- 위 코드는 타입이 추가될수록 복잡도가 올라간다.
- 다형성을 활용하는 것이 자연스럽다.
- 조건부 로직을 다형성으로 바꾸기(10장)
- class로 함수옮기기를 하는 것은 다른 컨텍스트로 옮기는 큰 작업
- 타입코드를 서브클래스로 바꾸기(12장)
- 생성자 팩터리 함수로 바꾸기(11장)
- 원본함수를 중첩 함수 여러개로 나눴다.
- 계산코드와 출력코드를 분리했다. (단계 쪼개기)
- 계산로직을 다형성으로 표현했다.
- 코드는 명확해야한다.
- 코드를 수정해야 할 상황이 되면 고쳐야 할 곳을 쉽게 찾을 수 있고,
오류 없이 빠르게 수정할 수 있어야 한다. - 건강한 코드베이스는 생산성을 극대화하고,
고객에게 필요한 기능을
더 빠르고 저렴한 비용으로 제공하도록 해준다.
코드를 건강하게 관리하려면
프로그래밍 팀의 현재와 이상의 차이에 항상 신경 쓰면서,
이상에 가까워지도록 리팩토링
해야한다.
리팩토링을 효과적으로 하는 핵심은
- 단계를 잘게 나눠야 더 빠르게 처리할 수 있고
- 코드는 절대 깨지지 않으며
- 작은 단계들이 모여서 상당히 큰 변화를 이룰 수 있다는 사실을 깨닫는 것이다.