주석
잘 달린 주석은 그 어떤 정보보다 유용하다. 경솔하고 근거 없는 주석은 코드를
이해하기 어렵게 만든다 오래되고 조잡한 주석은 거짓과 잘못된 정보를 퍼뜨려 해악을미친다.
우리는 코드로 의도를 표현하지 못해, 그러니까 실패를 만회하기 위해 주석을 사용한다.
- 요약 -
주석을 사용하기보다는 코드를 사용해서 의도를 나타내는 것을 지향하자.
특히 주석은 유지보수가 쉽지 않기 때문에 메서드에 대한 설명을 단순 나열하는 주석은 피해야 한다.
되도록이면 코드로 표현할 수 없는 정보를 전달해야 할 때만 주석을 사용하자
1. 주석을 사용할만한 경우
1.1 직관적이지 않은 정보를 전달할 때
코드를 작성할 때 표현식이라던지, 외부 라이브러리에 의해 코드를 직관적으로 해석하기 어려울 때가 있다.
이럴 때, 주석을 통해 해당 코드가 내포하고 있는 정보를 표현해 줄 수 있다.
[파악하기 어려운 정보의 주석]
//1시간마다 실행
//cron = 초 분 시 월 요일
@Scheduled(cron = "0 0 0/1 * * ?")
public void scheduleCache() {
cacheProcessor.updateViewToMySql();
cacheProcessor.flushRedis();
}
@Scheduled에 사용된 표현식이다.
해당 표현식을 잘 모른다면 scheduledChache()라는 메서드가 언제 실행되는지 사용된 표현식이 무엇을 의미하는지를 한눈에 파악하기 어렵다. 때문에 주석을 통해 이를 표현해 주는 것이 적절할 수 있다.
1.2 경고, 주의를 표시하는 경우
로직의 흐름이나 역할, 의도 같은 경우는 코드로 표현할 수 있지만, 경고나 주의사항 같은 경우는 코드로 온전히 표현하기 어려운 부분이 있다. 이런 경우 주석을 사용할 수 있다.
ex) 메서드를 사용했을 때 발생할 수 있는 파급 효과
서비스 구조상 발생할 수 있는 사항들
1.3 의미를 갖는 수식이나 코드로 표현하기 어려운 로직
알고리즘 형식의 코드는 수식이나 변수의 사용에 알고리즘에 따른 의미가 존재한다.
주석을 사용해서 이런 알고리즘 형식에 담긴 정보를 좀 더 파악하기 쉽게 표현할 수 있다.
[알고리즘 형식의 코드에서 주석 사용]
private static ArrayList<Integer> topologySort(Node[] nodeArr) {
//위상정렬된 값들이 들어갈 리스트
ArrayList<Integer> sortResult = new ArrayList<>();
Queue<Node> queue = new LinkedList<>();
//queue에 초기값으로 노드방향 간선 수가 0인 값들을 넣는다.
for (int i = 1; i < nodeArr.length; i++) {
if (nodeArr[i].linkEdge == 0) {
queue.offer(nodeArr[i]);
sortResult.add(nodeArr[i].number);
}
}
while (!queue.isEmpty()) {
Node node = queue.poll();
//반복문을 돌면서 node와 연결된 간선을 지운다.
//간선을 지운다 = 간선으로 이어진 node의 linkEdge(진입차수)에서 1을 빼줌
for (int i = 0; i < node.edge.size(); i++) {
Node linkNode = node.edge.get(i);
linkNode.linkEdge--;
if (linkNode.linkEdge == 0) {
queue.offer(linkNode);
sortResult.add(linkNode.number);
}
}
}
return sortResult;
}
메서드 명을 통해 위상정렬을 하는 것을 알 수 있지만 세부적으로 어떤 절차와 방식을 사용하는지 표현하기 위해 주석을 사용하였다.
주석을 통해 전체적인 코드의 흐름과 의미를 좀 더 쉽게 파악할 수 있다.
2. 지양해야 하는 주석 형식
2.1 나만 알아볼 수 있는 주석
주석을 메모장처럼 사용하여 그 당시의 내 생각을 적어놓는 경우가 있다.
이런 주석은 나중에 볼 때 나 자신도 무슨 뜻인지 알기 어렵고 다른 사람은 더더욱 그 의미를 파악할 수 없다.
2.2 메서드 로직을 설명하는 주석
메서드가 무슨 역할을 하고 어떻게 동작하는지를 주석으로 적는 경우가 있다.
[메서드의 내용을 단순 설명하는 주석]
//accountid를 받아서 해당 acount의 모든 boards를 redis에서 삭제 하는 메서드
private void removeBoardsFromRedis(Long accountId, String keyName) {
List<Board> boards = boardRepository.findByAccountId(accountId);
ValueOperations<String, String> valueOperations = redisTemplate.opsForValue();
for (Board board : boards) {
String key = keyName + "::" + board.getId();
if (valueOperations.get(key) != null) {
redisTemplate.delete(key);
}
}
}
이는 메서드의 내용을 그저 중복해서 언급하는 것밖에 되지 않는다
이런 주석을 적는 이유는 자신이 만든 메서드를 다른 사람이 쉽게 파악할 수 없다는 생각이 깔려있기 때문이다.
이는 표현에 실패한 메서드임을 나타낸다. 이런 경우에는 좀 더 의도와 역할이 명확히 파악될 수 있도록 메서드를 작성해 보자
2.3 위치를 표현하는 주석
특정 코드 구문이나 변수의 위치를 표현하기 위해 주석을 사용하는 경우가 있다.
[특정 부분을 강조하는 주석]
public static void main(String[] args) {
//**** 초기화 시작
Scanner scanner = new Scanner(System.in);
int colSize = scanner.nextInt();
int rowSize = scanner.nextInt();
Tomato[][] tomatoes = new Tomato[rowSize][colSize];
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
tomatoes[i][j] = new Tomato(i, j, scanner.nextInt());
}
}
//**** 초기화 끝
.
.
.
.
}
전형적인 의미 없는 주석이다.
이런 경우는 차라리 메서드를 사용해서 표현하는 것이 더 나은 방법이 될 수 있다.
[특정 부분을 강조하는 주석 개선]
public static void main(String[] args) {
Tomato[][] tomatoes = initTomatoes();
.
.
.
}
private static Tomato[][] initTomatoes() {
Scanner scanner = new Scanner(System.in);
int colSize = scanner.nextInt();
int rowSize = scanner.nextInt();
Tomato[][] tomatoes = new Tomato[rowSize][colSize];
for (int i = 0; i < rowSize; i++) {
for (int j = 0; j < colSize; j++) {
tomatoes[i][j] = new Tomato(i, j, scanner.nextInt());
}
}
return tomatoes;
}
2.4 모호한 주석
애매한 정보를 전달하는 주석은 없는 것이 더 낫다
주석이 있는 경우 보통은 주석을 먼저 파악하고 코드를 분석한다.
때문에 오해할 수 있는 정보를 주석에 작성하면 코드가 의도와는 다르게 분석될 수 있다.
2.5 외부 변수를 언급하는 주석
주석이 적용된 부분에 전혀 사용되지 않는 변수나 메서드, 클래스의 내용을 언급하는 것을 지양해야 한다.
이런 경우는 주석을 읽는 사람이언급된 외부 변수를 파악하기 위해 코드를 찾아봐야 할 수 도 있기 때문이다.
[외부 변수를 언급하는 주석]
//Board와 같은 방식으로 삭제됨
@Transactional
@CacheEvict(key = "#loginAccountId", value = {"findAccount", "findLoginAccount"})
public void removeAccount(Long loginAccountId) {
removeBoardsFromRedis(loginAccountId, "findBoard");
removeBoardsFromRedis(loginAccountId, "boardView");
try {
likesRepository.deleteByAccountId(loginAccountId);
commentRepository.deleteByAccountId(loginAccountId);
boardPhotoRepository.deleteByAccountId(loginAccountId);
boardTagRepository.deleteByAccountId(loginAccountId);
boardRepository.deleteByAccountId(loginAccountId);
followRepository.deleteByAccountId(loginAccountId);
accountRepository.deleteById(loginAccountId);
} catch (Exception e) {
throw new BusinessLogicException(ExceptionCode.FAIL_REMOVE_ACCOUNT);
}
}
Account를 삭제하는 메서드인데 주석에서는 메서드에서 사용되지 않는 Board라는 엔티티를 언급한다.
주석을 읽는 사람은 Board를 삭제한 방식을 파악하기 위해 코드를 뒤져야 하는 번거로움을 겪을 수 있다.
'책 > 클린코드' 카테고리의 다른 글
9. 단위 테스트 (0) | 2023.06.23 |
---|---|
6. 객체와 자료 구조 (0) | 2023.06.18 |
5. 형식 맞추기 (0) | 2023.06.18 |
댓글