개발자를 위한
Java Programming Style Guide (ref. Google style guide)
4.6 공백(whitespace)
- 세로 공백(Vertical Whitespace)
다음과 같은 경우에 하나의 빈줄은 항상 나타납니다.
1) 클래스의 연속된 멤버(consecutive member) 또는 초기자(initializer) 사이 : 필드(field), 생성자(constructors), 메서드(method), 중첩 클래스(nested classes), 정적 초기자(static initializers), 인스턴스 초기자(instance initializers)
- 예외(exception) : (다른 코드가 없는) 두 개의 연속된 필드 사이에서 빈줄 사용은 선택사항입니다. 필드의 논리적 그룹을 만들기 위해 필요에 따라 빈줄을 사용할 수 있습니다.
- 예외(exception) : 열거형 상수(enum constants) 사이의 빈 줄은 다른 섹션에서 다룹니다.
2) 이 문서의 다른 섹션인 소스 파일 구조(Source File Construction)나 임포트 구문(Import Statements)에서 정의된 대로 세로 공백을 사용할 수 있습니다.
예를 들어, 코드를 논리적인 하위 섹션으로 구조화하기 위한 구문 사이에서 처럼, 코드의 가독성을 개선시키기 위해서라면 어디든지 빈줄 하나를 사용할 수 있습니다. 첫번째 멤버(first member)나 초기자(initializer) 전에 빈줄을 두거나, 클래스의 마지막 멤버(last member)나 초기자(initializer) 다음에 빈줄을 두는 것은 권장하지 않고, 비권장하지도 않습니다.
여러 개의 연속되는 공백 라인(blank line)은 허용되지만, 결코 필수(또는 권장)는 아닙니다.
- 가로 공백(Horizontal whitespace)
프로그래밍 언어(language)나 다른 스타일 규칙(style rules)에서 요구하는 것을 넘어, 리터럴(literals)과 주석(comment) 및 Javadoc을 제외하고 단일 ASCII 스페이스도 다음 위치에서만 사용해야 합니다.
1) if, for, catch와 같은 예약어를 해당 줄에서 뒤에 오는 여는 괄호(()와 분리하기 위해 스페이스 사용 (ex. if (… )
2) else나 catch와 같은 예약어를 해당 줄에서 앞에 오는 닫는 중괄호(})와 분리하기 위해 스페이스 사용 (ex. …) else )
3) 여는 중괄호({) 앞에 스페이스(띄어쓰기)를 사용하지 않는 2가지 예외가 있습니다.
- @SoneAnnotation({a, b}) (‘({‘ 사이에 스페이스 사용되지 않음)
- String[][] x = {{“foo”}}; (‘{{‘ 사이에 스페이스 필요 없음)
4) 2항이나 3항 연산자 양쪽에 있습니다. 다음과 같은 “연산자와 유사한(operator-like)” 기호에도 적용됩니다.
- 결합형으로 묶여 있는 엠퍼센트(&) : <T extends Foo & Bar>
- 여러 개의 예외를 처리하는 catch 블록의 파이프 : catch (FooException | BarException e)
- 향상된 for 구문(“foreach”) 내의 콜론(:)
- 람다 식의 화살표: (String str) -> str.length()
그러나, 다음과 같은 경우에는 스페이스를 사용하지 않습니다.
- Object::toString과 같이 작성된 메서드(method) 참조에 사용되는 2개의 콜론(::)
- object.toString()과 같이 작성된 dot 구분자(. seperator)
5) , : ; 뒤나 캐스트(cast)의 닫는 괄호( ‘)’ ) 뒤에 스페이스 사용
6) 라인의 끝에서 코멘트(comment)의 시작인 더블 슬래쉬(//)의 앞뒤 양쪽
7) 유형과 변수 선언 사이 : List<String> list
8) (Optional) 배열 초기자(array initializer)의 양쪽 중괄호 사이
- new int[] {5, 6} 와 new int[] { 5, 6 } 모두 유효함
9) 어노케이션 유형과 대괄호([]) 혹은 … 사이
이 규칙은 라인의 시작이 끝부분에서 스페이스를 추가하는 부분에 대한 요구사항이나 금지사항이 아닙니다. 단지 라인의 내부 공간에서의 규칙 만을 다룹니다.
- 가로 정렬(Horizontal alignment) : 필요 없음(never required)
Terminology Note(용어집) : 수평 정렬은 특정 토큰이 이전 라인의 다른 토큰 바로 아래에 나타나도록 코드에 다양한 숫자의 공백을 추가하는 방법입니다.
이 방법은 허용되지만, 필수로 요구하지는 않습니다. 이미 사용된 부분에서 수평 정렬을 유지할 필요도 없습니다.
정렬이 없는 경우와 정렬을 사용하는 경우에 대한 예제는 다음과 같습니다.
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
Tip : 정렬은 가독성에 도움이 될 수 있지만, 향후 유지관리(maintenance)에 문제가 됩니다. 한줄만 수정해야 하는 미래의 변화를 고려해 보면, 이 변화로 인해 이전에 만족스러웠던 서식이 엉망이 될 수 있습니다. 이것은 코더에게 더 자주 근처 라인의 공백을 조정하도록 프롬프트를 표시하여 연쇄적인 재형식화(reformatting)를 유발할 수 있습니다. 그 한 라인의 변경은 “폭발 반경(blast radius)”를 가지게 됩니다. 최악의 경우에 무의미한 작업을 초래할 수 있지만, 기껏해야 버전 정보를 손상시키고 검토자의 속도를 늦추며 병합 충돌을 일으키는 정도입니다.
4.7 그룹화 괄호(Grouping parentheses) : 권장(recommended)
선택적인 그룹화 괄호는 작성자(author)와 검토자(reviewer) 사이에 그것들이 없어도 코드를 잘못 해석하지 않고 코드를 더 읽기 쉽게 만들 수 있다는 점에 동의하는 경우에만 생략 가능합니다. 모든 리더(reader)가 전체 Java 연산자 우선순위 테이블을 기억하고 있다고 가정하는 것은 전혀 합리적이지 않습니다.
4.8 특별한 구조(specific constructs)
1. Enum Classes
열거형 상수(enum constant) 다음에 오는 각 쉼표 뒤에 줄 바꿈(line break)은 선택 사항입니다. 추가 빈줄(보통 한 줄)도 허용됩니다. 다음은 한가지 가능한 예제입니다.
private enum Answer {
YES {
@Override public String toString() {
return "yes";
}
},
NO,
MAYBE
}
메서드(method)가 없고, 상수에 대한 문서가 없는 열거형 클래스(enum class)는 배열 초기자(array initializer)인 것처럼 선택적으로 형식화 될 수 있습니다.
private enum Suit { CLUBS, HEARTS, SPADES, DIAMONDS }
열거형 클래스(enum class)는 클래스이기 때문에 클래스에 적용되는 모든 형식 지정 규칙이 적용됩니다.
2. 변수 선언(Variable declarations)
1) 선언 당 하나의 변수 (One variable per declaration)
모든 변수 선언(필드 또는 로컬)은 하나의 변수만 선언합니다. int a, b;와 같은 선언은 사용하지 않아야 합니다.
예외) for 루프문 헤더에는 여러 변수 선언이 허용됩니다.
2) 필요할 때 선언(Declared when needed)
지역 변수(local variable)를 포함하고 있는 블록이나 블록과 유사한 구조의 시작 부분에 습관적으로 선언하지 않아야 합니다. 대신에, 지역 변수는 범위를 최소화하기 위해 처음 사용되는 지점에(사용 이유와 함께) 가까운 곳에 선언합니다. 지역변수를 선언한 후, 일반적으로 초기자(initializer)가 있거나 선언 바로 다음에 지역 변수를 초기화합니다.
3. 배열(Arrays)
1) 배열 초기자(Array initializer) : “블록과 유사한” 형태가 될 수 있음
배열 초기자는 “블록과 유사한 구조”처럼 형식화 될 수 있습니다. 예를 들어 아래와 같은 형태는(완전한 목록은 아니지만 : not exhaustive list) 모두 유효합니다.
new int[] {
0, 1, 2, 3
}
new int[] {
0,
1,
2,
3,
}
new int[] {
0, 1,
2, 3
}
new int[]
{0, 1, 2, 3}
2) C-Style로 배열을 선언하면 안 됩니다.
대괄호는 변수의 일부가 아니라, 유형의 일부가 되어야 합니다.
String args[]가 아니라 String[] args의 형태로 선언되어야 합니다.
4. 스위치 구문(switch statements)
Terminology Note(용어집) : 스위치 블록의 괄호 안에서 하나 이상의 구문 그룹(statement group)이 있을 수 있습니다. 각 구문 그룹은 하나 이상의 구문이 있는 하나 이상의 스위치 레이블(switch labels)로 이루어져 있습니다.(마지막 구문 그룹에는 0개 이상의 구문이 있습니다.)
1) 들여쓰기 (Indentation)
다른 블록과 마찬가지로, 스위치 블록의 내용은 +2만큼(+2 스페이스) 들여쓰기 됩니다.
스위치 레이블(switch label) 뒤에는 줄 바꿈이 있고, 들여쓰기 수준은 블록을 여는 것처럼 정확히 +2 증가합니다. 다음 스위치 레이블은 블록이 닫힌 것처럼 이전 들여쓰기 수준으로 돌아갑니다.
2) 실현되지 못한 부분 : 주석처리(Fall-through : commented)
스위치 블록 내에서 각 구문 그룹(statement group)은 갑자기 종료되거나(break, continue, return, 또는 thrown exception 구문과 함께), 다음 구문 그룹이 실행됨을 나타내거나, 다음 구문 그룹으로 계속됨을 나타내는 주석으로 표시될 수 있습니다. 실현되지 못한 부분(fall-through)에 대한 아이디어를 전달하는 주석으로 충분합니다.(일반적으로 //로 실현되지 못한 부분을 표시) 스위치 블록의 마지막 구문 그룹에는 이 특별한 주석이 필요하지 않습니다.
예를 들면,
switch (input) {
case 1:
case 2:
prepareOneOrTwo();
// fall through
case 3:
handleOneTwoOrThree();
break;
default:
handleLargeNumber(input);
}
case 1 뒤에는 주석이 없음을 유의하세요. 구문 그룹의 끝에만 주석이 있습니다.
3) default 케이스는 기본임 (The default case is present)
각 스위치 구문에는 코드가 없는 경우에도 default 구문 그룹이 포함되어 있습니다.
예외(exception) : 열거형 유형(enum type)에 대한 스위치 구문은 해당 유형의 모든 가능한 값을 가지는 명시적 사례를 포함하는 경우 default 구문을 생략할 수 있습니다. 이 때문에 IDE나 다른 정적 분석 도구에서 누락된 사례가 있는 경우 경고를 나타낼 수 있습니다.
5. 어노테이션 (Annotations)
클래스(class), 메서드(method)나 생성자(constructor)에 적용되는 어노테이션은 문서 블록(documentation block) 바로 다음에 나타납니다. 그리고 각 어노테이션은 그 자체 행에 나열됩니다.(즉, 라인 당 하나의 어노테이션). 이와 같은 줄바꿈(line break)은 라인 변경(line-wrapping)(섹션 line-wrapping)을 구성하지 않기 때문에 들여쓰기 수준이 증가하지 않습니다.
예를 들면,
@Override
@Nullable
public String getNameIfPresent() { ... }
예외(Exception) : 매개변수가 없는 단일 어노테이션은 서명(signature)의 첫번째 라인과 함께 대신 나타날 수 있습니다. 예를 들면 다음과 같습니다.
@Override public int hashCode() { ... }
필드(field)에 적용된 어노테이션은 문서 블록(documentation block)의 바로 다음에 나타납니다. 그러나 이런 경우, 여러 개의 어노테이션(매개변수화 가능한)이 동일 라인에 나열될 수 있습니다. 예를 들면 다음과 같습니다.
@Partial @Mock DataLoader loader;
6. 주석 (Comments)
이 섹션에서는 구현 주석(implementation comments : 소스코드에 대한 주석)만 다룹니다. Javadoc에 대해서는 별도의 Javadoc 섹션에서 다룹니다.
모든 줄바꿈에는 임의의 공백(whitespace)이 있고, 그 다음에 구현 주석이 올 수 있습니다. 그러한 주석은 비어 있는 라인(line non-blank)이 아닌 것으로 취급합니다(render).
1) 블록 주석 스타일 (block comment style)
블록 주석은 주변 코드와 같은 수준으로 들여쓰기 합니다. 블록 주석은 /* …. */ 형태나 // …. 형태로 나타납니다. 여러 라인의 /* … */ 주석에서 후속 라인은 이전 라인의 *와 정렬된 *로 시작해야 합니다.
/*
* This is
* okay.
*/
// And so
// is this.
/* Or you can
* even do this. */
블록별표나 다른 문자와 함께 그려진 박스(box)는 주석에 포함되지 않습니다.
Tip : 여러 라인의 주석을 작성할 때, 자동 코드 포맷터(automatic code formatters)가 필요할 때 라인을 다시 감싸도록(re-wrap)(단락 스타일 : paragraph-style) 하기 위해서 /* … */ 형태를 사용하세요. 대부분의 포맷터(formatters)는 // … 형태의 주석 블록에서 라인을 다시 감싸지 않습니다(don’t re-wrap).
7. 수정자(Modifiers)
클래스(class)와 멤버(member) 수정자가 있는 경우, Java 언어 표준(Java language specification)에서 권장하는 순서대로 나타납니다.
public protected private abstract default static final transient volatile synchronized native strictfp
8. 숫자형 문자열(Numeric Literals)
long 형 값을 가지는 정수 문자열(integer literals)은 대문자 L 접미사를 사용하고, 결코 소문자를 사용하지 않는다. (숫자(digit)1과의 혼동을 피하기 위해서) 예를 들면, 300000000l 이 아니라 300000000L을 사용한다.
댓글을 달아 주세요
댓글 RSS 주소 : http://www.yongbi.net/rss/comment/892