본문 바로가기

Java Programming

Programming by Intending

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
테스트위주의 개발 : 의도된 프로그래밍

2005년 2월 4일, Dave Astels에 의해 쓰여짐, 챕터의 예제는 courtesy of Prentice Hall PTR가 제공했다.

부분적인 코드에 대해서 작업을 하고 또 그것에 대해 이해하는 것이 어렵다는것을 발견한 적이 있습니까? 아마 로직이 뒤죽박죽 일겁니다, 식별자들은 의미가 없거나 아니면 더 심각하게는 혼동될 수 있을 겁니다. 문서가 있다구요? 해석이 가능했습니까? 이해가 가던가요? 코드까지 설명했나요? 정말인가요? 어떻게 알수 있습니까? 이 챕터에서는 XP에서 중요한 요소인 의도된 프로그래밍에 대해서 다룰것입니다, 그것은 당신이 코딩을 할때에 당신의 의도를 명확하게 만드는 것을 의미합니다.

O, be some other name!

—Romeo and Juliet, Act 2 Scene 2 William Shakespeare

의도된 프로그래밍의 중요한 요소는 커뮤니케이션입니다, 상세하게는 코드를 읽는 누군가에게 우리의 의도를 전달하는 것 입니다. 목표는 코딩을 할 때에 무엇을 우리가 생각하고 있었는지 그들이 이해할 수 있게 하는 것 입니다.

코드를 이해할 수 있고 의도를 보여줄 수 있게끔 하기위하여 무엇이 필요한지 알아봅시다.

NAMES 이름들
작명법에 의해 식별자를 의미한다, 우리가 작업을 할때 만들 여러 클래스들과 변수들과 메소드들 및 기타 등등에 대해서 이름을 선택한다. 이름 선택이 필요하다면 그 이름이 무엇을 의미하고 그 의미는 무엇이라고 이야기하는지 의미 분석이 명확한 것을 선택한다.

이름 짓는 것에 대해 생각할 때 챕터에 시작에서 시작했듯이 로미오와 줄리엣의 대사로부터 인용하는 것을 좋아한다. 우리는 이름이든 단어든 무엇이든 사용할 수 있다, 하지만 의미가 전달이 되지 않는다면, 미래에 이 코드를 읽거나 작업하게 될 사람에게 혼동을 줄 수가 있다. 이 과정에서는 의미가 있는 이름을 사용하는 것이다. 

우리 큰 딸은 자기가 좋아하는 이야기와 노래의 이름을 자기 고유의 이름으로 부르는 버릇으로 비록 가끔은 귀찮게 굴긴 하지만 보통은 귀여운 짓을 하곤 한다. 아이는 모든 음악과 이야기의 한 줄에 초점을 맞추고 그 한 줄로부터 이름을 도출한다. 잠자리에 들 시간이면 아이는 새로운 관심사에 대해서 우리가 스무고개 놀이를 하는 것처럼 열심히 물어본다. 이것은 어떤 것에 명확하지 않은 이름을 사용한데 대한 위험성이다. 당연히 우리는 이해할 수 있을지 모르지만, 모두가 그럴 수 있을까?

우리가 사용할 이름을 선택할 때 몇 가지 패턴들이 있다, 아래에서 더 자세히 알아보겠다.

클래스 이름이 무엇을 표현하는지 무엇을 하는지, 명사 또는 명사절을 클래스 이름으로 사용하라.

public class Movie {
  //...
}

public class MovieRatingComparator implements Comparator {
  //...
}

public class XMLMovieListReader implements MovieListReader {
  //...
}


일반적인 명사들을 사용하거나 인터페이스를 위한 명사구를 사용하라. 인터페이스는 약간 다르다. 만약에 형용사가 인터페이스이름으로 사용된다면 보통은 -able로 끝나는 것을 사용한다. 예를 들자면 Runnable, Serializable들이 있다. 이런 방법은 가능한 한 이름에 "I"를 계획하거나 추가하는 관습들을 피할 수 있다. 때로는 “무엇의 기반이 된다” 라는 것보다 좋은 인터페이스를 이름이 없다. 이런 경우에는 ISomething이 적합하다.


public interface Serializable {
}

public interface MovieListWriter {
  void write(MovieList movieList) throws IOException;
}

