리팩터링이란, 소프트웨어의 겉보기 동작은 그대로 유지한 채, 코드를 이해하고 수정하기 쉽도록 내부 구조를 변경하는 기법을 의미한다.
- 목표 : 1) 코드의 복잡성 감소 2) 가독성 향상 3) 유지 보수성을 개선 4) 확장성을 높임
- 금지 : 기능 변경/추가, 버그 수정, 성능 개선, 버전 업데이트
함수 추출하기
,조건부 로직을 다형성으로 바꾸기
처럼 이름 붙은 리팩터링 기법들이 이 정의에 해당한다.- 더 단순하고, 깔끔하고, 표현력이 뛰어난 코드, 내부 아키텍처/객체 모델을 만듬
소프트웨어 기능을 보존하면서 설계, 구조 및 구현을 개선
- 코드의 나쁜 냄새에 따라 여러 리팩토링 기법을 점진적으로 적용해 나가면 된다.
- 중간중간에 기존 프로그램의 기능과 동작이 잘 유지되는지 확인해 주어야 한다. (테스트 코드를 마련한 후, 테스트 코드를 기반으로 확인한다.)
“수시로!”
비슷한 일을 세 번째 하게 되면 리팩토링 한다.
1) 처음에는 그냥 한다.
2) 비슷한 일을 두 번째로 하게 되면, 일단 계속 진행한다.
3) 비슷한 일을 세 번째 하게 되면 리팩터링 한다.
리팩터링하기 가장 좋은 시점은 코드베이스에 기능을 새로 추가하기 직전이다. 이 시점에 현재 코들르 살펴보면서, 구조를 살짝 바꾸면 다른 작업을 하기가 훨씬 쉬워질 만한 부분을 찾는다.
버그를 잡을 때도 마찬가지다. 오류를 일으키는 코드가 세 곳에 복제되어 퍼져 있다면, 우선 한 곳으로 합ㅊ치는 편이 작업하기에 훨씬 편하다.
코드를 수정하려면 먼저 그 코드가 하는 일을 파악해야 한다. 코드를 파악할 떄마다 그 코드의 의도가 더 명확하게 드러나도록 리팩터링할 여지는 없는지 찾아본다.
코드를 파악하던 중에 일을 비효율적으로 처리하는 모습을 발견할 때가 있다. 간단히 수정할 수 있는 것은 즉시 고치고, 시간이 좀 걸리는 일은 짧은 메모만 남긴 다음, 하던 일을 끝내고 나서 처리한다.
앞에서 본 리팩터링은 모두 기회가 될 때에만 진행하는 리팩터링이다. 그러나 기능을 추가하거나 버그를 잡는 동안 리팩터링도 함께 하는게 좋다. 프로그래밍 과정에 자연스럽게 녹이는 것이다.
보기 싫은 코드를 발견하면 리팩터링하자. 그런데 잘 작성된 코드 역시 수많은 리팩터링을 거쳐야 한다.
팀 전체가 달려들어도 몇 주는 걸리는 대규모 리팩터링도 있다. 이런 상황에 처하더라도 팀 전체가 리팩터링에 매달리는 데는 회의적이다. 그보다는 주어진 문제를 몇 주에 걸쳐 조금씩 해결해가는 편이 효과적일 때가 많다.
코드 리뷰는 개밡팀 전체에 지식을 전파나는 데 좋고, 다른 이의 코드를 리뷰하는 데도 도움이 된다.
그리고 PR 리뷰모다는 짝 프로그래밍으로 진행되는 리뷰 형태에서 더욱 효과적일 수 있다. 프로그래밍 과정 안에 지속적인 코드 리뷰가 녹아있기 때문이다.
소프트웨어 개발자는 프로다. 프로 개발자의 역할은 효과적인 소프트웨어를 최대한 빨리 만드는 것이다. 리팩터링하면 소프트웨어를 빠르게 만드는 데 아주 효과적이다. 새 함수를 추가하려는데 현재 설계가 적합하지 않다면 먼저 리팩터링하고 나서 함수를 추가하는 편이 빠르다. 버그를 수정하려면 현재 소프트웨어의 작동 방식을 이해해야 한다. 이때도 리팩터링부터 하는 편이 가장 빠르다.
프로 개발자에게 주어진 업무는 새로운 기능을 빠르게 구현하는 것이고, 가장 빠른 방법은 리팩터링이다. 그래서 리팩터링부터 한다.
지저분한 코드를 발견해도 굳이 수정할 필요가 없다면 리팩터링하지 않는다. 리팩터링하는 것보다 처음부터 새로 작성하는 게 쉬울 때도 리팩터링하지 않는다.
무결점 클린코드, 완벽한 설계는 존재하지 않는다
를 인정!
리팩터링은 좋은 기법이지만, 이에 딸려오는 문제
도 엄연히 있기에, 이런 문제가 언제 발생하고 어떻게 대처해야 할지를 반드시 알고 있어야 한다.
리팩터링의 궁극적인 목적은 개발 속도를 높여서, 더 적은 노력으로 더 많은 가치를 창출하는 것이다. 그렇더라도 상황에 맞게 조율해야 한다. 예를 들어 리팩터링이 필요해 보이지만, 추가하려는 새 기능이 아주 작아서 기능 추가부터 하고 싶은 상황에 마주칠 수 있다. 이럴 때는 프로 개발자로서 가진 경험을 잘 발휘해서 결정해야 한다.
내가 직접 건드릴 일이 거의 없거나, 불편한 정도가 그리 심하지 않다고 판단되면 리팩터링 하지 않는게 나을 수 있다.
리팩터링은 오로지 경제적인 이유
로 하는 것이다. 리팩터링은 개발 기간을 단축하고자 하는 것이다. 기능 추가 시간을 줄이고, 버그 수정 시간을 줄여준다.
팀원이라면 누구나 팀이 소유한 코드를 수정할 수 있어야 한다.
기능별 브랜치의 통합 주기를 2~3일 단위로 짧게 관리해야 한다고 주장하는 사람이 많은데, 마틴 파울러는 이보다 더 짧게 통합해야 한다고 주장한다. 이 방식을 지속적 통합(Continuous Integration)
또는 트렁크 기반 개발(Trunk-Based Development)
이라 한다.
마스터를 건강하게 유지하고, 거대한 기능을 잘게 쪼개는 법을 배우고, 각 기능을 끌 수 있는 기능 토글을 적용하여 완료되지 않은 기능이 시스템 전체를 망치지 않도록 해야 한다.
CI와 리팩터링을 합쳐서 익스트림 프로그래밍(eXtreme Programming(XP))
이라고 한다.
리팩터링의 두드러진 특성은 프로그램의 겉보기 동작은 똑같이 유지된다는 것이다. 여기서 핵심은 오류를 재빨리 잡는 데 있다. 리팩터링하기 위핵서는 자가 테스트 코드를 마련해야 한다는 뜻이다.
테스트 코드는 리팩터링을 할 수 있게 해줄 뿐만 아니라, 새 기능 추가도 훨씬 안전하게 진행할 수 있도록 도와준다.
레거시 시스템을 파악할 때 리팩터링이 굉장히 도움된다. 하지만 조금의 수정이 큰 재앙을 불러 일으킬 수 있기에, 테스트 보강이 필요하다. 프로그램에서 테스트를 추가할 틈새를 찾아서 시슽템을 테스트해야 한다.
서로 관련된 부분끼리 나눠서 하나씩 공략하는 방법이 좋다. 코드의 한 부분을 훑고 넘어갈 때마다 예전보다 조금이라도 개선하려고 노력한다.