티스토리 뷰

study/클린코드

5. 형식 맞추기

pansy0319 2021. 6. 6. 02:50
반응형

[클린코드 - http://www.yes24.com/Product/Goods/11681152]

 

  • 프로그래머라면 규칙을 정해 형식을 깔끔하게 맞춰 코드를 짜야 한다

 

형식을 맞추는 목적

  • 코드 형식은 의사소통의 일환이다
  • 의사소통은 전문 개발자의 일차적인 의무다

 

적절한 행 길이를 유지하라

  • 500줄을 넘지 않고 대부분 200줄 정도인 파일로도 커다란 시스템을 구축할 수 있다
  • 일반적으로 큰 파일보다 작은 파일이 이해하기 쉽다
  • 신문 기사처럼 작성하라
    • 이름은 간단하면서도 설명이 가능하게 짓는다
    • 소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명한다
    • 아래로 내려갈수록 의도를 세세하게 묘사한다
    • 마지막에는 가장 저차원 함수와 세부 내역이 나온다
  • 개념은 빈 행으로 분리하라
    • 각 행은 수식이나 절을 나타내고 이렬ㄴ의 행 묶음은 완결된 생각 하나를 표현하기 때문에 그 사이에 빈 행을 넣어 분리해야 마땅하다
    • 빈 행은 새로운 개념을 시작한다는 시각적 단서다
  • 세로 밀집도
    • 세로 밀집도는 연관성을 의미한다
    • 서로 밀접한 코드 행은 세로로 가까이 놓여야 한다는 뜻이다
  • 수직 거리
    • 서로 밀접한 개념은 세로로 가까이 둬야 한다
    • 타당한 근거가 없다면 서로 밀접한 개념은 한 파일에 속해야 마땅하다
      • protected 변수를 피해야 하는 이유 중 하나
    • 같은 파일에 속할 정도로 밀접한 두 개념은 세로 거리로 연관성을 표현한다
      • 연관성 : 한 개념을 이해하는데 다른 개념이 중요한 정도
      • 연관성이 깊은 두 개념이 멀리 떨어져 있으면 코드 읽기 힘들다
    • 변수 선언
      • 변수는 사용하는 위치에 최대한 가까이 선언한다
      • 루프를 제어하는 변수는 루프 문 내부에 선언한다
    • 인스턴스 변수
      • 인스턴스 변수는 클래스 맨 처음에 선언한다
      • C++에서는 모든 인스턴스 변수를 클래스 마지막에 선언한다는 가위규칙(scisors rule)을 적용하고
        자바에서는 보통 클래스 맨 처음에 인스턴스 변수를 선언한다
        => 제일 중요한건 잘 알려진 위치에 인스턴스 변수를 모은다는 사실이다
    • 종속 함수
      • 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치한다
      • 호출하는 함수를 호출되는 함수보다 먼저 배치한다
    • 개념적 유사성
      • 친화도가 높을수록 코드를 가까이 배치한다
      • 함수가 다른 함수를 호출해 생기는 직접적인 종속성
      • 변수와 그 변수를 사용하는 함수
      • 비슷한 동작을 수행하는 함수들 - 명명법이 똑같고 기본 기능이 유사하고 간단한 함수들
    • 세로 순서
      • 함수 호출 종속성은 아래 방향으로 유지한다
      • 호출되는 함수를 호출하는 함수보다 나중에 배치한다
      • 소스 코드 모듈이 고차원에서 저차원으로 자연스럽게 내려간다

 

가로 형식 맞추기

  • 프로젝트 7개의 통계를 내보니 20자에서 60자 사이인 행이 총 행 수의 40%에 달했다
  • 프로그래머는 명백하게 짧은 행을 선호한다
  • 120자 행 길이 제한을 권장
  • 가로 공백과 밀집도
    • 가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현한다
      • 할당 연산자 사이에는 공백
      • 함수 이름과 이어지는 괄호 사이에는 공백을 넣지 않음
      • 함수의 인수는 공백으로 분리
      • 연산자 우선순위 강조에도 활용 가능
  • 가로 정렬
    • 가로 정렬은 코드의 엉뚱한 부분을 강조해 진짜 의도가 가려진다
    • 정렬하지 않으면 오히려 중대한 결함을 찾기 쉽다
  • 들여쓰기
    • 계층에서 각 수준은 이름을 선언하는 범위이자 선언문과 실행문을 해석하는 범위다 
    • 범위(scope)로 이뤄진 계층을 표현하기 위해 코드를 들여쓴다
    • 들여쓰는 정도는 계층에서 코드가 자리잡은 수준에 비례한다
    • 들여쓰기 무시하기
      • 간단한 if 문, while 문, 짧은 함수도 들여쓰기를 잘 하자
      • 한 행에 범위를 뭉뚱거린 코드를 피하자
  • 가짜 범위
    • 빈 while 문이나 for 문을 쓸 때 세미콜론(;)은 새 행에다 제대로 들여써서 넣어줘서 혼란을 피한다

 

팀 규칙

  • 팀은 한 가지 규칙에 합의해야 하고 모든 팀원은 그 규칙을 따라야 한다
  • 소프트웨어가 일관적인 스타일을 보여야 한다
  • 좋은 소프트웨어는 읽기 쉬운 문서로 이뤄진다
  • 스타일은 일관적이고 매끄러워야 한다

 

밥 아저씨의 형식 규칙

(예제 코드가 완전 깔끔 그 자체. 참고하기 위해 여기도 타이핑해놓았다)

public class CodeAnalyzer implements JavaFileAnalysis {
	public int lineCount;
    private int maxLineWidth;
    private int widestLineNumber;
    private LineWidthHistogram lineWidthHistogram;
    private int totalChars;
    
    public CodeAnalyzer() {
    	lineWidthHistogram = new LineWidthHistogram;
    }
    
    public static List<File> findJavaFiels(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) throw Exception {
    	BuffredReader 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 getLinedWidthHistogram() {
		retun 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 Interger[0]));
        Arrays.sort(sortedWidth);
        return sortedWidths;
    }
}
반응형

'study > 클린코드' 카테고리의 다른 글

7. 오류 처리  (0) 2021.06.10
6. 객체와 자료 구조  (0) 2021.06.06
4. 주석  (0) 2021.06.02
3. 함수  (0) 2021.06.01
2. 의미 있는 이름  (0) 2021.05.26
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함