01. 첫 번째 예시
#
서론리팩토링의 저자 마틴 파울러는 클린코드의 저자 로버트.C.마틴, TDD의 창시자 켄트백과 마찬가지로 소프트웨어 업계의 3대 성인(聖人) 중 한명이다.
그는 서론에 리팩토링을 왜 해야하는가?에 대한 이야기를 하면서, 자신의 경험담을 이야기한다.
유명한 그의 리팩토링의 중요성에 대한 영상을 보면 그가 얼마나 소프트웨어 개발에 있어서 깔끔한 코드와 구조를 중요하게 생각하는지 알 수 있다. 영상(한글 자막을 달아주신 데브원영님 감사합니다)
리팩토링은 외부적으로 봤을 때 동작에 이상이 없고, 구조적인 변경만 있을 뿐이지만 이러한 리팩토링을 계속해서 하지 않으면 결국 소프트웨어의 변경이 어려워지고, 예측할 수 없는 문제들이 계속해서 발생하게 된다.
즉, 리팩토링이란 소프트웨어 개발이 건축물처럼 만들고 나서 끝이 아니라, 계속해서 유지보수를 해야하고 요구사항과 스펙이 변경될 수 있으므로 변경을 용이하게 하기 위해 코딩 끝난 후 설계를 개선하기 위해 수행하는 작업이다.
또한 각 장이 갖는 의미를 설명하면서 시작부터 리팩토링이 무엇인지 실제 코드를 통해 보여준다.
다행히 이 책이 자바스크립트로 재판된 이유는, 조금 더 많은 사람들이 보기 위함이며 고급 문법은 다루지 않는다고 한다.
콜백/프로미스를 async/await으로 리팩토링하는 자바스크립트만의 문법은 다루지않는다고 한다. 자바스크립트는 어디까지나 수 많은 언어 중의 하나이며, 클래스, 모듈, 함수와 같이 일반적인 개념들에 대해서 다룬다고 한다.
#
01. 리팩토링: 첫 번째 예시어느정도 규모있는 프로그램을 만들자니 내용이 너무 많고, 그렇다고 너무 간단하면 리팩토링 할 부분이 없으니, 큰 서비스 중 하나의 기능을 구현한다고 상상하고 리팩토링에 임하도록 하자.
첫 번째 예시에서는 다양한 연극을 외주로 받아 공연하는 극단의 서비스를 개발해볼 것이다.
#
기능 요구 사항 분석공연 요청이 들어오면 연극의 장르와 관객 규모를 기초로 비용을 책정한다.
현재 이 극단은 두 가지 장르, 비극과 희극만 공연한다.
공연료와 별개로 포인트를 지급해서 다음번 의뢰 시 공연료를 할인 받을 수도 있다.
#
예제 코드현재 나는 자바스크립트를 실무에서 거의 쓰지 않는다. (간단한 스크립트 짤 때나 JSON 오브젝트 다룰 때 정도)
주로 쓰는 언어는 Java, Kotlin, Go, Typescript이다 보니 책에 있는 JS 예제를 그대로 옮겨적는 것은 학습에 큰 영향이 없을 것 같아서 Kotlin으로 재작성 해보았다. (마틴 파울러도 해당 예제들을 수 십개의 언어로 만들어보았다고 하니 안될 것도 없어 보인다.)
전체 코드는 코드 저장소에 있다.
#
첫 예시 프로그램의 소감코드를 짜면서 느꼈지만 when 구문 안에서 반복되는 코드가 있는 것이 조금 불편하게 느껴졌다. (뭔가 리팩토링 할 수 있을 것 같은 느낌적인 느낌)
책에서는 프로그램이 새로운 기능을 추가하기에 애매하다면 기능을 추가하기 쉬운 구조로 리팩토링한 뒤에 원하는 기능을 추가한다고 한다.
추가적인 요구 사항은 사용자에게 청구내역을 HTML로도 출력하는 기능이 필요할 수 있다고 한다. (요구사항의 추가 가능성)
또 연극이 현재 비극과 희극만 존재하는데, 사극이나 전원극, 고전극, 자유극 등등 극의 타입이 얼마든지 추가로 생길 수 있다. 그러면 공연료와 적립 포인트 계산법에 반드시 영향을 미치게 되어있다.
이처럼 연극 장르와 공연료 정책이 달라질 때 마다
statement()
함수를 수정해야 한다.여기서 HTML 출력을 위해
htmlStatement()
함수까지 복사해서 만든다면 모든 수정이 두 함수에 일관되게 적용하도록 보장해주어야한다.리팩토링이 필요한 이유가 여기에 있다. 변경에 유연하게 대처하기 위해서!
#
리팩토링의 첫 단계리팩토링의 첫 단계는 테스트코드다.
리팩토링에서 테스트의 역할은 꽤 중요한데, 리팩토링 중 실수가 발생할 수 있기 때문에 촘촘한 테스트 코드를 작성해주어야한다.
#
statement() 함수 쪼개기statement 함수처럼 긴 함수를 리팩토링할 때는 부분으로 나눌 수 있는 지점을 찾는다.
switch문을 함수로 뽑아내보자 이런 기법을 함수 추출하기라는 이름으로 부른다.
자 그러면 리팩토링한 결과가 일치하는지 확인하기 위해 테스트 코드를 작성해두자.
나는 테스트 코드가 없는 리팩토링은 낙하산 없이 번지점프를 하는 것과 같다고 생각한다.
테스트에는 JUnit 5를 사용했다.
앞으로 이 테스트가 우리의 리팩토링의 안전장치가 되어줄 것이다.
나는 종종 동기들에게 돌아만 가는 코드는 원숭이도 짤 수 있다라고 이야기하곤 했다. 그 정도로 깔끔한 코드가 중요하다고 생각하기 때문이다.
그런데 이 책에서도 마찬가지로 마틴 파울러의 명언이 나온다. 컴퓨터가 이해하는 코드는 바보도 작성할 수 있다. 사람이 이해하도록 작성하는 프로그래머가 진정한 실력자다
#
play 변수의 제거play는 개별 공연에서 값을 얻으므로 매개 변수에서 처리할 필요가 없다.
이러한 play 변수를 최대한 제거하는 것을 임시 변수를 질의 함수로 바꾸기라고 부른다.
마틴 파울러는 임시 변수를 최대한 제거해서 복잡도를 낮춘다고 한다.
마틴 파울러는 불필요한 지역 변수를 최대한 줄이는 방식이 리팩토링에 편하다고 한다.
나는 평소에 임시 변수를 많이 만드는 편인데, 제거하는 것이 리팩토링에 더 도움이 된다고 한다. 이런 것을 변수 인라인 하기라고 부른다고 한다.
마틴 파울러는 추출 작업을 할 때 가장 먼저 지역 변수부터 제거한다고 한다.
이렇게 임시 변수를 제거하기 위해 별도의 함수로 뽑아내보면 다음과 같이 리팩토링이 된다.
리팩토링을 하다보면 성능에 대한 걱정을 할 때가 있다.
하지만 마틴 파울러는 성능은 신경쓰지 말고 더 깔끔한 코드를 얻기 위해 일단 무시하고, 추후에 성능이 이슈가 된다면 다시 개선 작업하는 것을 가이드하고 있다.
이 과정에서 리팩토링은 같은 4개의 스텝으로 진행했다.
- 반복문 쪼개기로 변수 값을 누적시키는 부분을 분리
- 문장 슬라이드하기로 변수 초기화 문장을 변수 값 누적 코드 바로 앞으로 옮긴다.
- 함수 추출하기로 적립 포인트 계산 부분을 함수로 추출한다.
- 변수 인라인하기로 volumeCredits 변수를 제거한다.
- 어느정도 리팩토링이 완료되었다.
#
중간 점검statement()의 메인 로직은 단 7줄에 불과하며 모든 기능들을 함수로 분리해내었다.
복잡하게 얽힌 덩어리를 잘게 쪼개었으니 이번엔 기능 변경을 해보자.
앞서 이야기 했던 Text 출력하는 statement()와 HTML을 출력하는 statement(), 두 가지 기능을 개발해야한다.
그런데 중첩함수가 이미 많으니 그대로 복-붙을 하기에는 조금 애매하니 단계 쪼개기를 사용하여 로직을 나눠보자.
코드를 구조적으로 나누면서 코드 양이 늘었지만, 훨씬 보기 편하게 변경되었다.
게다가 htmlStatement를 어떠한 코드 중복이나 변경 없이 아주 손쉽게 만들어낼 수 있었다.
이번엔 다형성을 활용해 계산 코드를 재구성해보자.
#
다형성을 활용한 계산 코드 재구성이번 요구 사항은 연극 장르를 추가하고 장르마다 공연료와 적립 포인트 계산 방식을 다르게 지정하도록 기능을 수정해야한다.
amountFor()를 수정하면 되는데 여간 귀찮은 일이 아니다.
이를 객체지향의 다형성을 이용해 개선해보자.
로직이 매우 깔끔해지고 한 눈에 알아보기 쉽게 개선되었다.
공연의 종류가 늘어나면 팩토리 메서드인
createPerformanceCalculator
에서 타입을 추가해주고,PerformanceCalculator
인터페이스를 구현하는 구현체를 만들어서 계산 로직을 만들어주기만 하면 된다.이전에 비해서 훨씬 알아보기 쉬워졌고 구조적으로 코드가 변했다.
함수 추출하기, 변수 인라인하기, 함수 옮기기, 조건부 로직을 다형성으로 바꾸기와 같은 과정을 거쳐서 리팩토링을 진행했다.
이번 챕터에서는 원본 함수를 중첩 함수 여러 개로 나눈 뒤 단계 쪼개기를 사용해서 계산 코드와 출력 코드를 구분해냈다. 마지막으로 계산 로직을 다형성으로 표현했다.
결국 좋은 코드를 가늠하는 확실한 방법은 얼마나 수정하기 쉬운가에 달려있다.
#
요약리팩토링의 핵심은 수정하기 쉬운 코드를 만드는 것이다.
이를 위해 먼저, 각 단계를 굉장히 잘게 나눠야 한다.
그리고 코드가 변경될 때 마다 매 번 컴파일하고 테스트하여 작동하는 상태로 유지한다.
#
Reference- Refactoring 2판 ( 저자 : 마틴 파울러 )