구글의 자바 코딩스타일 가이드

구글에서 사용하는 자바코딩의 가이드라인을 알아보자

1 기본

1.1 용어정리

  1. 클래스class라 함은 이타적inclusive인 의미의 "통상적"인 클래스, 열거형 클래스, 인터페이스 또는 애너테이션유형(@interface)를 지칭한다.
  2. 멤버member- of a class라 함은 이타적으로 중첩클래스nested class, 필드, 메서드 또는 생성자constructor- initializer와 주석comment을 뺀 모든 최상위 컨텐츠all top-level contents를 지칭한다.
  3. 주석comment라 함은 언제나 구현주석implementation comment를 지칭한다. 문서주석documentation comment란 단어는 사용하지 않으며 통상적인 자바독Javadoc이란 용어를 사용한다.

2 소스파일 기본

2.1 파일명명규칙

  • 파일명은 해당 자바파일에 정의된 최상위 클래스의 대소문자 구분 된 클래스명을 따르며 .java의 확장자를 사용한다.

2.2 소스파일 인코딩

  • 소스파일은 UTF-8형식의 인코딩을 사용한다.

2.3특수문자

2.3.1 공백문자

  • 끝자리 문자 이외에는 ASCII 가로공백문자 ASCII horizontal space character 0x20만이 소스파일 내에서 사용되며, 이는,
    1. 다른 모든 공백문자나 문자리터럴은 이스케이프 되어야 한다.
    2. Tab문자는 인덴트로 사용되지 않는다.

