학생 신분에서, 교육을 받는 입장에서 또는 개인 및 팀 프로젝트를 하는 입장에서, 가장 접하기 쉽지 않은 부분 중 하나가 리팩토링이지 않을까 생각한다.
Software Engineering을 하시는 분이라면, 모두들 어느 시점에서는 꼭 마주하는 이 리팩토링, 가장 어색하고 개인적으로도 하고 싶지 않았던 (
"반복 작업"을 하기 싫어하는 성격이다... 게임도 이지모드, 하드모드, 헬모드 등 반복적인 루프를 갖고 있는 게임을 싫어한다...
) 부분에 대해서 가장 필요하고 가장 빈번하게 일어나는 작업 중 하나란 것을 몸소 한번 더 인지하며 개념을 정리하고자 하였다.
Wikipedia에서는 리팩토링(Code Refactoring)을 다음과 같이 정의하였다.
code refactoring is the process of restructuring existing computer code—changing the factoring—without changing its external behavior.
코드 리팩토링은 현존하는 컴퓨터 코드를 재구성하는 과정이다 - factoring(decomposition: 어렵고 복잡한 방식을 쉽고 가독성있게)을 바꾸면서 - 외부적인 행동을 바꾸지 않으면서
즉, 현존하는 코드는 절대 완벽하지 않다. 아무리 잘 짠 코드일지라도, 시간이 지남에 따라, 기술이 발전함에 따라, 기획과 개발 방향성에 따라 바뀌어야 하는 순간이 있을 것이다. 이러한 과정을 리팩토링을 통해 더욱 견고하고 확장성있게 넓혀갈 수 있을 것이다.
리팩토링을 할 때 가장 중요하고 많이 보는 것은 무엇일까?
현재 코드를 리뷰하고, 리팩토링 방안을 생각하는 입장으로써, 가장 신경 쓰이는 부분은 당연 가독성과 유지보수성이다.
1. 가독성과 유지보수성
a) 가독성
많은 개발자들을 보면 다들 "혼자서 일하는 것"과 "다 함께 일하는 것"에 대해 많은 고찰을 한다. 회사에 다니니까, 프로젝트를 함께하니까, 다양한 개발자들이 내 코드를 보니까... 많은 이유를 통해 협업의 관점에서 가독성은 중요하다. 하지만 사실 "누군가와 함께" 보다, 단순히 잘 짠 코드는 "내가" 읽기 편하다.
당연히 내가 짯으니까 난 읽기 쉽지... 라는 생각은 현재 5개가 넘는 프로젝트를 진행해보며 버리게 되었다. 내 코드도 읽기 힘들때가 다반수이고, 몇일이 지나면 내 코드가 남코드 같다. 내가 짠 코드도 금방 어색해지는 상황에서 가독성을 높이기 위한 cost는 전혀 아깝지 않을 것이다. 그리고 이러한 cost에 조금 더 노력을 쏟아 누구든지 읽을만한 코드가 된다면 훨씬 좋지 않을까?
b) 유지보수성
앞서 설명했드시, 서비스 및 프로젝트는 단기성이 아니다. 언젠가 기능을 붙히고 코드를 작성해야 할 순간이 생긴다. 물론 처음부터 잘 사용하면 절대적 주기가 줄거나, 비용을 줄일 수 있지만, 인수인계와 같은 상황에 부딫혔을 때, 더욱 질적인 코드를 제공하고자 리팩토링을 진행한다.
2. 리팩토링의 마음가짐
리팩토링을 진행 할 땐 고려할 부분이 매우 많을 것이다. 프로젝트 구조부터 코드의 인덱싱, 네이밍 컨벤션 등등...
프로그래밍에서 사용되는 수 많은 밈들과 좋은 이야기들이 있다.
https://wou.edu/las/cs/csclasses/cs161/Lectures/rulesofthumb.html
[Programming Rules of Thumb
a) Subprogram behavior and length: Subprograms should do precisely ONE conceptual task and no more. The length of a subprogram should allow it to be easily visually inspected; generally no more that one page in length. Similarly you should generally
wou.edu](https://wou.edu/las/cs/csclasses/cs161/Lectures/rulesofthumb.html)
한 대학의 자료에서 몇가지 좋은 프로그래밍 룰들을 가져와 보았다. 내용은 다음과 같다.
1) K.I.S.S. (Keep It Simple, Stupid) 간단하게 하라고 바보야!
- 서브프로그램의 behavior와 length: 서브프로그램은 "단 하나"의 conceptual task를 진행해야 한다. I/O와 로직은 최대한 분리하자.
- 여러가지의 task로 decompose 될 수 있는 서브프로그램일 경우, 나누자. 각각의 테스크가 테스트 과정을 거치고 합쳐져도 된다. Gall's Law에 따르면, 모든 복잡한 task는 간단한 task들로 부터 진화(evolved) 된 것이다.
2) "Rule of Three" (code duplication) 3의 규칙
- 복사-붙혀넣기는 당연한 과정 중 하나이고, 이러한 과정이 한번은 있어도 된다. 하지만 그 이상부터는 새로운 과정으로 추출되어야 한다.
- 코드를 유지보수하는 사람은 n번 쓰인 코드에 대해 n번 바꿔야 한다. 하지만 잘 추출된 코드는 1번으로 해결할 수 있다.
3) Ninety-ninety rule ( failure to anticipate the hard parts) 90-90 규칙 (어려운 부분들을 예측하는 것의 실패)
- 프로젝트(코드)의 90%는 개발 시간의 90%를 차지한다. 나머지 10%는 개발 시간의 90%를 차지한다.
- 오탈자 처럼 보이는 180%의 시간은 프로젝트(코드)의 진행 시간에 대한 현실적인 생각이다.
- 프로젝트(코드)의 큼지막한 부분 90%는 예상과 비슷한 시간으로 진행된다. 하지만 나머지 10%는 보통 버그나 코드 개선과 같은 방향성을 갖고 있는데, 이러한 부분들은 예상과 다르게 흘러갈 때가 많다. 기존 진행했던 90%보다 더 많은 시간을 차지하기 쉽상이다.
4) Efficiency vs. code clarity (chasing false efficiency) 효율성 vs 코드 가독성 (잘못된 효율성을 쫒는 것)
- "bit twidlling": 한 줄이라도 더 적게 적으려고 가독성을 포기하지마라! 실질적으로 이러한 행동이 기능적이나 알고리즘적으로 더욱 나은 성과를 갖고 오지 않는다. *bit twiddling: 비트 조작은 단어보다 짧은 비트 또는 다른 데이터 조각을 알고리즘 적으로 조작하는 작업입니다.
- 코드의 실질적인 성능을 향상시키는 알고리즘은 O(N^2)에서 O(NlogN) Complexity를 조정하는 과정과 같은 부분에서 일어난다.
- Critical 한 부분들은 97%의 코드가 아닌 3%의 코드에서 발생한다.
- 병목 현상은 예기치 못한 부분에서 일어난다. 즉, 현상이 일어난 부분을 확정짓기 전까진 어림짐작하지 마라.
5) Naming of things (subprograms and variables) 네이밍 (서브-프로그램과 변수)
- 네이밍 컨벤션
- 유지보수를 위한 소스코드를 읽고 이해하는데 필요한 비용을 줄이기 위해
- 소스코드의 모양세를 개선하기 위하여 (지나치게 긴 이름, 불분명한 약어)
- 서브프로그램의 verb/verb 형식의 네이밍. 형용사 혹은 명사의 변수 네이밍
이러한 부분들을 "기억"하고 "습관화" 하는 것이 현재 글을 쓰고 있는 Junior Developer의 위치에서 가장 중요한 것 같다. 내가 짠 코드들은 누군가는 읽는다. 같이 협업하는 동료, 코드를 리뷰해주는 선임, 코드를 읽고 인수인계를 진행 할 미래의 후임 등...
다음 포스트에서는 조금 더 깊게 들어가, 리팩토링의 방향성과 앞서 언급한 서브프로그램(Frontend, 언어는 Javascript 관점에서는 함수)의 작성 방향성(명령형 프로그래밍과 선언형 프로그래밍)에 대해 이야기하고자 한다.
'Software Engineering' 카테고리의 다른 글
Git 브랜치 전략, Git-flow (0) | 2022.09.03 |
---|---|
성능을 위한 프론트엔드 설계와 코드 - 1 (0) | 2022.08.28 |
Quality Assurance (QA: 품질보증) (0) | 2022.08.26 |
함수형 프로그래밍 (Functional Programming) (0) | 2022.08.21 |
명령형 프로그래밍 VS 선언형 프로그래밍 (2) | 2022.08.15 |