본문 바로가기
책/클린코드

4. 주석

by 히포파타마스 2023. 6. 18.

주석

 

잘 달린 주석은 그 어떤 정보보다 유용하다. 경솔하고 근거 없는 주석은 코드를 
이해하기 어렵게 만든다 오래되고 조잡한 주석은 거짓과 잘못된 정보를 퍼뜨려 해악을미친다.

 

 

우리는 코드로 의도를 표현하지 못해, 그러니까 실패를 만회하기 위해 주석을 사용한다.

 

 

- 요약 -

주석을 사용하기보다는 코드를 사용해서 의도를 나타내는 것을 지향하자.

특히 주석은 유지보수가 쉽지 않기 때문에 메서드에 대한 설명을 단순 나열하는 주석은 피해야 한다.

되도록이면 코드로 표현할 수 없는 정보를 전달해야 할 때만 주석을 사용하자

 

 

 

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

댓글