코드 퀄리티를 높이는 방법과 왜 그래야 하는지 by Venkat
이 글은 (1) Reasons & Ways to Improve Code Quality • Venkat Subramaniam • GOTO 2021 - YouTube 의 저만의 해석 및 감상문입니다.
[TOC]
코드 품질을 왜 높여야만 하는가?
코드 품질을 높여야 하는 이유는 순전히 경제적인 이유 때문입니다.
코드의 품질이 낮아지면 코드의 가독성이 떨어지고 기능의 수정이나 개선을 하기 위해서 어떻게 해야 하는지 알아내기가 점점 어려워집니다. 그렇게 되면 시간을 많이 소요하게 될 것이고, 프로그래머들이 만들어내는 시간 대비 가치는 점점 낮아질 것입니다. 그렇게 되지 않도록 끊임없이 코드 품질을 높여야 합니다.
코드 품질을 개선하는 방법은?
코드의 품질을 높이기 위한 방법으로 총 여섯 가지 제안하고 있습니다.
- 함수는 한 단계만 추상화해라.
- 코드의 응집력을 높이고, 결합도를 낮춰라.
- 의도를 표현하라.
- 원시적인 코드에 대한 집착을 버려라.
- 똑똑한 코드를 멀리하라.
- 주석은 무엇보다 왜라는 질문에 집중해서 작성해라.
- 의미 있는 이름을 부여해라.
- 전략적 코드 리뷰
하나씩 살펴보겠습니다.
Honor SLAP
SLAP은 Single Level of Abstraction Principle입니다. 함수를 한 단계씩 구체화하면서 작성하라는 것입니다.
이렇게 하는 게 왜 코드 품질을 개선하는지 말씀드리겠습니다.
우리가 파악하기 힘든 코드의 특성 중 하나는 함수가 너무 길다는 것입니다. 길면 보통 복잡하기 때문이지요.
함수가 길다는 것은 무슨 뜻일까요? 100줄? 1000줄? 함수가 긴 것이 코드 파악에 어려움을 준다는 것은 대부분의 사람이 동의하지만, 길다의 기준은 모두 다를 수 밖에 없습니다.
화자는 함수의 길이가 ‘줄’에 해당하지 않는다고 얘기합니다. 우리 마음속에 함수의 길이는 추상화의 깊이라고 얘기합니다.
예를 들어 보겠습니다.
주말에 부모님 집에 가서 식사한 것을 설명할 때, “집에서 현관문으로 걸어가 손잡을 잡고, 문을 열어 밖으로 나와서, 다시 스크린 도어를 열고 나와서 아파트 밖으로 나온 다음, 앞으로 걸어가다가, 왼쪽에 있는 아파트 정문으로 나가서, 50미터 밖에 있는 버스 정류장까지 간 다음에 3426번 버스를 올 때까지 기다렸다가 버스가 정류장에 정차한 후에 문이 열린 후에 올라타고, 주머니에 있는 교통카드를 꺼내서 교통카드를 버스 운전사 좌석 옆에 있는 카드 리더기에 찍고, 카드리더기가 1250원 표시한 것을 확인한 후에 몸을 돌려서 앞에서 두 번째 좌측에 있는 빈 자리에 앉아서… (후략)”
이렇게 얘기하지는 않을 겁니다. 이렇게 얘기하는 순간 주변에 사람들은 다 도망갈 겁니다. (웃음) 이 문장의 문제는 1)도대체 무슨 말을 하려는 건지 따라갈 수가 없다는 것 2) 듣는 사람이 어디까지 구체적으로 듣고싶은지 모르는 채로 너무 구체적으로 얘기한 것입니다. 사람은 보통 이렇게 대화하지 않습니다. 일반적인 대화는 이렇겠죠?
“주말에 뭐 했어?”
“주말에 부모님이랑 식사했어.”
“어디 갔는데?”
“부모님 집에서 먹었어?”
“부모님 집이 어딘데? 멀어?”
“부모님 집은… xxx에 있어. "
“뭐 타고 갔어?”
“버스”
“너희 집에서 그 동네까지 바로 가는 버스가 있어?”
“3426번 타면 어디를 거친 후에 바로 가”
“…”
“…”
대화가 계속 진행될 수도 있고, 물어보는 사람이 더 구체적인 게 궁금하지 않으면 더는 얘기하지 않고, 대화가 종료될 것 같습니다. 아주 간단한 사실부터 구체적인 사실에 도달하는 것. 이게 사람이 무언가를 파악하는 자연스러운 방식입니다.
화자는 코드도 마찬가지라고 말하고 있습니다.
코드의 응집력을 높이고, 결합도는 낮춰라.
코드의 응집력이 높다는 것은 서랍 정리가 잘 되어 있는 것과 비슷합니다. 제가 서랍이 여러 개 있는데, 각 서랍에 들어가는 물건의 기준이 정해져 있지 않다면, 나중에 필기구를 찾을 때 어느 서랍을 열어봐야 하는지 몰라서 다 열어봐야 합니다. 서랍이 잘 정리되어 있고 두 번째 서랍에 필기구가 정리되어 있으면 두 번째 서랍만 뒤져서 원하는 필기구를 찾으면 됩니다. 코드의 응집력이 높다는 것도 이와 상통합니다. 특정 종류의 함수를 어디서 찾아야 하는지 코드를 읽는 사람이 파악할 수 있게 하는 것. 그게 응집력이 높은 코드를 작성해야 하는 이유입니다.
의도를 코드에 표현해라
이 부분은 이런 저런 설명을 영상에서 했지만, 해당 문장이 모든 것을 설명하는 것 같아서 부연 얘기는 하지 않겠습니다.
원시적인 코드에 대한 집착을 버려라
절차지향적인 프로그래밍 - 아주 단순한 분기문과 반복문, 그리고 변수에 재할당이 동시 다발적으로 일어나는 함수 - 는 그 안에서 파악해야 하는 내용들이 많아짐에 따라서 복잡성이 증가합니다. 이런 함수들은 대체적으로 람다를 통해서 선언적 함수로 치환할 수 있습니다. 선언적 함수는 사람으로 하여금 함수의 역할을 더 잘 이해하게 만들어줍니다.
Stream.iterate(n, e-> e+1).filter(Sample::isPrime).limit(k).mapToDouble(Math::sqrt).sum() //isPrime은 소수인지 판단하는 함수
이 함수를 보면 stream api 를 인지하고 있을 때 n에서 1씩 증가하면서 소수만 걸러낸 후에 k개까지만 해당 소수의 제곱근으로 변환한 다음에 합을 구한다. 라고 이해할 수 있습니다.
절차지향적이라면
double result = 0;
int index = n;
int count = 0;
while(count < k){
if(isPrime(index)){
result+= Math.sqrt(index);
count++;
}
index++;
}
return result;
이렇게 표현할 수 있을 것 같습니다. 이걸 읽으려면 세가지 변수를 우선 머리속에 입력한 다음에, 어떤 상황에서 어떻게 변하는지 하나하나 다 파악해야 합니다.
똑똑한 코드를 멀리하라
똑똑한 코드란, 코드를 본 후에 설명을 듣고는 ‘이 함수가 이런 것을 하는 함수라고?’ 100이면 100 다 놀라는 코드입니다. 이런 함수를 작성하는 이유는 순전히 자기 만족입니다. 이런 코드는 시간이 지나고 언젠가 본인의 뒤통수를 칠겁니다. 똑똑한 바보는 폭력적이고 복잡한 것을 만들어내지만 천재는 단순함을 만들어낸다는 말을 기억하십시오.
주석은 what 보다는 why를 설명하라
코드 품질이 높다면 해당 함수나 클래스가 무엇을 하는 것인지 설명하는 것은 일종의 중복 작업입니다. 무엇을 하는지는 코드 그 자체로 표현하고, 그 코드가 왜 존재하는지를 설명하는 게 더 중요합니다.
의미있는 이름을 부여하라
자녀의 이름을 지어주듯이 좋은 이름을 지어주십시오.
전략적 코드 리뷰
코드 리뷰를 하기 위해서 팀 전체가 방안에 들어가서 처음부터 코드를 보면서 리뷰하는 것은 악몽이나 다름이 없습니다. 코드 리뷰는 소규모로 진행하되, 테스트 코드부터 리뷰하세요. 테스트코드를 읽고 의도를 파악한 다음에 실제 코드를 읽으면서 그 의도가 표현되었는지, 혹은 놓친 게 없는지 확인하고, 필요하다면 리뷰어가 테스트 코드를 추가하는 방식으로 진행하면 코드 리뷰가 한결 수월해집니다.