본 글은 아래 구글의 문서를 정리한 것입니다.
Google Java Style Guide
1 Introduction This document serves as the complete definition of Google's coding standards for source code in the Java™ Programming Language. A Java source file is described as being in Google Style if and only if it adheres to the rules herein. Like ot
google.github.io
Java Convention
Source file
- 파일 명
- 대소문자를 구별하는 최상위 클래스 이름 뒤에 .java를 붙인다.
- 특수 문자
- 공백 문자
- 줄 끝내기 문자를 제외하고, ASCII의 0x20( = 일반적인 스페이스)만이 유일한 공백문자이다.
- 이 이외의 공백문자들은 escaped된다.
- Tab은 들여쓰기에 사용하지 않는다.
- 특수 이스케이프 문자들
- 아래 특수 이스케이프 문자열은 같은 의미의 옥텟이나 유니코드 대신에 아래의 문자열을 사용한다.
- ASCII가 아닌 문자들의 표현
- 실제 문자(∞)를 쓰는 것이 유니코드(\u221e)보다 더 읽기 쉽기 때문에 권장된다!
- 공백 문자
- 소스 파일 구조
- 아래의 구성요소들이 각 한 줄씩 띄어서 작성한다.
- License or copyright (존재한다면)
- Package 문장 (줄 바꿔 쓰지 않는다)(열 제한(column limit)가 적용되지 않는다.)
- Import 문장
- 단 하나의 최상위 클래스
- Import 문장
- wildchard import는 사용하지 않는다.
- 줄 바꿔 쓰지 않는다. 열 제한이 적용되지 않는다.
- static import를 모아서 한 블럭, non-static import를 모아서 한 블럭 작성한다.
- static import 블러과 non-static import 블럭 사이에 한 줄을 띈다.
- ASCII 순으로 정렬한다.
- static import는 static nested clasess를 위해 사용되지 않는다. 일반적인 import로 import한다.
- 아래의 구성요소들이 각 한 줄씩 띄어서 작성한다.
- Class 선언
- 하나의 파일에 최상위 클래스는 하나
- 클래스의 멤버들의 순서
- 정해진 건 없지만, 논리적으로 설명할 수 있어야한다.
- overload한 생성자 혹은 메서드들은 하나로 뭉쳐서 작성한다.
Formatting
- 괄호
- 선택적 괄호의 사용
- if, else, for , do, while 의 괄호안의 본문이 비어있거나 한 줄만 있는 경우에도 괄호를 사용한다.
- 다른 괄호( lambda 표현)는 선택적으로 사용한다.
- K & R style (비어있지 않는 블럭)
- 괄호는 Kernighan and Ritchie style을 따른다.
- 여는 괄호 전에 줄 바꿈 사용하지 않는다.
- 여는 괄호 뒤에서 줄 바꾼다.
- 닫는 괄호 앞에서 줄 바꾼다.
- 닫는 괄호 뒤에서 줄 바꾼다. 다만 구문이 끝나거나 메소드, 생성자, 클래스가 끝났을 때만 적용됨. else나 콤마가 뛰따라지는 괄호 다음에는 줄 바꿈 하지 않는다.
- 괄호는 Kernighan and Ritchie style을 따른다.
- 빈 블럭
- 빈 블럭은 괄호가 줄바꿈 없이 바로 닫힐 수 있다.({}) 다만, 다중 블럭 구문(if/else or try/catch/finally에서는 바로 닫으면 안된다.
- try { doSomething(); } catch (Exception e) {} // 안됨
- 선택적 괄호의 사용
- Block indentation: +2 spaces
- 새로운 블락이나 블락같은 구조가 열리면 두 칸을 들여쓴다.
- 이것은 코드나 주석에도 똑같이 영향을 준다.
- 한 줄에 한 문장을 작성한다.
- 열 제한 : 100
- 100 문자(여기서 문자는 유니코드의 문자)의 제한이 있다.
- 이 제한을 넘기면 Line-wrapping(줄바꿈)을 해야한다.
- 예외들
- 긴 URL이나 긴 JSNI는 애초에 지킬 수가 없음
- package나 import 문장들
- shell에 복사 붙여넣기 된 주석 속의 명령문
- 매우 긴 식별자
- Line-Wrapping (긴 한 줄이 몇 줄로 나뉘는 것)
- 정해진 방법은 없다. 같은 한 줄이라도 여러 다른 방법으로 될 수 있다.
- 메서드나 직역 변수를 추출하는 것은 Line-Wrapping을 피하는 방법이 될 수 있다.
- where to break
- 높은 문법 수준에서 줄바꿈해라
- non-assignment 연산자에서 줄 바꿈이 일어날 경우 기호 이전에서 바꾼다. 이것은 연산자와 유사한 기호들에 적용된다.
- .
- ::
- 엠퍼샌드 <T extends Foo & Bar>
- catch 블락 속의 a pipe (catch (FooException | BarException e))
- assignment 연산자 다음에 줄바꿈 하지만, 전에 해도 괜찮다. 향상된 for문에 안의 assignment와 유사한 콜론(:)에도 적용된다.
- 메서드 또는 생성자의 이름은 여는 소괄호(()에 붙는다.
- 컴마(,)는 앞선 토큰(문자)에 붙는다.
- 람다 표현식의 화살표 근처에서는 줄바꿈 하지 않는다. 다만, 람다의 본문이 한 줄인 경우네는 화살표 뒤에서 바로 들여쓸 수 있다.
- MyLambda<String, Long, Object> lambda = (String label, Long value, Object obj) -> { ... }; Predicate<String> predicate = str -> longExpressionInvolving(str);
- line wrapping의 목적은 가독성을 높이는 것이지, 라인 수를 줄이는 것이 아니다.
- non-assignment 연산자에서 줄 바꿈이 일어날 경우 기호 이전에서 바꾼다. 이것은 연산자와 유사한 기호들에 적용된다.
- 이어지는 라인의 들여쓰기는 최소 +4 스페이스
- line-wrapping에서 줄 바꿈 할 때 최소 4개의 스페이스는 들여쓴다.
- 여러 이어지는 줄이 생길 경우 들여쓰기는 4 스페이스를 넘을 수 있다.
- 문법적으로 평행한 요소들로 linewrapping할 때만 같은 수순의 들여쓰기를 한다.
- 높은 문법 수준에서 줄바꿈해라
- 공백 문자
- 수직 공백
- 아래의 경우 하나의 공백 줄은 항상 나타난다.
- 연이은 필드, 생성자, 메소드, 이너 클래스, 정적 초기화, 인스턴스 초기화 사이에서
- 예외: 두 개의 이어지는 필드 사이의 공백은 선택이다. 논리적인 그루핑할 때 띄어쓰는 게 좋다.
- 예외 : enum 상수들 사이의 공백도 선택적
- 연이은 필드, 생성자, 메소드, 이너 클래스, 정적 초기화, 인스턴스 초기화 사이에서
- 이외에도 한줄의 공백줄은 어디서든 가독성을 높이기위해 사용될 수 있다.
- 연속된는 공백 줄은 권장되지 않는다.
- 아래의 경우 하나의 공백 줄은 항상 나타난다.
- 수평 공백
- 다음의 예약어(if, for, each)와 여는 소활호(()사이에서는 띄어쓴다.
- 다음의 예약어(else, catch)와 닫는 중괄호 (}) 사이에서 띄어쓴다.
- 모든 여는 중괄호({) 앞에서 띄어쓴다.
- 예외: @SomeAnnotation({a, b})
- 예외: String[][] x = {{"foo"}};
- 모든 이항 또는 삼항 연산자의 양쪽에서 띄어쓴따.
- 연산자와 유사한 아래의 symbol에서도 양쪽을 띄어쓴다.
- <T extends Foo & Bar>
- catch (FooException | BarException e)
- 향상된 for 문의 콜론 (:)
- 람다의 화살표
- 아래의 경우는 띄어쓰지 않는다.
- Object::toString
- object.toString()
- , : ; ) 뒤에서 띄어쓴다.
- 주석을 시작하는 //과 문장 사이에서 띄어쓴다. 여러 번 가능.
- List<String> ``list
- 배열 초기화의 괄호 양쪽에 띄어도 안띄어도 된다.
- new int[] {5, 6} and new int[] { 5, 6 } are both valid
- type annotation 과 [] or ... 사이에서 띄어쓴다.
- 연산자와 유사한 아래의 symbol에서도 양쪽을 띄어쓴다.
- 수평 맞춤 : 절대 권장되지 않음
- private int x; // permitted, but future edits private Color color; // may leave it unaligned
- 그루핑을 위한 괄호는 권장됨
- 특별한 구조들
- Enum 클래스
- Enum상수 다음의 콤마 뒤에 한 줄 또는 두 줄 띄는 것 가능
- 메서드와 doc이 없는 enum클래스도 선택적으로 가능
- private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
- 변수 선언
- 한 줄에 하나의 변수만 선언한다. int a, b; : 안됨
- 예외: for 문
- 지역 변수를 습관적으로 한 블락이 시작될 때 선언하지 않는다. 대신, 이 변수가 사용되는 곳과 가까운 곳에서 선언한다. 선언과 동시에 초기화하거나 직후에 초기화하는 것이 권장된다.
- 한 줄에 하나의 변수만 선언한다. int a, b; : 안됨
- 배열
- 배열 초기화 : 블락처럼
- new int[] { new int[] { 0, 1, 2, 3 0, } 1, 2, new int[] { 3, 0, 1, } 2, 3 } new int[] {0, 1, 2, 3}
- C-style(ex. String args[])로 선언하지 않는다.
- Switch 문
- 다른 블락처럼 2칸 들여쓴다.
- Fall-through는 주석을 단다.
- switch (input) { case 1: case 2: prepareOneOrTwo(); // fall through case 3: handleOneTwoOrThree(); break; default: handleLargeNumber(input); }
- 코드가 없더라도 default label을 작성한다.
- 예외 : 모든 경우를 작성한 enum에 대한 switch에서는 작성하지 않아도 됨.
- Annotation
- Type-use annotation
- @Target(ElementType.TYPE_USE)으로 meta-annotated된 어노테이션들은 annotated된 타입 바로 전에 붙는다.
- final @Nullable String name;
- @Target(ElementType.TYPE_USE)으로 meta-annotated된 어노테이션들은 annotated된 타입 바로 전에 붙는다.
- 클래스 / 메서드 / 생성자 어노테이션
- document block 바로 뒤에 붙고, 한 줄에 하나의 어노테이션을 적는다.
- @Deprecated @CheckReturnValue public final class Frozzler { ... }
- 예외 : 한 줄인 메서드나 생성자는 어노테이션도 한 줄에 적을 수 있다.
- @Override public int hashCode() { ... }
- 필드 어노테이션
- documentation block 바로 뒤에 붙는다. 여러 개의 어노테이션이 한줄에 붙을 수도 있다.
- @Partial @Mock DataLoader loader;
- 파라미터나 지역변수 어노테이션
- 특별한 규칙은 없다.
- Type-use annotation
- 주석
/* * This is // And so /* Or you can * okay. // is this. * even do this. */ */
- 여러 줄을 쓴다면 /* … */를 사용한다.
- Enum 클래스
- 수직 공백
Naming
- 식별자는 ASCII 문자로 작성하여 정규식의 \\w+가 매칭되도록 한다.
- 구글 스타일에서는 특별한 prefix나 suffix를 사용하지 않는다.
- name_, mName, s_name and kName
- Package 명
- 오직 소문자와 숫자만 사용한다(_ 사용하지 않는다.)
- com.example.deepspace, not com.example.deepSpace or com.example.deep_space
- Class 명
- UpperCamelCase를 사용한다.
- 명사나 명사구를 사용한다.
- 테스트 클래스는 끝에 Test를 붙인다.
- 테스트 클래스가 하나의 클래스만 커버한다면, 그 클래스명 뒤에 Test를 붙인다.
- Method명
- LowerCamelCase를 사용한다.
- 동사나 동사구를 사용한다.
- 상수 명
- UPPER_SNAKE_CASE를 사용한다.
- 상수가 아닌 필드 명, 매개변수명, 지역변수명
- LowerCamelCase
- 명사나 명사구
- 지역변수는 final이나 immutable이더라도 상수로 취급하지 않는다.
- 타입 변수 명
- 하나의 대문자로 표현
Programming Practices
- @Override는 항상 사용한다.
- Caught exception은 비우지 말고, 꼭 작성한다.
- 테스트에서 기대된 예외에서는 작성하지 않아도 된다.
- Static members는 항상 클래스를 명시해서 사용한다.
Javadoc
- 일반적인 포맷
한 줄에 담을 수 있으면, 한 줄도 가능. 하지만 @return과 같은 블럭 태그가 없을 때만 가능./** An especially short bit of Javadoc. */
- /** * Multiple lines of Javadoc text are written here, * wrapped normally... */ public int method(String p1) { ... }
- 문단
- 맨 앞에 <p>를 적고 , 빈칸을 두지 않고 내용을 작성한다.
- 문단과 문단사이에는 한줄을 띈다. 즉, * 하나만 있다.
- Block Tags
- **@param, @return, @throws, @deprecated 가 순서대로 쓰인다. 이걸 쓸려면 꼭 설명을 붙여야한다.**
- 설명이 길어지면 줄바꿈 후 네 칸을 들여쓰고 이어 작성한다.
- The summary fragment
- Javadoc은 짧은 summary fragment로 시작한다.
- 이것은 짧게 이 기능을 설명한다.
- 완성된 문장이 아닌 명사구나 동사구로 작성한다.
- Javadoc을 작성해야하는 곳
- 최소한, 모든 public class와 이것의 public 또는 protected 멤버에 작성되어야하고, 몇 예외를 밑에 달아야한다.
- 예외: 너무 당연한 것에는 사용하지 않다.
- 예외: overrides
- 주석을 설명이 필요하다면, Javadoc으로 작성한다.
'General' 카테고리의 다른 글
[DDD] 값객체와 엔티티, 도메인 서비스 (0) | 2023.06.03 |
---|---|
MSA(Micro Service Architecture) 이해해보기 (0) | 2023.05.22 |
객체지향 설계 원칙 - SOLID (0) | 2022.11.14 |
TDD(테스트 주도 개발) 시작하는 방법 (0) | 2022.11.06 |
[로깅 전략] 로그는 어떻게 남겨야할까? (중앙집중식 로깅) (0) | 2022.10.26 |