메소드 이름에는 동사나 동사구를 사용해라. 메소드는 무언가를 한다, 그래서 이름에 동사를 사용하고 의미를 부여한다. 예를 첨부하였다.

private int calculateAverageRating() {
  int totalRating = calculateTotalRating();
  return totalRating / ratings.size();
}

Accessor와 Mutator에는 일반화된 약속을 사용한다. 인스턴스 변수들을 어떻게 검색하고 변경하는지에 대하여 많은 프로그래밍 언어들은 일반화된 약속이 있다. 예를 들어 당신이 사용하는 자바에서는 X라는 변수에 대해서 검색하고 변경하는것을 getX, setX라고 표현하고 있다.

public Category getCategory() {
  return category;
}

public void setCategory(Category aCategory) {
  category = aCategory;
}

public boolean isOfCategory(Category aCategory) {
  return category.equals(aCategory);
}

boolean 변수에 대해서는 자바나 스몰토크 둘 다 isX라고 사용한다. 어떤 경우에는 객체의 선택적인 부분에 X를 참조하는 곳에 isX() 형태를 사용한다.

public boolean isRated() {
  return !ratings.isEmpty();
}

public boolean hasRating() {
  return !ratings.isEmpty();
}
실제의 인스턴스 변수들과 마찬가지로 계산된 값을 적용한 것을 기록한다. 예를 들면 원형 큐 class가 full인지 아닌지를 묻는 메소드가 필요하다면, isFull이라고 하는것을 추천한다.


때로는 get 접두어를 떨어뜨리는 것이 더 명확하다. 예를 들어 합성 객체의 크기를 가져오는 getSize 라고 하는 것보다 size를 사용하는 경우가 있다. 당신이 하나의 변수와는 반대로 요청한 객체의 값인 경우이다.

public int size() {
  return movies.size();
}

이 경우에는, 우리는 Java 클래스 라이브러리에서 사용된 약속을 따른다. 다른 사람이 당신의 코드를 읽을 때 익숙하게 해야 하기 때문에 당신이 일하고 있는 환경의 관용구에 따르게 하는 좋은 아이디어 이다.

메소드 이름에 과잉 정보를 넣지 마라. 만약에 X라는 인스턴스에 추가하는 메소드가 필요하다면, 매개변수가 X이기 때문에 add라고 하기보다는 addX라고 메소드명을 사용할 것이다. 만약에 차후에 인수의 타입을 바꾸는(심지어 클래스의 단순한 이름 교정) 재구성을 한다면 메소드는 인수와 동시에 바뀐다는 이점이 있다. 순수한 중복은 오해하기 쉽고 복잡하게 되어 있다. 다른 이점은 당신이 메소드 이름을 오버로딩 하는 것에 의하여 다른 유형의 추가를 지원할 필요가 있는 경우에 당신이 명확성을 얻는다는 것이다.

public void add(Movie movieToAdd) throws DuplicateMovieException {
  if (this.contains(movieToAdd)) {
   throw new DuplicateMovieException(movieToAdd.getName());
  }
  movies.add(movieToAdd);
}

항상 예외가 있다. 메소드 이름에 type 정보가 있는 경우 더 명확할 수 있고 더 읽기 쉬울 수 있다.

public void addRating(Rating ratingToAdd) {
  ratings.add(ratingToAdd);
}

변수 이름에는 명사와 명사구를 사용하라. 변수는 어떤것을 가지고있는 의미를 부여하는 명사를 사용한다. 예를들면  rating, movies, connectionToReviewServer 가 있다.

public class Movie {
  private String name = "";
  private Category category = Category.UNCATEGORIZED;
  private List ratings = null;

  //...
}

이름을 신중하게 선택해라, 하지만 시간을 너무 많이 허비하면 안 된다. 만약 차후에 의도를 더 잘 전달할 수 있는 다른 이름이 결정되면 바꿀 수 있도록 바꾸기 쉽게 해야 하는 것을 기억해라. 그것이 가장 중요한 기본 리팩토링중에 하나이다. 툴을 사용하는 것은 자동으로 리팩토링 하는 것을 제공해 줄 것이다.

단순화
다른 사람에게 생소한 어떤 것을 설명할 때, 가능한 한 간단하게 말한다. 마찬가지로 코딩을 할 때 간단하게 해야만 한다. 훗날, 누군가가 코드를 읽고 이것이 무엇을 하고 어떻게 되는지를 이해하려고 하게 될 것을 명심해라,

가장 단순한것부터 해라

그래서 어떻게 코드를 명확하게 할 것인가? 한 방법은 가능한 한 간단한 알고리즘을 사용하는 것이다. 항상 가장 쉬운 방법이 최고의 방법이라는 것을 익혀야 한다. 그게 아니라는 것을 증명할 수 없다면 항상 바꿀 수 있다.(?) eXtreme Programing에서 많이 인용되는 어구 중에 하나가, “수행 가능하게 하는 가장 간단한 것이 무엇인가?” 이다.



“무엇인가?” 라고 질문한다면, “그게 무슨 뜻인데?”, 간단한 테스트를 생각해보자:

public void testEmptyList() {
  MovieList emptyList = new MovieList();
  assertEquals(0, emptyList.size());
}
이 테스트를 한 번에 통과하기 위하여, 우리는 가장 수행 가능한 가장 간단한 것을 해야 한다:

public int size() {
  return 0;
}


우리는 size() 메소드는 아주 간단하다는 걸 알고 있다. 그러나 이것이 무엇이 되어야 하는지 모른다. 0을 리턴하는 것이 테스트를 통과하게 만드는 가장 간단한 방법이다. 그러나 비어있지 않은 list 행동을 위한 테스트를 작성 하고 이 메소드를 일반화시켜야 한다,


리팩토링으로 간단하게 유지하시오.

코드를 간단하고 의미가 명확하게 하는 또 다른 방법은 불분명한 코드를 명확하게 바꾸는 것이다. 이것은 사용되는 리팩토링의 방법의 하나이다. 챕터 2에서 아주 중요한 주제로 더 깊은 토론을 하게 된다.

코드를 의도를 분명하게 하는 많은 리팩토링 방법이 있다. Fowler의 리팩토링의 대부분은 코드를 명확하게 한다는 것은 주장하는 동안, 우리는 단지 한 부분을 생각한다. 더 많은 정보 위해서 [15]와 [16]을 보도록 하자. 이것은 클래스와 메소드, 변수들의 이름을 바꾸는 것을 포함한다. 더 복잡한 의도를 명확하게 하는 리팩토링 방법은 다음에 설명된다.


복잡한 표현을 가지는 변수라면 설명하십시오, 그것에 대해 나누고, 임시 변수에 중간 값들을 넣고 그 의도에 대한 설명을 한다.

메소드가 조금 복잡할 경우에 메소드를 풀어라. 메소드들을 나누고, 메소드 안에 나눈 메소드를 집어 넣는다. 이 방법은 여러 메소드들안에 일반적인 코드를 본다면

많은 일을 하거나 여러 가지 책임을 가진 클래스가 있다면 클래스를 풀어라. 여러개의 클래스들로 책임을 나눌수 있다.

값을 계산하여 임시 변수 안에 저장하는 것 보다 쿼리가 있는 임시 값을 대체하라, 그 계산을 리턴 할 값이 있는 메소드를 식에 집어 넣고 그것을 부르는 것으로 대신할 수 있다.

재사용 될 임시변수가 될 부분일 경우에는 임시변수를 쪼개 놓아라. 각각 사용될 새로운 임시변수를 만들어라.

매개변수를 가르키는 코드가 있다면, 그것을 삭제 하라. 임시변수를 사용하여 대신 할 수 있다.

WARRANTED ASSUMPTIONS(검증된 가설)

의도된 프로그래밍이라고 명명된 이 섹션의 테스트는 프로젝트에서 첫 테스트로 사용된 것이다. 이 테스트는 보여주기위해 쓰여진 것이고, 다른 코드는 아직 작성하지 않았다. 이것이 의미가 있을까? 이 테스트 코드를 본다면, 이 테스트들이 몇 가지의 가설을 만드는 것을 볼 수 있다.


there is a class called MovieList, MovieList 라고 불리우는 클래스가 있다.

MovieList는 인수가 없는 생성자가 있다. 그리고 size라고 불리우는 매개변수가 없고 int값을 리턴하는 메소드가 있다.


