본문 바로가기
Clean Code

[클린 코드] 5장 - 형식 맞추기 (Formatting)

by 노력남자 2022. 3. 1.
반응형

이번 포스팅에선 클린 코드 5장 - 형식 맞추기에 대해 알아보겠습니다.

 

왜 형식을 맞춰야 할까?

 

1장에서 우리는 저자라고 했습니다.

 

독자가 읽고 수정하기 편하도록 할 의무가 있습니다.

 

public List<Cell> getFlaggedCells() { List<Cell> flaggedCells = new ArrayList();
    for (Cell cell : gameBoard) if (cell.isFlagged()) flaggedCells.add(cell);return flaggedCells;}

 

위하고 아래 코드 둘 중 어떤 게 잘 읽히나요? 당연히 아래입니다. 

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList();

    for (Cell cell : gameBoard)
        if (cell.isFlagged())
            flaggedCells.add(cell);

    return flaggedCells
}

 

항상 동일한 형식의 코드를 짤 수 있게 하는 게 중요합니다.

 

팀 프로젝트면 팀원과 정한 형식

 

개인 프로젝트면 개인이 정한 형식

 

어떤 소스에선 a 형식으로, 어떤 소스에선 b 형식으로 짜게 되면 소스 읽는데 엄청 어려움이 생깁니다.

 

사람이 코드를 이해하는데 코드의 구조, 형식이 익숙할수록 도움이 된다고 합니다.

 

그럼 어떤 형식으로 짜야 좋을지 알아보겠습니다.

 

좋은 코드 형식 (세로)

 

1. 적절한 행 길이를 유지하라!

 

JUnit, testNG 등 큰 프로젝트들도 하나의 클래스가 

 

대부분 200 줄을 넘지 않는다고 합니다. 제일 긴 파일은 400줄 정도?

 

그럼 여기서 알 수 있는 부분은 엄청 큰 프로젝트라도 하나의 클래스 파일 길이가 200줄 정도여도 충분히 개발 가능하다입니다.

 

클래스 길이가 길면 길수록 이해가 어렵기 때문에 짧게 짤려고 노력하자. (200줄 미만으로)

 

 

2. 신문 기사처럼 작성하라!

 

신문 기사를 보면 헤더 - 전체 요약문 - 본문이 나오듯이

 

소스 코드도 가장 중요하고 대표가 될만한 부분부터 위에서 차근차근 정리하자.

 

가장 대표가 될만한 소스 코드가 중간에 있으면 소스를 이해하는 게 정말 어렵다.

 

 

3. 개념은 빈 행으로 분리하라!

 

글에 문단이 있듯이 코드에는 빈 행이 있다.

 

아래 소스코드를 보면 다 따닥따닥 붙어있어서 잘 안 읽힌다.

 

엄청 간단한 소스인데 이정도다.

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList();
    for (Cell cell : gameBoard)
        if (cell.isFlagged())
            flaggedCells.add(cell);
    return flaggedCells;
}

 

아래처럼 변수는 변수끼리 로직은 로직끼리 (로직 내에서도 다른 개념이면 빈 행으로!) 반환은 반환만 따로 구분해주니 아주 읽기가 편해졌다.

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList(); // 변수

    for (Cell cell : gameBoard) // for 문
        if (cell.isFlagged())
            flaggedCells.add(cell);

    return flaggedCells; // 반환
}

 

 

4. 세로 밀집도

 

개념을 빈행으로 구분했다면 세로 밀집도는 연관성을 의미한다!

 

아래 처럼 변수가 for문 로직 위에 붙어있다.

 

뭔가 보기 껄끄럽지 않나? 변수는 변수끼리 붙어있었으면 좋겠다는 생각이 든다.

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList(); 
    
    List<Cell> dummyCells = new ArrayList();
    for (Cell cell : gameBoard)
        if (cell.isFlagged())
            flaggedCells.add(cell);
            dummyCells.add(cell);
            
    return flaggedCells;
}

 

아래 코드처럼 변경하니 마음이 편해졌다.

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList(); 
    List<Cell> dummyCells = new ArrayList();
    
    for (Cell cell : gameBoard)
        if (cell.isFlagged())
            flaggedCells.add(cell);
            dummyCells.add(cell);
            
    return flaggedCells;
}

 

 

