리팩터링하기 전에 제대로 된 테스트부터 마련한다. 테스트는 반드시 자가진단하도록 만든다.
statement()
함수 쪼개기한 가지를 수정할 때 마다 테스트하면, 오류가 생기더라도 변경 폭이 적어 문제를 찾고 해결하기 쉽다. 한번에 너무 많이 수정하려다 실수하는 경우 디버깅하기 어려워 결과적으로 작업시간이 늘어난다.
...
for (let perf of invoice.performances) {
const play = playFor(perf); // 인라인된 변수 제거
let thisAmout = amountFor(perf, playFor(perf)); // 변수 인라인
...
}
playFor()
함수를 사용하도록 기존 play
변수를 활용하는 코드들을 수정하고, play
매개변수를 제거한다.format -> formatAsUSD -> usd
: 44p1개의 반복문 -> 2개의 반복문으로 수정
volumeCredits
변수를 제거한 프로세스
- 반복문 쪼개기 : 변수 값을 누적시키는 부분을 분리한다.
- 문장 슬라이드하기 : 변수 초기화 문장을 변수 값 누적 코드 앞으로 이동시킨다.
- 함수 추출하기 : 적립 포인트 계산 부분을 별도 함수로 추출한다.
- 변수 인라인하기 :
voulmeCredits
변수는 제거한다.
statement()
에 필요한 데이터 처리 (연산)playfor()
함수를 statement()
로 옮기고, 기존 playfor()
를 호출하던 부분을 중간 데이터를 사용하도록 수정한다.function totalAmont(data){
return data.performances
.reduce((total,p)=> total + p.amount, 0); // for문을 파이프라인으로 변경
}
function totalVolumeCredits(data) {
return data.performances
.reduce((total,p) => total + p.volumeCredits,0); // for문을 파이프라인으로 변경
}
현재 상태에서 코드를 변경하려면 계산을 수행하는 함수에서 조건문을 수정해야 한다.
amoutFor()
함수는 연극 장르에 따라 계산 방식이 달라진다는 사실을 알 수 있는데, 이런 형태의 조건부 로직은 코드 수정 횟수가 많아질수록 비효율적인 코드로 느껴지기 쉽다.
구조적인 프로그래밍을 위해 객체지향의 핵심 특성인 다형성을 활용하는 방안에 대해 알아보자.
- 상속 계층부터 정의한다.
- 희극 서브 클래스와 비극 서브클래스가 각자의 계산 로직을 정의하도록 슈퍼 클래스 > 서브 클래스의 상속관계를 맺도록 하는 것은 ‘희극이냐 비극이냐’ 하는 1차적인 판단으로부터 연결되어지는 계산 로직이 달라지도록 의도한다.
performanceCalculator()
만들기 : aPerformance
를 this.performance
와 같은 모양으로 변경한다.약 50여 페이지에 걸쳐 간단한 로직과 간결한 코드를 가지고 있던 모양새가 보다 구조적이고 명료한 코드로 변환됨과 동시에 엄청나게 코드의 양이 늘어남을 느낄 수 있었다.
나는 짧고 간결한 코드를 선호하는 편이지만, 좋은 코드
란 짧은 코드를 의미하지 않는다는 말을 다시금 확인하게 된 것 같아 정신을 바짝! 차리게 되는것 같다.
현재, 프로젝트에서 각각의 관심사를 분리하고 쪼갤 수 있을 때까지 쪼개어 나가는 방식을 지향(채택이라고 하기에는 내가 너무 못지키고 있다)하고 있어, 특히 리팩터링을 하는 과정에서 점차 함수가 분리되고, 파일이 분리되어 나가는 과정이 낯설게만 느껴지지 않았는데, 지금 당장은 아토믹 디자인 패턴을 구현하는데 자꾸만 게으름을 부리게 되지만, 앞으로는 보다 더 철저하게, 효율적인 코드를 고려할 수 있도록 노력해야겠다.
1장은 개념을 설명하고, 정의하기보다는 예시를 통해 전체적인 흐름과 중간중간 어떤 기법을 사용했는지에 대한 언급 정도로 넘어가는 파트이다보니 생각보다 쉽게 이해할 수 있었는데, 자세한 방법론이나 개념들을 잘 익혀보는 것으로! 😤
파이팅해봅시다!