티스토리 뷰

반응형


| 5. 형식 맞추기


--


|| 형식을 맞추는 목적


-

- 코드 형식은 중요하다. 코드 형식은 의사소통의 일환이다.

- 오늘 구현한 코드의 가독성은 앞으로 바뀔 코드의 품질에 지대한 영향을 미친다..



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


-

- 적은 행 길이로도 커다란 시스템을 구축할 수 있다.

- 일반적으로 큰 파일보다 작은 파일이 이해하기 쉽다.


||| 신문 기사처럼 작성하라.


- 소스 파일도 신문 기사와 비슷하게 작성하자. 이름은 간단하면서도 설명이 가능하게 짓는다.

- 소스 파일 첫 부분은 고차원 개념과 알고리즘을 설명한다. 아래로 내려갈수록 의도를 세세하게 묘사.

  마지막에는 가장 저차원 함수와 세부 내역

- 가장 중요한 개념을 가장 먼저 표현


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


- 빈 행은 새로운 개념을 시작한다는 시각적 단서이다.


||| 세로 밀집도


- 서로 밀접한 코드 행은 세로로 가까이 놓아야 한다.

1
2
3
4
5
6
7
public class ReporterConfig {
    private String className;
    private List<Property> properties = new ArrayList<Property>();
    public void addProperty(Property property) {
        properties.add(property);
    }
}
cs


||| 수직 거리


- 서로 밀접한 개념은 한 파일에 속해야 찾기 쉽다.

- 밀접한 두 개념은 세로 거리로 연관성을 표현한다.


> 변수 선언

- 사용하는 위치에 최대한 가까이 선언.

> 인스턴스 변수

- 클래스 맨 처음에 선언.

- 잘 설계한 클래스는 많은 클래스 메서드가 인스턴스 변수를 사용하기 때문.

> 종속 함수

- 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치.

- 가능하다면 호출하는 함수를 호출되는 함수보다 먼저 배치

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
32
33
34
35
36
37
38
39
40
41
42
public class WikiPageResponder implements SecureResponder {
  protected WikiPage page;
  protected PageData pageData;
  protected String pageTitle;
  protected Request request;
  protected PageCrawler crawler;
 
  public Response makeResponse(FitNesseContext context, Request request)
    throws Exception {
    String pageName = getPageNameOrDefault(request, "FrontPage");
    loadPage(pageName, context);
    if (page == null)
      return notFoundResponse(context, request);
    else
      return makePageResponse(context);
  }
 
  private String getPageNameOrDefault(Request request, String defaultPageName)
  {
    String pageName = request.getResource();
    if (StringUtil.isBlank(pageName))
      pageName = defaultPageName;
 
    return pageName;
  }
 
  protected void loadPage(String resource, FitNesseContext context)
    throws Exception {
    WikiPagePath path = PathParser.parse(resource);
    crawler = context.root.getPageCrawler();
    crawler.setDeadEndStrategy(new VirtualEnabledPageCrawler());
    page = crawler.getPage(context.root, path);
    if (page != null)
      pageData = page.getData();
  }
 
  private Response notFoundResponse(FitNesseContext context, Request request)
    throws Exception {
    return new NotFoundResponder().makeResponse(context, request);
  }
 
// ...
cs



|| 가로 형식 맞추기


-

- 120자 정도의 행 길이를 제한


> 가로 공백과 밀집도

- 가로로는 공백을 사용해 밀접한 개념과 느슨한 개념을 표현

1
2
3
4
5
6
7
private void measureLine(String line) {
    lineCount++;
    int lineSize = line.length();
    totalChars += line.length();
    lineWidthHistogram.addLine(lineSize, lineCount);
    recordWidestLine(lineSize);
}
cs

> 들여쓰기

- 범위로 이루어진 계층을 표현하기 위해 코드를 들여씀.

- 짧은 함수에서도 들여쓰기로 범위를 제대로 표현하자.



|| 밥 아저씨의 형식 규칙


-

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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;
  }
}
 
// Added to get code to build
interface JavaFileAnalysis {}
class LineWidthHistogram {
  public void addLine(int lineSize, int lineCount) {
    //TODO: Auto-generated
  }
 
  public Attributes getLinesforWidth(int width) {
    return null;  //TODO: Auto-generated
  }
 
  public Set<Integer> getWidths() {
    return null;  //TODO: Auto-generated
  }
}
cs







출처 : 클린 코드 (Robert C. Martin)







반응형
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday