보다 깔끔한 코드를 위해 Google Java Style Guide를 정리하고자 한다.
Google Java Style Guide는 Google의 Java 코딩 표준을 정리한 문서이다.
https://google.github.io/styleguide/javaguide.html
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
문서를 읽고 개인적으로 중요하다고 생각한 것들에 대해 작성할 계획이다.
1. Introduction (소개)
1.1 Terminology notes (용어 노트)
이후 언급할 class(클래스)는 일반적인 클래스, enum 클래스, 인터페이스, @interface를 포괄적으로 의미한다.
이후 언급할 member(멤버)는 필드, 메서드, 생성자, 중첩 클래스를 포괄적으로 의미한다.
이후 언급할 comment(주석)은 '구현에 대한 주석'을 의미한다. 문서에 대한 주석은 Javadoc라는 용어를 사용한다.
2. Source file basics (소스 파일 기본 사항)
2.1 File name (파일 이름)
파일 이름은 최상위 클래스의 이름과 .java 확장자로 구성한다.
2.2 File encoding: UTF-8 (파일 인코딩: UTF-8)
소스 파일은 UTF-8로 인코딩한다.
3. Source file structure (소스 파일 구조)
소스 파일 구성은 다음 순서를 따른다.
- License 혹은 저작권 정보
- Package 정보
- Import 정보
- 최상위 클래스
3.1 License or copyright informations, if present (라이선스 혹은 저장권 정보(있는 경우))
라이선스 혹은 저작권 정보가 파일에 있는 경우 작성한다.
3.2 Package statement
package문은 줄 바꿈을 하지 않는다.
package문은 열 제한을 적용하지 않는다.
3.3 import statements
static imports, non-static imports 순으로 작성한다.
static imports, non-static imports가 모두 있는 경우 빈 줄 하나로 두 블록을 구분한다. 각 블록 안에는 빈 줄을 작성하지 않는다.
3.4 Class declaration (클래스 선언)
하나의 최상위 클래스 선언만 해야 한다.
** 다른 클래스나 멤버 선언 시 논리적 순서를 따르는 것이 가장 중요하다.
(ex - 새 메서드를 습관적으로 맨 아래에 추가하지 않는다. 이는 논리적 순서가 아니라 추가된 날짜별 순서가 되기 때문이다.)
** 오버로딩(여러 생성자 포함)은 각각을 떨어뜨리지 않는다. 이는 식별자가 서로 달라도 적용된다.
4. Formatting (포맷)
4.1 Braces (중괄호)
4.1.1 Use of optional braces (중괄호 활용)
중괄호는 if, else, for, do, while 등에 사용된다.
중괄호는 K&R style을 따른다.
4.1.2 Nonempty blocks: K & R style (블록이 비어있지 않은 경우)
아래 자세한 설명이 없다면 여는 중괄호( { ) 앞에는 줄 바꿈을 하지 않는다.
여는 중괄호( { ) 뒤에는 줄 바꿈을 한다.
닫는 중괄호( } ) 앞에는 줄 바꿈을 한다.
닫는 중괄호( } ) 뒤에는 줄 바꿈을 한다. 이것은 중괄호가 해당 블록의 본문을 종료하는 경우에만 해당된다.
예를 들어 else 혹은 쉼표( , )가 나오는 경우엔 줄바꿈을 하지 않는다.
google java style guide의 예시(K&R style)
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();
}
{
int x = foo();
frob(x);
}
}
};
4.1.3 Empty blocks: may be concies (블록이 비어있는 경우: 간결할 수 있음)
블록이 비어있는 경우 K&R 스타일 혹은 간결한 활용(줄 바꿈 없이 활용)을 할 수 있다.
다중 블록의 일부인 경우 간결한 활용을 할 수 없다.
google java style guide의 예시(간결한 활용 허용 예시)
// This is acceptable(허용)
void doNothing() {}
// This is equally acceptable(허용)
void doNothingElse() {
}
// This is not acceptable: No concise empty blocks in a multi-block statement
//(허용 안함)
try {
doSomething();
} catch (Exception e) {}
4.3 One statement per line (한 줄에 하나의 명령문)
각 명령문 뒤엔 줄바꿈을 한다.
4.4 Column limit: 100 (열 제한: 100)
Java 코드의 각 열은 100자 이하여야 한다. 이때, 1자는 모든 Unicode code point를 의미한다.
예외:
- 열 제한을 준수할 수 없는 줄(Javadoc의 URL 등)
- package, import문
- shell에 복사 붙여 넣기를 할 수 있는 주석
- 매우 긴 식별자
4.5 Line-wrapping (줄 바꿈)
여기서 의미하는 줄 바꿈은 한 줄로 작성해도 동작하는 코드를 여러 줄로 나누는 경우이다.
4.5.1 Where to break (중단할 위치)
- 메서드 혹은 생성자 이름은 뒤의 여는 괄호( ( )와 붙어 있어야 한다.
- 쉼표는 계속 붙어 있어야 한다.
- 람다는 단일 표현식으로 구성된 경우가 아니라면 람다의 화살표 다음엔 줄 바꿈이 일어나지 않아야 한다.
google java style guide의 예시(람다의 경우)
//그 외의 경우
MyLambda<String, Long, Object> lambda =
(String label, Long value, Object obj) -> {
...
};
//단일 표현식
Predicate<String> predicate = str ->
longExpressionInvolving(str);
4.6 Whitespace (공백)
4.6.1 Vertical Whitespace(세로 공백 - Enter)
다음의 경우 하나의 세로 공백을 둔다.
클래스의 멤버 혹은 초기화 사이(필드, 생성자, 메서드, 중첩 클래스, 초기화블록 등)
예외: 두 연속된 필드 사이의 빈 줄은 선택사항이다.(빈 줄이 상황에 따라 논리적인 그룹을 만들 수 있음)
가독성을 향상하는 위치엔 빈 줄이 있을 수 있다.(이때 여러 줄의 빈 줄이어도 되지만 권장하진 않는다.)
4.6.2 Horizontal whitespace (가로 공백)
규칙 요구사항이나 상수, 주석, 문서를 제외하고 공백은 다음 위치에만 있는다.
- if, for, catch와 같은 예약어와 다음 여는 괄호( ( ) 사이.
- else, catch와 같은 예약어 앞의 닫는 중괄호( } ) 사이
- 단, 아래 두 경우는 닫는 중괄호를 붙인다.
- 어노테이션 활용 시 - @SomeAnnotation({a, b})
- 배열 선언 시 - String[][] x = {{"foo"}};
- 이항 혹은 삼항 연산 시
- <T extends Foo & Bar>
- catch (FooException | BarException)
- for(String s : sArr)
- (String str) -> str.length() 등
- ( :: )과 ( . )은 붙여서 사용한다.
- Object::toString()
- object.toString()
- 이중 슬래시( // ) 주석 사용 시 여러 개의 공백 사용 가능
- 선언 유형과 변수 사이
- List<String> list
- 배열 초기화 시
- new int[] {1, 2},
- new int[] { 1, 2 } 둘 다 허용
4.6.3 Horizontal alignment: never required (수평정렬: 필요 없음)
Google Java Style에선 가로 정렬을 하지 않는다.
google java style guide의 예시(가로 정렬 예시)
private int x; // this is fine
private Color color; // this too
private int x; // permitted, but future edits
private Color color; // may leave it unaligned
해당 정렬은 이후의 유지 관리가 어려워지기 때문. 만약 한 줄만 어긋나면 이후 형식이 엉망이 될 수 있다.
4.7 Grouping parentheses: recommended (그룹화 괄호: 권장)
코드를 잘못 해석할 가능성이 없는 경우 괄호 생략 가능
4.8 Specific constructs (특수한 구성)
4.8.1 Enum classes
열거형 상수 뒤에 오는 콤마 다음의 줄 바꿈은 선택 사항이다. 빈 줄도 허용한다.
google java style guide의 예시(enum 클래스의 경우)
private enum Answer {
YES {
@Override public String toString() {
return "yes";
}
},
NO,
MAYBE
}
//아래도 허용
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
4.8.2 Variable declarations (변수 선언)
4.8.2.1 One variable per declaration (선언 당 한 변수만)
한 줄엔 하나의 변수만 선언한다. int a, b;등의 형태는 사용하지 않는다.
예외: for문의 헤더엔 여러 변수 선언 가능
4.8.2.2 Declared when needed (필요할 때 선언하기)
지역 변수를 블록의 시작 부분에 습관적으로 선언하지 않는다.
지역 변수는 처음 사용되는 지점에 가깝게 선언한다.
4.8.3 Arrays
4.8.3.1 Array initializers: can be "block-like" (배열 초기화: 블록 형태일 수 있음)
배열 초기화는 블록 형태로 할 수 있다.
google java style guide의 예시(배열 선언 방식)
new int[] { new int[] {
0, 1, 2, 3 0,
} 1,
2,
new int[] { 3,
0, 1, }
2, 3
} new int[]
{0, 1, 2, 3}
위 형태는 모두 가능하다.
4.8.3.2 No C-style array declarations (C 스타일의 배열 선언하지 않기)
배열 선언은 String args[]가 아닌 String[] args와 같이 한다.
4.8.4 Switch statements
4.8.4.2 Fall-through: commented (완료되지 않은 경우: 주석 처리)
swtich문 블록 내에서 갑자기 종료되는 경우 주석으로 표시한다.
google java style guide의 예시(switch문 중간 종료의 경우)
switch (input) {
case 1:
case 2:
prepareOneOrTwo();
// fall through
case 3:
handleOneTwoOrThree();
break;
default:
handleLargeNumber(input);
}
4.8.4.3 Presence of the default label (default 라벨의 유무)
default 안에 코드가 없더라도 포함한다.
예외: enum과 같이 모든 경우의 값을 명시할 수 있는 경우 default 생략 가능
4.8.5 Annotations
4.8.5.1 Type-use annotations (Type-use 어노테이션)
Type-use annotations는 타입 정의 바로 앞에 나온다.
google java style guide의 예시(Type-use annotations)
final @Nullable String name;
public @Nullable Person getPersonByName(String name);
4.8.5.2 Class annotations
클래스에 적용되는 annotations는 블록 바로 위에 있으며 한 줄에 하나씩 적는다.
google java style guide의 예시(Class annotations)
@Deprecated
@CheckReturnValue
public final class Frozzler { ... }
4.8.5.3 Method and constructor annotations
메서드 및 생성자 annotations는 Class annotations와 동일하다.
예외: annotation이 하나이고 매개변수가 없으면 한 줄로 적을 수 있다.
google java style guide의 예시(Method and constructor annottions)
@Deprecated
@Override
public String getNameIfPresent() { ... }
@Override public int hashCode() { ... }
4.8.5.4 Field annotations
필드 annotations는 여러 개가 같은 줄에 나열될 수 있다.
google java style guide의 예시(Field annotations)
@Partial @Mock DataLoader loader;
4.8.5.5 Parameter and local annotations
파라미터 혹은 지역 변수에 대한 규칙은 없다.
4.8.6 Comments (주석)
여기서의 주석은 구현에 대한 주석으로 문서에 대한 주석과 다르다.
4.8.6.1 Block comments style (블록 주석 스타일)
블록 형태의 주석은 /* ... */ 혹은 //을 활용한다.
/* ... */를 활용할 땐 후속줄의 *와 이전 줄의 *가 정렬되어 있어야 한다.
google java style guide의 예시(블록 형태의 주석)
/*
* This is // And so /* Or you can
* okay. // is this. * even do this. */
*/
5.8.7 Modifiers (제어자)
제어자는 다음 순서로 작성한다.
public protected private abstract default static final transient volatile synchronized native strictfp
예를 들어 static이고 final이고 private인 변수는 private static final 순으로 작성한다.
4.8.8 Numeric Literals (숫자 리터럴)
long형 정수 리터럴은 소문자 l이 아닌 대문자 L을 사용한다.(숫자 1과의 혼동을 피하기 위해)
예를 들어 30000000l이 아닌 30000000L의 형태로 사용한다.
5. Naming
5.1 Rules common to all identifiers (모든 식별자에 공통되는 규칙)
ASCII문자와 숫자만 사용한다. 일부의 경우 밑줄을 허용한다.
Google java style에선 특수한 접두사 혹은 접미사를 사용하지 않는다.(name_, mName, s_name, kName 등)
5.2 Rules by identifier type
5.2.1 Package names
패키지 이름은 소문자와 숫자만 사용한다. 연속된 단어는 단순하게 연결한다.
예를 들어 com.example.deepSpace 혹은 com.example.deep_space가 아닌 com.example.deepspace을 사용한다.
5.2.2 Class names
클래스 이름은 UpperCamelCase로 작성한다. 일반적으로 명사 혹은 명사구로 작성한다.
인터페이스 이름은 명사일 수 있지만 때로는 형용사(Readable 등)일 수 있다.
테스트 클래스는 Test로 이름을 끝낸다. ex) HashImpTest
5.2.3 Method names
메서드 이름은 lowerCamelCase로 작성한다. 일반적으로 동사 혹은 동사구로 작성한다.
JUnit 테스트 메서드 이름에선 논리적인 설명을 위해 밑줄을 활용할 수 있다. ex) transferMoney_deductsFromSource
5.2.4 Constant names
상수 이름은 UPPER_SNAKE_CASE로 작성한다.
여기서의 상수는 내용이 불변인 정적 final 필드이다. 상수의 구분 예시는 아래와 같다.
google java style guide의 예시(상수와 상수가 아닌 것의 차이)
// Constants
static final int NUMBER = 5;
static final ImmutableList<String> NAMES = ImmutableList.of("Ed", "Ann");
static final Map<String, Integer> AGES = ImmutableMap.of("Ed", 35, "Ann", 32);
static final Joiner COMMA_JOINER = Joiner.on(','); // because Joiner is immutable
static final SomeMutableType[] EMPTY_ARRAY = {};
// Not constants
static String nonFinal = "non-final";
final String nonStatic = "non-static";
static final Set<String> mutableCollection = new HashSet<String>();
static final ImmutableSet<SomeMutableType> mutableElements = ImmutableSet.of(mutable);
static final ImmutableMap<String, SomeMutableType> mutableValues =
ImmutableMap.of("Ed", mutableInstance, "Ann", mutableInstance2);
static final Logger logger = Logger.getLogger(MyClass.getName());
static final String[] nonEmptyArray = {"these", "can", "change"};
5.2.5 Non-constant field names
Constant가 아닌 필드는 lowerCamelCase로 작성한다. 일반적으로 명사 혹은 명사구로 작성한다.
5.2.6 Parameter names
매개변수 이름은 lowerCamelCase로 작성한다.
공용 메서드에선 한 문자로 된 매개변수 이름 사용을 지양한다.
5.2.7 Local variable names
지역 변수 이름은 lowerCamelCase로 작성한다.
final이고 불변인 경우에도 지역 변수는 상수로 취급하지 않고 상수 스타일로 작성하지 않는다.
5.2.8 Type variable names
각 타입 변수 이름은 아래 두 가지 스타일 중 하나로 활용한다.
- 단일 대문자, 선택적 단일 숫자(ex- E, T, T2, X)
- 클래스에 사용되는 형식의 이름 + 대문자(ex-RequestT, FooBarT)
5.3 Camel case: defined
HTTP, IPv6 등의 약어를 Camel case로 변환하는 경우는 다양하지만 Google Java Style은 다음의 방법을 따른다.
- 구문을 일반 ASCII로 변환하고 아포스트로피( ' )를 제거한다. ex- Müller -> Mulleres
- 위의 결과를 공백으로 나누어 단어를 구분한다.
- 모든 항목을 소문자로, 첫 문자만 대문자로 지정한다.
- 모든 단어를 단일 식별자로 결합한다.
google java style guide의 예시 (약어가 포함된 경우)
Prose form | Correct | Incorrect |
XML HTTP request | XmlHttpRequest | XMLTHHPRequest |
new customer ID | newCustomerId | newCustomerID |
inner stopwatch | innerStopwatch | innerStopWatch |
supports IPv6 on iOS? | supportsIpv6OnIos | supportsIPv6OnIOS |
YouTube importer | YouTubeImporter YoutubeImporter(허용. 권장하지 않음) |
6. Programming Practices (프로그래밍)
6.1 @Override: always used (@Override: 항상 사용)
@Override는 사용한 경우 항상 적는다.
예외: 상위 메서드가 @Deprecated인 경우 생략 가능
6.2 Caught exceptions: not ignored (예외: 무시하기 않기)
예외가 발생했을 때 이에 대한 아무런 작업도 하지 않는 것은 올바르지 않다.
catch 블록에서 아무런 작업도 하지 않는 것이 올바른 경우, 이유를 주석으로 설명해야 한다.
google java style guide의 예시(catch 블록에 주석이 필요한 경우)
try {
int i = Integer.parseInt(response);
return handleNumericResponse(i);
} catch (NumberFormatException ok) {
// it's not numeric; that's fine, just continue
}
return handleTextResponse(response);
예외: 테스트에서 이름이 expected인 경우 주석으로 설명하지 않아도 된다.
(expected는 예상 유형의 예외를 발생시키는지 확인하기 위한 일반적인 단어이므로)
google java style guide의 예시(expected 경우)
try {
emptyStack.pop();
fail();
} catch (NoSuchElementException expected) {
}
6.3 static members: qualified using class (static 멤버: 클래스를 이용)
클래스의 static 메서드를 활용할 때 해당 클래스 이름으로 접근해야 한다.
google java style guide의 예시 (static 클래스의 활용)
Foo aFoo = ...;
Foo.aStaticMethod(); // good
aFoo.aStaticMethod(); // bad
somethingThatYieldsAFoo().aStaticMethod(); // very bad
6.4 Finalizers: not used (finalize: 사용하지 않기)
Object 클래스의 finalize는 사용하지 않는다.
7. Javadoc
7.1 Formatting (포맷)
7.1.1 General form (일반 형태)
Javadoc의 기본 형식은 아래와 같다.
google java style guide의 예시 (Javadoc 기본 형식)
//여러 줄인 경우
/**
* Multiple lines of Javadoc text are written here,
* wrapped normally...
*/
public int method(String p1) { ... }
//한 줄인 경우
/** An especially short bit of Javadoc. */
7.3 Where Javadoc is used (Javadoc이 사용되는 곳)
Javadoc은 일부 예외를 제외하고 pualic 클래스와 public, protected 멤버에 대해 작성이 필요하다.
예외: 설명이 필요 없는 간단하고 명백한 경우 작성하지 않는다.
'Java > Java' 카테고리의 다른 글
Java - 배열 복사와 반복, clone()과 arraycopy() 속도 비교 (0) | 2023.11.21 |
---|---|
Java - Formatter (1) | 2023.10.23 |
Java - .of .asList .emptyList (0) | 2023.10.02 |
Java - 생성자, 초기화 블록 (1) | 2023.09.25 |
Java - Java 변수, 메서드 (0) | 2023.09.24 |