우리가 테스트를 쓰기위해 가정을 만드는 것은 사용하게 될 요점들로부터 인터페이스를 디자인할 수 있는 능력을 준다. 읽기 쉽고 의미가 있는 이름을 선택하는 것을 가능하게 하고 또 그것은 이해하기 쉽고 명확하다. 또한 요점을 다시 봄으로써, 필요한 행동들을 결정할 수 있다. 이것은 적은 코드만을 작성하고 빠르게 작업할 수 있고, 정확하고 필요한 행동들만으로 제한이 된다.

어떻게 적은 코드들을 작성해가야 할까? 첫째로 그 코드가 필요하다는 것이 증명되기 전까지는 코드를 추가하는 것을 미뤄야 한다. 구현하는 것을 포함할 뿐만 아니라 클래스를 만들거나, 메소드를 만드는 것 또한 마찬가지이다. 만들 인스턴스들에 대한 테스트를 마치기 전까지는 클래스를 만들지 않아야 한다. 마찬가지로, 호출할 메소드들에 대한 테스트를 마치기 전까지는 메소드를 추가해서는 안 된다.

코드를 써갈 때(테스트도 마찬가지로),어떻게 그것이 동작하는지에 대해서는 걱정하지 말고 당신이 원하는 것을 쓰도록 한다. 당신이 원하는 도와주는 클래스, 메소드, 인스턴스들을 구성한 후에 그것을 구현할 것에 대해서 고민한다. 이것은 현재 의도된 것에 초점을 맞추도록 한다. 컴파일러는 만들었던 가설에 대해서 기억하게 도와줄 것이다.


HOW TO PROGRAM BY INTENTION 어떻게 의도된 프로그래밍을 하는가

당신의 코드에 의도를 전달하는 것을 강화시키는 테크닉이 여러 가지가 있다. 테크닉들을 조사하고 사용방법을 조사한다. 은유법을 사용하고, 먼저 테스트를 하고, 재구성하고, 가설을 만들고, 당신이 다음에 무엇을 할지 컴파일러가 당신에게 전해주는 것들이 있다.

Common Vocabulary 일반적인 어휘

프로젝트와 관계된 모든 것들은 도메인과 시스템에 대한 일반적인 어휘를 사용해야한다. 이해하기 쉬운 비유된 단어이거나 실제 상황을 나타내는 단어 일 수 있다.

일반적인 어휘를 갖는 것은 두 가지 측면에서 도움을 준다:

복잡한 소프트웨어를 개발하는 것은 다른 배경과 지식 영역을 가진 사람들을 포함하는 것이기 때문에 그 영역을 이해시키는 것이 어렵다. 그러나 영향력 있는 팀이 되는 것은, 특별히 해결해야 할 시스템의 문제와 문제 영역의 일반적인 이해를 성취하는 것이 필요하다. 팀의 기술적인 구성원들이 사업에 대한 깊은 지식을 가지고 있지 않은 어려운 문제점이 있다. 반면에 시스템이 큰 범위 내에서 어떻게 무엇을 하는지 사업자들이 명확하게 이해할 수 있다는 것을 확인하는 것이 문제이다. 비유를 사용하는 것이 이 두 구성원에게 시스템과 그 영역의 설명을 제공하는  중개를 도와준다.

Chrysler에서의 원초적인 XP프로젝트는 좋은 예이다. Chrysler의 사람들은 조립라인과 공정 용어를 이해했다. 프로그래머들이 개발 중인 급료 계산 시스템에 대해서 비유를 사용하였다. 직원들의 임금은 상품이 되었고, 파트타임으로 만들어졌다. 이것은 많은 워크스테이션에 통과하였고, 각각 보너스를 더하거나 공제를 받거나, 일한 시간을 돈으로 환산하는 것 같은 동작을 할 수 있었다.

일반적인 어휘로 이름을 선택한다면 모두가 그 의미를 아는 것으로 선택해라. 일반적인 어휘라는 것은 모두가 같은 부분에 대하여 같은 의미를 사용하는 것을 말하는 것이다. 크게 혼란할 수 있고 알아 듣기 어려운 것을 피할 수 있고 많은 시간이나 금전적인 소모를 피할 수 있다. 모두가 사용하는 용어들을 포함해야 할 뿐만 아니라 명확한 방법으로 의미여야 한다.

Test First
테스트를 가장 먼저 하라

테스트를 가장 먼저 하는 것의 가장 큰 효과 중에 하나는 재구성할 수 있게 하는 큰 부분들을 알 수 있다는 것이다. 또한 테스트를 먼저 작성하면, 어떻게 동작할지 생각하기 전에 무엇이 필요한지에 대해서 생각해 볼 수 있다.

