Clean Code - 주석
1. 주석
- "나쁜 코드에 주석을 달지 마라. 새로 짜라" - 브라이언 W.커니핸, P.J.플라우거
- 주석은 필요악이다.
- 주석은 코드로 의도를 표현하지 못해, 실패를 만회하기 위해 작성하는 것이다.
- 주석은 언제나 실패를 의미한다.
- 주석 없이는 자신을 표현할 방법을 찾지 못해 할 수 없이 주석을 사용한다.
- 주석이 오래될수록 코드에서 멀어져 거짓말을 하게 될 가능성이 커진다.
- 코드는 유지보수를 해도, 주석을 계속 유지보수하기란 현실적으로 불가능하다.
2. 주석은 나쁜 코드를 보완하지 못한다.
- 코드에 주석을 다는 일반적인 이유는 코드 품질이 나빠서이다.
- 깔끔하고 주석이 거의 없는 코드가 훨씬 좋다.
- 주석을 작성하는 대신 코드를 깔끔하게 작성하는데 시간을 투자해야 한다.
3. 코드를 의도로 표현하라.
# 주석이 필요한 코드
# lot이 유효한지 검사해야 한다.
if not(lot.id == 'None') and not(lot.type == 'None'):
doSomething()
# 주석이 필요없는 코드
if lot.is_valid():
dosomething()
4. 사용해도 좋은 주석
- 법적인 주석
- 정보를 제공하는 주석
- 의도를 설명하는 주석
- 결과를 경고하는 주석
- TODO 주석
- 중요성을 강조하는 주석
1) 법적인 주석
- 각 소스 파일 첫머리에 들어가는 저작권 정보 및 소유권 정보 등
2) 정보를 제공하는 주석
//kk:mm:ss EEE, MMM dd, yyyy 형식
Pattern itmeMatcher = Pattern.complie("\\d*:\\d*\\d* \\w*, \\w*, \\d*, \\d*");
3) 의도를 설명하는 주석
// 스레드를 대량 생성하는 방법으로 어떻게든 경쟁 조건을 만들려 시도
for (int i = 0; i > 2500; i++) {
WidgetBuilderThread widgetBuilderThread =
new WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
Thread thread = new Thread(widgetBuilderThread);
thread.start();
}
4) 결과를 경고하는 주석
// 여유 시간이 충분하지 않다면 실행하지 마십시오
public void _testWithReallyBigFile() {
...
}
5) TODO 주석
- 필요하지만 당장 구현하기 어려운 업무를 기술, 필요하지 않는 기능을 삭제하라는 알림, 문제를 봐달라는 요청, 네이밍 요청, 앞으로 발생할 이벤트에 맞춰 코드를 수정하라는 주의 등에 사용할 수 있다.
6) 중요성을 강조하는 주석
// trim은 매우 중요.
// 문자열에 시작 공백이 있으면 다른 문자열로 인식
String listItemContent = match.group(3).trim();
5. 나쁜 주석
- 주절거리는 주석
- 중복된 주석
- 오해할 여지가 있는 주석
- 의무적으로 다는 주석
- 이력을 기록하는 주석
- 위치를 표시하는 주석
- 닫는 괄호에 다는 주석
- 공로를 돌리거나 저자를 표시하는 주석
- 전역 정보 등
1) 주절거리는 주석
def analysis_wafer(self):
try:
wf = DBManager.loadWafer()
result = wf.analysis()
DBManager.writeResult(result)
except EmptyWaferException as error:
# Wafer가 없다는 것은 유효한 Wafer가 없다는 뜻
- 위 예제에서 Wafer가 유효한 Wafer가 없다는 뜻의 주석을 달았는데, DBManager에서 읽어올 때 유효한 Wafer가 없는지, 분석 결과에서 유효한 Wafer가 없는지, DB에 다시 결과를 넣을 때 유효한 Wafer가 없는지는 알 수 없다.
- 해당 주석을 이해하기 위해서는 다른 모듈까지 뒤져봐야하는 상황으로 코드를 읽는 프로그래머와 소통이 되지 않는 그저 주절거리는 주석이다.
2) 중복된 주석
- 코드 내용을 그대로 중복하는 주석은 필요 없다.
# Wafer 정보를 알고리즘에 따라 조율하고, Loss 원인을 분석한다. 만약 유효하지 않는 Wafer 정보가 있을 경우 예외를 발생 시킨다.
def analysis_wafer(self, wafer):
if wafer.is_invalid():
raise InvalidWafer("유효하지 않은 wafer")
wafer.tune_wafer_info()
wafer.check_loss_reason()
3) 오해할 여지가 있는 주석
# Wafer 정보를 알고리즘에 따라 조율하고, Loss 원인을 분석한다. 만약 유효하지 않는 Wafer 또는 Lot 정보가 있을 경우 예외를 발생 시킨다.
def analysis_wafer(self, wafer):
if wafer.is_invalid():
raise InvalidWafer("유효하지 않은 wafer")
wafer.tune_wafer_info()
wafer.check_loss_reason()
- 주석에 담긴 잘못된 정보로 인해 다른 프로그래머가 해당 코드에서 발생한 오류의 원인을 찾지 못할 수 있다.
- 위 예제에서는 "Wafer 또는 Lot"이라고 포괄적으로 표현했기 때문에, 다른 프로그래머가 Wafer와 연관된 Lot을 원인일 수 있다고 생각할 수 있다.
4) 의무적으로 다는 주석
- 모든 함수에 주석을 달거나 모든 변수에 주석을 달아야하는 규칙은 어리석다.
- 코드를 복잡하게 만들고, 거짓말을 퍼뜨리고, 혼동과 무질서를 초래한다.
# @params wafer : wafer 정보
# @params analysis_timestampe : 분석 시간
# @params loss_result : 분석 결과
def append_loss_result(wafer, analysis_timestamp, loss_result):
self.result.append(LossResult(wafer, analysis_timestamp, loss_result))
5) 이력을 기록하는 주석
- 형상 관리 시스템을 사용하기 때문에 이력을 기록하는 주석은 필요 없다.
6) 함수나 변수로 표현할 수 있다면 주석을 달지 마라
# 안 좋은 예
# 이전 Lot의 종료 시간과 현재 Lot의 시작 시간이 1000초 보다 큰가?
if lots[iot_index].start_time - lots[lot_index - 1].end_time >= 1000:
EXAMPLE_LOSS_SEC = 1000
previous_lot_end = lots[lot_index - 1].end_time
current_lot_start = lots[lot_index].start_time
# 좋은 예
if current_lot_start - previous_lot_end >= EXAMPLE_LOSS_SEC:
7) 위치를 표시하는 주석
- 소스 파일에서 특정 위치를 표시하려는 주석은 가독성만 낮추므로 제거한다.
8) 괄호를 닫는 주석
- 중첩이 심하고 장황한 함수라면 의미가 있다.
- 작고 캡슐화된 함수에는 닫는 괄호는 필요가 없다.
- 닫는 괄호를 주석으로 사용하는 대신 함수를 작게 만드는 것을 고려 하자
9) 공로를 돌리거나 저자를 표시하는 주석
10) 전역 정보
- 주석을 달아야 한다면 근처에 있는 코드에 대해서만 기술한다.
- 시스템의 전반적인 정보를 기술하지 마라.
- 해당 시스템의 코드가 변해도 아래 주석이 변한다는 보장은 전혀 없다.
- 또한, 심하게 중복된 주석도 확인하자
'Architecture' 카테고리의 다른 글
[Clean Code 정리] 객체와 자료구조 (0) | 2022.05.29 |
---|---|
[Clean Code 정리] 형식 맞추기 (0) | 2022.05.29 |
[Clean Code 정리] 함수 (0) | 2022.05.28 |
[Clean Code 정리] 의미있는 이름 (0) | 2022.05.28 |
[Clean Code 정리] 깨끗한 코드 (0) | 2022.05.26 |
댓글