2.3.2 특수문자 이스케이프 순서

  • 특수 이스케이프 시퀀스 (\b, \t, \n, \f, \r, ", '및 \)가있는 문자의 경우 해당하는 8진수(\012)나 유니코드(\u000a) 대신 해당 시퀀스가 사용된다.

2.3.3 ASCII 이외의 문자

  • 다른 모든 ASCII 이외의 문자에 대해서는 실제의 유니코드문자 (e.g. ∞) 또는 그에 해당하는 이스케이프 된 유티코드 문자 (e.g. \u221e)를 사용한다. 어떤 유형을 사용할 것인지에 대한 선택은 코드를 더 쉽게 이해할 수 있음에 기반하며, 문자리터럴 외에 또는 주석에 이스케이프 된 유니코드 문자는 지양한다.

    Tip: 이스케이프 된 유니코드문자를 사용 시, 그리고 해당 유니코드문자를 사용 시에도, 이를 설명하는 주석은 매우 도움이 된다.

예제:

Example Discussion
String unitAbbrev = "μs"; 가장 좋은 형태: 주석없이도 이해가 가능
String unitAbbrev = "\u03bcs"; // "μs" 허용되지만 이렇게 할 이유가 없음
String unitAbbrev = "\u03bcs"; // Greek letter mu, "s" 허용되지만 어색하고 실수 할 여지가 많음
String unitAbbrev = "\u03bcs"; 좋지 않음: 어떤 의도인지 파악하기 어려움
return '\ufeff' + content; // byte order mark 좋음: 출력되지 않는 문자에 대해서 이스케이프를 사용하고 필요하면 주석을 사용

Tip: 특정 프로그램들이 ASCII 문자를 지원하지 않을까봐 걱정되어 여러분이 작성하는 코드의 가독성을 줄이지 말자. 만약 그런 프로그램이 있다면, 그 프로그램은 고장난 것이며 고쳐야 한다.

3 소스파일구조

  • 소스파일의 구조는 다음을 순차적으로 포함한다:
    1. 라이선스 또는 저작권정보 (기존재 시)
    2. 패키지 선언문
    3. 임포트import 선언문들
    4. 정확히 하나의Exactly one 최상위 클래스
  • 그리고 정확히 하나의 Exactly one 빈 줄로 각 요소를 나눈다.

3.1 라이선스 또는 저작권정보 (기존재 시)

  • 만약 특정 파일에 라이선스 또는 저작권 정보가 존재 한다면 이곳에 포함한다.

3.2 패키지 선언문

  • 패키지선언문은 줄바꿈 하지 않는다 not line-wrapped. 컬럼제한(4.4섹션, 컬럼제한: 100)은 패키지 선언문에 적용되지 않는다.

3.3 임포트 선언문

3.3.1 와일드카드 임포트 사용금지

  • 와일드카드 임포트1, 스태틱이든 간에, 사용되지 않는다

3.3.2 줄바꿈 하지 않음

  • 임포트 선언문은 줄바꿈 하지 않는다. 컬럼제한(4.4섹션, 컬럼제한: 100)은 패키지 선언문에 적용되지 않는다.

3.3.3 정렬과 간격

  • 임포트 선언문은 다음과 같이 정렬한다:
    1. 모든 스태틱 임포트를 같은 블럭에 정렬
    2. 모든 스태틱이 아닌 임포트를 같은 블럭에 정렬
  • 만약 스태틱과 스태틱이 아닌 임포트가 동시에 존재 할 경우, 하나의 빈 줄로 두 블럭을 나눈다. 그 외에 경우엔 빈 줄로 나누는 경우는 없다.
  • 각 블럭 안의 임포트문들은 이름을 ASCII 정렬순서로 정렬한다. (참고: '.'는 ';' 앞에 정렬되므로 임포트 선언문들이 ASCII 정렬 순서와 다름)

3.3.4 클래스는 스태틱 임포트 하지 않음

  • 스태틱 중첩클래스들은 스태틱 임포트를 하지 않고 일반적인 임포트를 사용한다.

3.4 클래스 선언

3.4.1 정확히 하나의 최상위 클래스 선언

  • 각 최상위 클래스는 자신에게 할당된 하나의 소스파일에 존재한다.

3.4.2 클래스 내용의 정렬

  • 당신이 선택한 클래스 멤버와 이니셜라이저들의 정렬방법은 학습가능성learnability에 막대한 영향을 미칠 수 있다. 하지만, 앞서 말한 것에 대한 정확한 방법recipe는 없다; 각자 다른 클래스는 다른 방법으로 내용을 정렬할 수 있다.

  • 중요한 것은, 각 클래스들이, 유지보수자가 물어봤을 때 대답해 줄 수 있는, 논리적인 정렬을 사용한다는 것이다. 예를 들어, 새로운 메서드들이 습관적으로 클래스의 마지막에 추가되지 않게 하는 것인데, 이것은 그저 "날짜순으로 추가"로 정렬된 것이며, 이것은 논리적인 정렬이 아니다.

3.4.2.1 오버로딩Overloads: 절대 나누지 않는다
  • 하나의 클래스가 여러개의 생성자constructor를 지닌다거나, 같은 이름의 메서드들이 여러개 존재한다면, 다른 코드들이 중간에 끼어들지 않고(private 멤버 포함), 순차적으로 표시한다.

4 포맷

  • 용어참고: 블록형 구조란 클래스, 메서드 또는 생성자의 몸통body영역을 의미하한다. 섹션 4.8.3.1 배열이니셜라이저 array initializers에 따라, 모든 배열이니셜라이저는 선택적으로 블록형구조로 취급될 수 있다.

4.1 중괄호Braces

4.1.1 조건부optional일 경우 중괄호사용

  • 중괄호는 if, else, for, do 그리고 while문에서 사용되며, 내용이 비거나 한줄single statement만 쓰더라도 중괄호를 쓴다.

4.1.2 비어 있지 않은 블록 Nonempty block : K & R 스타일

  • 중괄호는 커니간Kernighan과 릿치Ritchie스타일("Egyptian Brackets")의 nonempty 블럭과 블럭형 구조스타일을 따른다.
    • 중괄호를 연 다음 줄바꿈한다.
    • 중괄호를 닫기 전 줄바꿈한다.
    • 중괄호를 닫은 후엔, 해당 중괄호가 메서드, 생성자 또는 명명된named 클래스를 종료할 때만 줄바꿈을 한다. 예를들어, 중괄호 뒤에 else 또는 쉼표comma가 따라올 땐 줄바꿈하지 않는다.

    예제:

      return () -> {
        while (condition()) {
          method();
        }
      };
    
      return new MyClass() {
        @Override public void method() {
          if (condition()) {
            try {
              something(); } catch (ProblemException e) {
              recover();
            }
          } else if (otherCondition()) {
            somethingElse();
          } else {
            lastThing();
          }
        }
      };
    
    

4.8.1섹션 열거형 클래스에서 열거형 클래스에 대한 몇가지 예외를 설명한다.

4.1.3 빈 블록: 간결할 수도 있음

  • 빈 블록, 또는 블록형구조는 K & R 스타일을 따를 수 있다( Section 4.1.2에서 설명한 것처럼). 다른형태로는 빈 블록은 다중블럭선언문multi-block statement의 한 부분이지 않을 경우(직접적으로 다중블록을 가지고 있는 경우: if/else 또는 try/catch/finally) 중괄호 사이에 다른 문자열이나 줄바꿈 없이 바로 열고 닫을 수 있다({}).
    예제:
    // 허용
    void doNothing() {}
    
    // 허용 
    void doNothingElse() {
    }
    


    // 허용되지 않음: 다중블록선언문에선 간결한 빈블록을 사용할 수 없다
    try {
      doSomething();
    } catch (Exception e) {}
    

4.2 블록 들여쓰기: +2 띄어쓰기

  • 새로운 블럭이나 블럭형 구조가 열릴 경우, 들여쓰기는 두번 띄어쓰기two spaces 한다. 만약 블럭이 닫힌다면, 들여쓰기는 기존 들여쓰기레벨로 돌아간다. 들여쓰기레벨은 코드와 주석 모두에 블럭 안에서 적용된다. (Section 4.1.2 비어있지 않은 블록: K & R스타일의 예제 참조)

4.3 라인line 당 하나의 선언문

  • 한줄에는 하나의 선언문만으로 이루어진다.

4.4 컬럼제한: 100

  • 자바코드는 100자characters의 컬럼제한을 가진다. 하나의 "문자"라는 의미는 아무 유니코드의 코드포인트code point2 의미한다. 아래의 예외경우를 제외하고 컬럼제한을 초과한 경우엔 Section 4.5줄바꿈에서 설명하듯이 줄바꿈line-wrapping을 해야한다.

    각각의 유니코드 코드포인트는2, 화면의 가로값이 길거나 짧아도, 하나의 문자로 계산한다. 예를 들어, 전각문자fullwidth characters를 사용하는 경우, 해당 줄을 이 규칙이 엄격하게 적용되는 범위 전에 줄바꿈 할 수 있다.

    예외:

    1. 컬럼제한을 따르는 것이 불가능한 줄의 경우(자바독의 URL 또는 긴 JSNI 메서드 참조).
    2. 패키지package 그리고 임포트import 선언문(Section 3.2 패키지선언문Section 3.3 임포트선언문 참조)
    3. 주석 내에 작성 된 쉘에 잘라내기 후 붙혀넣기cut-and-pasted 할 수 있는 명령문들command lines.

4.5 줄바꿈

  • 용어참고: 규칙에 위반되지 않는 선에서 한 줄single-line의 코드를 여러줄로 나눌 경우, 이 작업을 줄바꿈line-wrapping이라고 한다.
  • 줄바꿈을 하는데 있어 모든 상황에 대하여 포괄적이고 결정적인 줄바꿈을 하는 공식은 없다. 하지만 동일한 코드에 대하여 줄바꿈을 하는데 유효한 여러가지 방법이 있다.

참고: 줄바꿈을 하는데 전형적인 이유는 컬럼제한을 넘기지 않기 위해 해당 행위를 하는 것이지만, 컬럼제한의 범주에 들어가지 않지만 코드저자의 재량으로 줄바꿈을 할 수 있다.

: 줄바꿈을 하는 대신 메서드 또는 지역변수를 적출extract 함으로써 문제를 해결할 수도 있다.

4.5.1 줄바꿈 할 위치

  • 줄바꿈의 주요 지침은 : 더 높은 구문레벨에서 줄바꿈 하는것을 선호한다. 그리고:
    1. The prime directive of line-wrapping is: prefer to break at a higher syntactic level. Also:

When a line is broken at a non-assignment operator the break comes before the symbol. (Note that this is not the same practice used in Google style for other languages, such as C++ and JavaScript.) This also applies to the following "operator-like" symbols: the dot separator (.) the two colons of a method reference (::) an ampersand in a type bound (<T extends Foo & Bar>) a pipe in a catch block (catch (FooException | BarException e)). When a line is broken at an assignment operator the break typically comes after the symbol, but either way is acceptable. This also applies to the "assignment-operator-like" colon in an enhanced for ("foreach") statement. A method or constructor name stays attached to the open parenthesis (() that follows it. A comma (,) stays attached to the token that precedes it. A line is never broken adjacent to the arrow in a lambda, except that a break may come immediately after the arrow if the body of the lambda consists of a single unbraced expression. Examples:

####

4.6

4.7

4.8

4.8.1 열거형 클래스

5 명명규칙

6 프로그래밍 관행

7 자바독



주석

  1. [와일드카드 임포트]특정 패키지 내에 존재하는 모든 클래스를 임포트하는 임포트 선언문 예: java.util.* 

  2. [유니코드 코드포인트] 유니코드를 정의하는 'U+' 0 부터 10FFFF값 사이의 16진수 값  2