개발자는 매번 끊임없이 자기 자신에게 과연 "무엇이 좋은 코드일까?"라는 물음표를 던진다.
개발자라면 회사에서 코딩을 하고나서 회의에서 다른 사람들 앞에서 자신이 짠 코드 리뷰를 하면서 설명하고 업무를 진행한다. 코드 리뷰를 하지 않는 회사도 있지만 대개는 코드 리뷰를 진행하여 코드 품질을 높이려고한다.
하지만 여러사람들의 의견을 나누다보면 팀원, 팀장조차도 "애매하다", "모르겠다" 등 미온적인 태도를 갖는 것을 볼 수 있다. 과연 왜 이런 태도를 갖게 되는 것일까?
왜 코드 리뷰때마다 "애매하다"고 말하는 것인가?
정말 여러 방향의 길이 있고 패턴이 있다면 "정답"이란 것을 명확히 표현할 수 없기때문에 이렇게 말하는 경우도 있다.
이럴 경우라면 다행이겠지만 정말 자신이 작성한 코드에 대해서 코드 자체가 잘 작성했는지 몰라서 "애매하다" 라고 얘기했다면 이거는 큰 문제이며 코드에 대해 무엇이 맞고 틀린지 자신감과 지식이 부족해서라고 봐도 무방할 것이다.
좋은 코드란?
과연 무엇이 좋은 코드라고 우리는 얘기할 수 있을까? 몇가지 간단한 예시를 들어보도록 한다.
1. 코드는 읽기 쉬워야 한다.
아래 예시는 보자마자 알겠지만 연산의 우선순위 보는 가독성이 매우 떨어진다.
# Bad
a = b + c - d / e
# Good
result = (b + c - d) / e
함수안에 여러일을 할 필요는 없다. 하나의 함수에는 단일 업무만 수행해야한다.
# Bad
def calculate_and_display_result(x, y, z):
result = x + y * z
print(f"The result is: {result}")
# Good
def perform_calculation(x, y, z):
return x + y * z
# Good
def display_result(result):
print(f"The result is: {result}")
2. 코드는 예측 가능해야 한다.
add_numbers의 함수의 시그니처만 봐도 두개의 인자값을 받아서 더하는 함수라는 것을 추측할 수 있다.
하지만 some_numbers는 추상적일뿐만 아니라 안의 본문까지 모두 살펴봐야 코드 내용을 추측할 수 있다.
# Bad
def some_numbers(a, b):
return a * b
# Good
def add_numbers(a, b):
return a + b
3. 코드는 오용하기 어려워야한다.
예를 들어 TV 뒷면을 보면 전원, HDMI 소켓 구멍이 다르기때문에 맞지 않아서 잘못 사용할 수 없다.
이런 예처럼 코드도 잘못 사용하지 못하도록 오용을 하지 않도록 클래스명, 함수명을 정확히 명시하여 오용을 피해야한다.
4. 코드를 모듈화한다.
# Bad
def complex_algorithm(input_data):
# ...
# Good
class Algorithm(object):
def calculate_data(self, data):
# ...
def apply_algorithm(self, data):
# ..
5. 코드를 재사용 가능하고 일반화한다.
# Bad
# 특정한 상황에서만 사용 가능한 코드
def calculate_circle_area(radius):
# ...
# Good
# 일반적으로 사용 가능한 코드
def calculate_area(shape, dimensions):
# ...
6. 테스트가 용이해야한다.
위에서 연결된 부분이긴하지만 하나의 함수에 여러가지 업무를 수행해버리면 아래처럼 단위 테스트에 어려움이 있다.
# Bad
# 테스트하기 어려운 함수
def complex_function(data):
# ...
# Good
# 테스트하기 쉬운 함수
def simple_function(data):
# ...