또 다른 이점은 테스트에 성공 했을 경우에 끝이 났다는 것이다. 이것은 적어도 두 가지 장점을 가지고 있다.

일을 빠르게 하게 도와준다, 왜냐하면 테스트에 통과하고 끝이 났을 때 어떤 나머지 것들을 옮겨 올 수 있고 테스트를 통과할 것을 할 때 필요한 것보다 많은 복잡한 코드를 제작하는 것을 피하기에 수월하다. 이 방법은 우리의 전체적인 코드의 질을 향상시켜주고 동시에 적고 더 이해가 쉽게 만들어 준다.

Make Assumptions 가정들을 세워놓아라

이것은 테스트 코드를 먼저 작성하는 것과 밀접한 관련이 있다. 하지만 테스트 코드를 작성하는 것만으로 국한 되지 않는다. 잘 알려진 구현들을 하는 동안에 가정을 세울 수 있다. 작업을 할 때 가정을 세워 놓는 것은 무엇이 필요하고 무엇을 호출할 것인지 만들기 전에 결정할 수 있다. 이 방법은 어떻게 완성시킬지에 대한 자세한 기술적인 것에 대해서 고민하기 전에 완성을 위해 필요한 것이 무엇인지를 생각해 보게 한다. 또한 가까운 일에 집중 할 수 있게 해준다. 유효하지 않게 바뀌는 몇 개의 가정들을 만든다면, (가정을 세운 것이 존재하지 않게 된다면) 컴파일을 시도할 때 찾아 낼 수 있다. 가정을 만들어야만 할 때 하고 있던 것을 완료할 수 있다. 기존에 하려던 것에 대한 정보를 잃어버리는 위험을 초래 할 수 있다. 따라서, 해야 할 것들에 대해서 조금씩 적을 수 있게 노트나, 빈 종이 묶음을 컴퓨터 옆에 두어라.



Refactor 재구성하라

필요한 것이 확인 될 때 재구성하는 것은 이미 의도를 명확하게 만든 것을 바꿀 수 있다. 재구성하는 것은 이 챕터 보다 앞선 챕터 2에서 더 잘 토론되어 있다.


Let the Compiler Tell You
컴파일러가 알려주도록 하라.


이 만들어야 할 가정들의 자취를 보관하는 것에 대해서 걱정하지 않도록 도와주기 때문에, 이 방법은 필요할 때 까지 일을 미룰 수 있도록 도와 준다. 거짓으로 변화할 수 있는(아직 존재하지 않지만 코드에 쓰이는 클래스나 메소드 같은) 가정을 만들 때 컴퓨터가 우리에게 정보를 제공 할 수 있다. 자바나 C++같은 경우에 컴파일러가 빼먹은 어떤 것과 올바르게 되어야만 하는 것(빼먹은 클래스나 메소드를 끄집어내는) 대해서 보고를 해준다.



예를들어 프로젝트를 위해서 처음 작성된 코드는 다음과 같다.

public void testEmptyListSize() {
  MovieList emptyList = new MovieList();
  assertEquals("Size of empty movie list should be 0.",0,emptyList.size());
}

만약 이 첫 코드가 프로젝트에서 사용이 된다면, 컴파일러는 다음과 같은 메시지를 보여준다.

MovieList cannot be resolved or is not a type.
So we create the required class:

public class MovieList {
}
Compiling again results in:

The method size() is undefined for the type MovieList

다음으로, 메소드를 추가 해 넣을수 있다:

public int size() {
  return 0;
}

컴파일러가 당신에게 알려주게 하는 것을 도입하면, 만들어야 하는 가정들에 대해서 걱정하는 것을 그만 둘 수 있다. 이것은 또한 정말 필요한 만큼보다 더 다른 것을 하는 것을 피할 수 있는 방법이다.



Do the Simplest Thing
가장 간단한 것을 수행하라

말하기에 앞서서 단순화하기 위해 노력하는 것은 다시 말할 필요가 있다. 코드가 간단하게 시작하는 것은 간단한 것을 복잡하게 만드는 것보다 간단하다. 항상 가장 간단한 것을 수행하지 않을 수 있다, 하지만 당신의 코드는  가장 간단한 것을 찾아내다 보면 더 간단하고 명확하게 될 것이다. 이전의 섹션에서 단순화에 대해서 자세하게 다루었다.

