[CleanCode] -5. 형식 맞추기

Young Min Sim ·2021년 4월 14일
0

CleanCode

목록 보기
5/16

💁🏻‍♂️ 컨벤션

형식을 맞추는 목적

  • 오랜 시간이 지나 원래 코드의 흔적을 더 이상 찾아보기 어려울 정도로 코드가 바뀌어도
    맨 처음 잡아놓은 구현 스타일과 가독성 수준유지보수 용이성과 확장성에 계속 영향을 미친다.

👮🏻‍♂️ 권장하는 규칙

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

  • JUnit, FitNesse 등은 500줄을 넘어가는 파일이 없으며 대다수가 200줄 미만이다.
    200줄 미만으로도 커다란 시스템을 구축할 수 있다.
  • 일반적으로 큰 파일보다 작은 파일이 이해하기 쉽다.

    책에서 예시를 드는 프로젝트들은 테스트와 관련된 파일들로 보입니다.
    실제 프로그래밍을 하다 보면 200줄 미만으로 작성한다는게
    현실적으로 어렵고 억지로 줄이려고 파일을 나누는 건 오히려 비효율적일 때도 있다고 생각합니다.

    가독성을 해치지 않는 선에서
    가능한 파일을 작게 분리하는게 좋다는 것을 강조하는 뜻으로 보면 될 것 같습니다.

  • 신문 기사처럼 작성하라
    • 신문에서 기사를 요약하는 제목 -> 구체적인 내용으로 가는 것처럼,
    • 위에서 아래로 내려갈 수록 구체적으로 작성한다. (추상화 수준 ⬆️ -> ⬇️)
  • 개념은 빈 행으로 분리하라
    • 빈 행은 새로운 개념을 시작한다는 시각적 단서
  [빈 행 X]
  import Foundation
  class Model {
  	...
  }
  
  
  [빈 행 O]
  import Foundation
  
  class Model {
  	...
  }  
  • 세로 밀집
    • 빈 행이 개념을 분리한다면 세로 밀집도는 연관성을 의미한다
    • 연관 있는 개념끼리는 밀집
  [밀집 X]
  class Model {
     private var topConstraint: NSLayoutConstraint!
     
     private var bottomConstraint: NSLayoutConstraint!
  }
  
  
  [밀집 O]
  class Model {
     private var topConstraint: NSLayoutConstraint!
     private var bottomConstraint: NSLayoutConstraint!
  }

이 개념을 알지 못하더라도 본능적으로 불편함을 유발하는 부분이 아닐까 생각합니다

  • 수직 거리

    • 지역 변수는 사용하는 위치에 최대한 가까이 선언한다.
    • 인스턴스 변수는 클래스 맨 처음
    • 종속 함수는 세로로 가까이 배치한다.
      가능하다면 위에서 (아래로 읽는 규칙을 적용하여) 호출하는 함수를 호출되는 함수보다 먼저 배치한다.
    • 개념적 유사성: 꼭 종속 관계가 아니더라도 (테스트 할 때 assert- 같이) 개념적으로 유사한 함수들은 가까이 배치할 함수들

    결국 일관성에 관한 이야기.
    이렇게 일관성 있게 코드를 작성하면 유추가 가능해지는게 가장 큰 장점이라고 생각합니다.

    일관성 있는 코드를 읽다 보면 아 이 함수는 밑에서 나오겠구나 유추가 되고
    혹은 밑에 나오지 않는 경우 해당 함수가 가지는 어떠한 특수성으로 인해 다른 곳에 위치해있겠구나 등 굳이 찾아보지 않아도 유추가 가능해집니다.

  • 가로 형식 맞추기

    • 가급적이면 120자 정도로 행길이 제한
  • 들여쓰기

    • 간단한 함수라도 들여쓰기
  func emptyString() { return "" }

보다는,

  func emptyString() {
     return ""
  }

2. 밥 아저씨의 형식 규칙

public class CodeAnalyzer implements JavaFileAnalysis {
    private int lineCount;
    private int maxLineWidth;
    private int widestLineNumber;
    private LineWidthHistogram lineWidthHistogram;
    private int totalChars;

    public CodeAnalyzer() {
        lineWidthHistogram = new LineWidthHistogram();
    }

    public static List<File> findJavaFiles(File parentDirectory) {
        List<File> files = new ArrayList<File>();
        findJavaFiles(parentDirectory, files);
        return files;
    }

    private static void findJavaFiles(File parentDirectory, List<File> files) {
        for (File file : parentDirectory.listFiles()) {
            if (file.getName().endsWith(".java"))
                files.add(file);
            else if (file.isDirectory())
                findJavaFiles(file, files);
        }
    }

    public void analyzeFile(File javaFile) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(javaFile));
        String line;
        while ((line = br.readLine()) != null)
            measureLine(line);
    }

    private void measureLine(String line) {
        lineCount++;
        int lineSize = line.length();
        totalChars += lineSize;
        lineWidthHistogram.addLine(lineSize, lineCount);
        recordWidestLine(lineSize);
    }

    private void recordWidestLine(int lineSize) {
        if (lineSize > maxLineWidth) {
            maxLineWidth = lineSize;
            widestLineNumber = lineCount;
        }
    }

    public int getLineCount() {
        return lineCount;
    }

    public int getMaxLineWidth() {
        return maxLineWidth;
    }

    public int getWidestLineNumber() {
        return widestLineNumber;
    }

    public LineWidthHistogram getLineWidthHistogram() {
        return lineWidthHistogram;
    }

    public double getMeanLineWidth() {
        return (double)totalChars/lineCount;
    }

    public int getMedianLineWidth() {
        Integer[] sortedWidths = getSortedWidths();
        int cumulativeLineCount = 0;
        for (int width : sortedWidths) {
            cumulativeLineCount += lineCountForWidth(width);
            if (cumulativeLineCount > lineCount/2)
                return width;
        }
        throw new Error("Cannot get here");
    }

    private int lineCountForWidth(int width) {
        return lineWidthHistogram.getLinesforWidth(width).size();
    }

    private Integer[] getSortedWidths() {
        Set<Integer> widths = lineWidthHistogram.getWidths();
        Integer[] sortedWidths = (widths.toArray(new Integer[0]));
        Arrays.sort(sortedWidths);
        return sortedWidths;
    }
}
  • 위에서 아래로 글을 읽을 수 있도록
  • 개념적으로 밀접한 것은 가깝게, 먼 것은 멀게

0개의 댓글