5. 코드 순서

 

클래스 내에 아래와 같은 순서로 코드를 작성하자.

 

1) static 변수 : public -> protected -> package -> private

2) instance 변수 : public -> protected -> package -> private

3) 생성자

4) 메서드 : (public -> private -> private) -> (public -> private -> private)...

 

public 메서드에서 호출되는 private 메서드는 바로 아래에 둔다.

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList();

    addFlaggedCells(flaggedCells);

    return flaggedCells;
}

private void addFlaggedCells(List<Cell> flaggedCells) {
    for (Cell cell : gameBoard)
        if (cell.isFlagged())
            flaggedCells.add(cell);
}

 

좋은 코드 형식 (가로)

 

 

1. 가로 길이를 길게 하지말자!

 

가로 길이가 도대체 얼마가 긴 걸까?

 

인텔리제이를 켜서 클래스를 만들어보자

 

그럼 아래와 같이 선이 보이는데 저기까지 문자가 120글자가 들어갑니다.

 

 

120글자를 빽빽하게 항상 코드를 작성하라는 게 아니라 최대한 저기는 넘지 말자라는 의미입니다.

 

길면 길수록 이해가 안 가니 되도록이면 짧게 작성합시다.

 

 

2. 공백을 잘 넣자!

 

아래와 같이

 

=, : 양 옆에 공백이 없고

 

함수 호출 부분에 공백이 있고 예) cell .isFlagged()

 

보기가 어렵고 소스가 깔끔해 보이지 않는다.

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells=new ArrayList();

    for (Cell cell:gameBoard)
        if (cell .isFlagged())
            flaggedCells .add(cell);

    return flaggedCells;
}

 

공백을 잘 쓰자.

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList();

    for (Cell cell : gameBoard)
        if (cell.isFlagged())
            flaggedCells.add(cell);

    return flaggedCells;
}

 

 

3. 정렬을 하지 말아라!

 

가장 긴 변수랑 뭔가 맞춰볼려고 아래처럼 정렬을 한다면 그건 잘못된 생각이다.

 

아래처럼쓰면 어떤 값을 넣는지 솔직히 잘 안 보이고 변수명만 보인다.

 

context =                 context;
socket =                  s;
requestParsingTimeLimit = 10000;

 

아래와 같이 쓰자.

 

context = context;
socket = s;
requestParsingTimeLimit = 10000;

 

 

4. 들여쓰기를 잘하자!

 

아래처럼 들여쓰기를 안 하고 그냥 엔터만 치면서 코드를 짜면 보기가 불편하다.

 

public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells=new ArrayList();

for (Cell cell:gameBoard)
if (cell .isFlagged())
flaggedCells .add(cell);

return flaggedCells;
}

 

아래처럼 각 로직에 맞게 들여쓰기를 잘 쓰자!

 

public List<Cell> getFlaggedCells() {
    List<Cell> flaggedCells = new ArrayList();

    for (Cell cell : gameBoard)
        if (cell.isFlagged()) // for문 안이니까 들여쓰기 +1
            flaggedCells.add(cell); // if문 안이니까 들여쓰기 +2

    return flaggedCells;
}

 

팀 코딩 컨벤션

 

위에 소개한 좋은 형식들도 중요하지만 가장 중요한 건 같이 일하는 팀원과 정한 코딩 컨벤션이다.

 

아래 유명한 컨벤션 가이드를 참고해서 팀원들과 잘 형식을 정해보자.

 

구글 java 컨벤션 : https://google.github.io/styleguide/javaguide.html

네이버 java 컨벤션 : https://naver.github.io/hackday-conventions-java/

 

 

개발자 나름 선호하는 코딩 컨벤션이 틀리기 때문에 위에 설명한 내용이 맘에 안 들 수 있습니다.

 

각자 열심히 개발하면서 보기 좋다고 생각되는 형식이 있기 때문이죠.

 

다른 사람들과 형식이 다르다면 너무 고집하지말고 같이 얘기하면서 뭐가 좋은지 잘 느껴보고 적용하는 게 중요합니다.

 

 

반응형

댓글