이점에 대해서는 다른 의견들이 있다. 가능한 일을 할 수 있는 가장 간단한 것을 권한다. 간단하게 하는 것이 버릇이 되도록 시작할 때 당신 스스로 가장 간단한 것을 하게 하는 것을 선호하도록 하는 것을 권한다. 그렇게 되면 단순하게 하는 것은 그것이 무엇인지 깨닫는 동안은 중요하지 않게 된다.

"NO COMMENT" 코멘트를 달지 말아라.

코멘트를 쓰는 유효한 이유들이 있다. 후에 이것에 대해서 다룰 것이다. 그러나 챕터 2에서 다루었기 때문에, 대부분의 코멘트들은 유효한 이유들을 위해서 쓰여지지 않는다. Fowler's Refactoring은 코멘트를 탈취제 라고 부른다. 코멘트들은 코드의 악취들을 숨기도록 한다. (코드가 지저분하고 코드가 형편없이 쓰여지거나, 이름이 제대로 선택되지 않거나, 로직이 이상하게 되어 있는 경우 등) 코멘트들은 코드가 무엇을 하는지에 대한 설명이 추가되어진다. 코드는 불필요하게 코멘트들을 만들지 않기 위해서 재구성 되어져야한 하고 되어졌어야만 한다.

“문서를 작성하지 말라” 고 말하지 않았기 때문에 내가 틀렸다고 하지 말라. 실제 XP를 하는 누구도 그렇게 이야기 하지 않을 것이다. 가끔 특별한 문서를 갖고 있는 것은 소비자에게는 중요하다. 또한 나는 “절대 코멘트 남기지 말라” 고 말하지 않았다. 내가 말한 것은 “불필요한 코멘트를 남기지 말라” 는 것이다. 대부분의 코멘트들은 코드의 의도를 명확히 위해서 불필요하게 쓰여 진다. 코멘트를 쓰게 될 때에 어떻게 의사 전달을 할지 보다는 왜 확실히 해야 하는지가 명확히 해야 한다.


Valid Comments
유효한 코멘트들이란

위에서 언급했듯이 코멘트를 남기는 것이 좋은 것들이 있다.

미완성된 코드, 코멘트의 이런 형식은 일을 하는 중심에 있는 것이거나 어떻게 개발된 코드인지 보는 기록으로 대체된다. 일반적으로 많이 이런 형식의 코멘트는 하루 안에 완성할 수 있는 작은 것이 아니면 필요하지 않다. 기록처럼 만들 필요가 있다는 것을 발견한다면, 빠르게 찾을 수 있게 하기 위해 규정된 태그를 선택한다. 그리고 일반화되지 않은 코멘트는 피한다. 다음과 같은 것을 제안한다:

// TODO: The tree should be balanced after doing the insertion.





이런 코멘트의 형식을 유용하게 쓰는 것은 재구성 될 것에 도움을 줄 수 있는 코드를 기록할 수 있다. 아마도 재구성이 필요하다는 것을 볼 수 있을 것이다. 그러나 그럴 시간이 없다. 누군가 알아 낼 수 있을 기록을 남기고 그리고 시간이 있을 때 재구성을 한다. 이와같이 “refactoring To Do" 라는 코멘트처럼 규정된 단어를 사용해야 한다. 아래와 비슷한 것을 제안 한다:

// CODE DEBT: the looping structure is a bit convoluted, could use
// some method extraction.



정말 유효한 코멘트가 아니므로 재구성을 명확하게 할 필요가 없다. 대신에 이전의 형식과 같아야 한다. 차용증과 같다. 재구성이 코드를 깔끔하게 하지 않으면 누군가가 곧 해야 하거나 의문이 드는 코드를 수집하거나 다시 작성해야한다.

// NEEDS WORK: I tried extract method, but it's still awkward.
// Maybe refactoring to a Strategy would clean it up?




어떤 이유에서 이상한 알고리즘을 사용한다면 코멘트와 함께 그것에 대한 기록을 남겨야한다. 그것을 더 알 수 있는 곳을 읽게 될 사람에게 알려준다. 많은 코멘트로 알고리즘에 대한 문서를 만들지 않도록 한다. 그냥 그 알고리즘이 무엇인지를 기록하고 왜 그것을 사용했는지, 어디서 그 정보를 알 수 있는지를 남겨라.

// I used an AVL Tree algorithm here to keep the tree balanced.




검증된 알고리즘을 사용하는 경우에는 저자에 대한 정보와 어디서 가져왔는지의 코멘트를 첨부한다. 이런 형식의 코멘트는 밑의 형식처럼 쓰여진다.
// This AVL alorithm was based on Brad Appleton's implementation at
// http://www.enteract.com/~bradapp/ftp/src/libs/C++/AvlTrees.html


Performance tuning 성능 조정

이것은 중요하다. 성능조절이 필요할 경우에 그것에 대해서 설명하는 코멘트를 추가해야 한다. 적어도 문제의 메소드가 조정되었다는 기록을 남겨줄 필요가 있다. 이런 기록없이 조정을 한다면 차후에 코드를 명확하게 하고, 프로세스하에서 최적화된 원상복귀 재조정을 할 누군가를 찾아야만 한다. 일반적으로 프로젝트에서는 늦게까지 성능조정을 할 필요가 없다는 것을 숙지하고, 한번의 퍼포먼스는 신중하게 되어야 하고, 현재 문제가 되는 것을 찾아 낼 수 있어야 한다.

// A circular queue is used here for performance reasons: to avoid
// having to move elements around.




Class comment 클래스 코멘트

보통 코멘트에 문제점을 쓰는 것 대신에 자주 쓰이는 경우 중에 하나이다. 많이 필요하지는 않다. 클래스를 시작할 때 간략한 설명과 왜 클래스가 존재하는지 어떻게 쓰이는지에 대해 간략하게 기록하는 것으로 족하다. 이 클래스 튜토리얼을 써서 어떻게 기록하는 것을 피하라. 아래는 테스트를 위해 존재 하는 것이다.

/**
* This class represents a single movie title. It is responsible for
* maintaining its own ratings, reviews, etc.
*/




마지막 기록은 코멘트 들과 관련이 있다. 프로그래머들은 누가 그것을 작성했는지 파일의 헤더에 코멘트를 포함한 그들의 작업에 대해 알린다. 괜찮은 방법이다. 어디서 작성했는지 언제 했는지에 대한 것을 기대할 수 있다.

만약 XP를 연습하고 있는 중이고, 특별한 공동의 코드 소유자이고, 모두가 그 코드로 작업하게 된다면, 그것은 팀이 소유하고 있는 것이다.

각각의 파일로 일하는 사람의 기록은 소스 코드 제어 시스템(SCCS : source code control system)에 의해 유지될 것이다. 그것은 파일에 정보를 스스로 잘 넣을 수 있도록 크다. 파일안에 확장가능한 change log를 넣지 말라.(e.g., $Log$ in CVS) 이것은 코드를 어수선하게 하고 파일의 용량을 늘리고, SCCS로부터 추출하기 쉬운 정보를 복제한다.


SUMMARY 요약

이 챕터에서 어떤 이름을 선택하는 것과 같이 어쩌면 별로 중요해보이지 않은 것들에 대해 서술한 것 같지만 코드의 질에 큰 영향력을 줄 수 있다. 우리는 이름을 짓고, 단순화 시키고, 집중 점을 유지하고 의도가 투명한 코드를 만드는 기술에 대해서 다루었다. 이런 방법들을 연습하는 이점은 코드를 유지시킬수 있고 단순화하고, 이해하기 쉽게 한다.

금방 누군가가 우리의 코드를 읽을 수 있다. 스스로 만든 코드를 다시 읽어볼 수 있다, 어떨 때는 오랜 시간 뒤에 볼 수 있다. 코드에 의해 망쳐지고 헷갈리게 되는 우리 뿐만 아니라 어떤 누구든, 헷깔리고 어색하고 최악의 상황에는 오해하게 된다.

잘 만들어지고, 단순하고, 명확하고, 의미 전달이 잘되는 코드는 작업을 빠르게 할 수 있다. 이런 코드는 어떻게 프로그램을 잘할지에 대해서 읽는 사람이 알 수 있게 도와준다. 문제 해결에 좋은 해결책을 알려주고 그 해결책을 어떻게 명확하게 표현할지를 가르쳐 준다.

이런 명확한 의도로 된 코드를 하는 것은 어떤 프로그래머에게도 가치가 있다.