[우아한테크코스/프리코스] Java Code Conventions
파일의 마지막은 새줄 문자 LF로 끝나야 한다.
파일 마지막에 개행을 해야 하는 이유?
POSIX명세가 그러하기 때문이다. 명세에는 프로세스 환경, 파일과 디렉토리등 다양한 개념을 규격화하고 있다.
ref

On Save의 Ensure every saved file ends with a line break ✅
약어의 중간단어를 소문자로 표기하고 프로젝트 별로 모두 대문자로 표기할 약어의 목록을 명시하는 방식을 이용해 가독성을 높이고 규칙을 단순화한다.
예) HTTP+API+URL의 클래스 이름의 경우 - 대문자로 표기할 약어의 목록을 정의하지 않은 경우 : HttpApiUrl - API만 대문자로 표기할 약어의 목록에 있을 경우 : HttpAPIUrl -HTTP,API,URL 모두 대문자로 표기할 약어의 목록에 있을 경우 : HTTPAPIURL
패키지 이름은 소문자를 사용하여 작성한다.
단어별 구분을 위해 ‘_’나 대문자를 섞지 않는다.
//Good ex
package com.navercorp.agigateway
//Bad
package com.navercorp.apiGateway
package com.navercomp.api_gateway
클래스 이름은 단어의 첫 글자를 대문자로 시작하는 대문자 카멜표기법을 사용한다.
// Good Exemples
public class Reservation;
public class AccessToken;
// Bad Exemples
public class reservation;
public class Accesstoken;
클래스 이름은 명사나 명사절로 짓는다.
인터페이스의 이름은 명사/명사절로 혹은 형용사/형용사절로 짓는다.
// Good Exemples
public interface RowMapper {
public interface AutoClosable {
JUnit 등으로 작성한 테스트 코드를 담은 클래스는 ‘Test’를 마지막에 붙인다.
// Good Exemples
public class WatcherTest {
메서드 이름은 첫 단어를 소문자, 이어지는 단어의 첫글자를 대문자로 작성한다.
메서드명은 기본적으로 동사로 시작한다.
동사사용 : renderHtml()
전환메서드의 전치사 : toString()
Builder 패턴 적용한 클래스의 메서드의 전치사 : withUserId(String id)
“static final”로 선언되어 있는 필드는 상수로 간주한다.
상수 이름은 대문자로 작성하며, 복합어는 언더스커오를 사용하여 단어를 구분한다.
public final int UNLIMITED = -1;
public final String POSTAL_CODE_EXPRESSION = “POST”;
상수가 아닌 클래스의 멤버변수/지역변수/메서드 파라미터에는 소문자 카멜표기법을 사용한다.
private boolean authorized;
private int accessToken;
메서드 블럭 범위 이상의 생명주기를 가지는 변수에는 1글자로 된 네이밍을 금지.
반복문의 인덱스나 람다 표현식의 파라미터 등 짧은 범위의 임시 변수에는 관례적으로 가능.
HtmlParser parser = new HtmlParser();
클래스 ,필드,메서드,변수값,import문 등의 소스 구성요소를 선언할 때 고려해야할 규칙이다.
클래스를 import 할때는 와일드카드 (*)없이 모든 클래스명을 다 쓴다.
// Good Examples
import java.util.List;
import java.util.ArrayList;
// Bad Examples
import java.util.*;
클래스/메서드/멤버변수의 제한자는 Java Language Specification에서 명시한 아래의 순서로 쓴다.
public protected private abstract static final transient
-> volatile synchronized native strictfp
배열 선언에 오는 대활호는 타입의 바로 뒤에 붙인다.
변수명 뒤에 붙이지 않는다.
// Good Examples
String[] names;
// Bad Examples
String names[];
long형의 숫자에는 마지막에 대문자 ‘L’을 붙인다.
소문자 ‘l’보다 숫자 ‘1’과의 차이가 커서 가독성이 높아진다.
long base = 54423234211L;
들여쓰기는 코드의 계층을 구분하기 위해 추가하는 문자이다.
1개의 탭의 크기는 스페이스 4개와 같도록 에디터에서 설정한다.
중괄호({})는 클래스, 메서드, 제어문의 블럭을 구분한다.
클래스 선언, 메서드 선언, 조건/반복문 등의 코드 블럭을 감싸는 중괄호에 적용되는 규칙이다.
중괄호 선언은 K&R 스타일(Kernighan and Ritchie style)을 따른다.
{를 쓰고 열고 새줄을 삽입한다.블럭을 마친후에는 새줄 삽입 후 중괄호를 닫는다.
public class SearchConditionParser {
public boolean isValidExpression(String exp) {
if (exp == null) {
return false;
}
for (char ch : exp.toCharArray()) {
....
}
return true;
}
}
// Good Examples
if (line.startWith(WARNING_PREFIX)) {
return LogPattern.WARN;
} else if (line.startWith(DANGER_PREFIX)) {
return LogPattern.NORMAL;
} else {
return LogPattern.NORMAL;
}
try {
writeLog();
} catch (IOException ioe) {
reportFailure(ioe);
} finally {
writeFooter();
}
do {
write(line);
line = readLine();
} while (line != null);
// Bad Examples
if (line.startWith(WARNING_PREFIX)) {
return LogPattern.WARN;
}
else if (line.startWith(DANGER_PREFIX)) {
return LogPattern.DANGER;
}
else {
return LogPattern.NORMAL;
}
try {
writeLog();
}
catch (IOException ioe) {
reportFailure(ioe);
}
finally {
writeFooter();
}
do {
write(line);
line = readLine();
}
while (line != null);
내용이 없는 블럭을 선언할 때는 같은 줄에서 중괄호를 닫는 것을 허용한다.
public void close() {}
조건, 반복문이 한 줄로 끝더라도 중괄호를 활용한다.
이 문서에 언급된 중괄호의 전후의 공백, 제어문 앞 뒤의 새줄 규칙도 함께 고려한다.
// Good Examples
if (exp == null) {
return false;
}
for (char ch : exp.toCharArray()) {
if (ch == 0) {
return false;
}
}
// Bad Examples
if (exp == null) return false;
for (char ch : exp.toCharArray()) if (ch == 0) return false;
줄바꿈은 작성한 명령어가 줄 너비를 초과했을 경우 코드 가독성을 위해서 강제로 줄을 바꾸는 것을 말한다.
최대 줄 사용 너비는 120자까지 가능하다.
줄바꿈 이후 이어지는 줄에서는 시작 줄보다 적어도 1단계의 들여쓰기를 더 추가한다.
AbstractAggregateRootTest.AggregateRoot proxyAggregateRoot =
em.getReference(AbstractAggregateRootTest.AggregateRoot.class, aggregateRoot.getId());
빈 줄은 명령문 그룹의 영역을 표시하기 위하여 사용한다.
package com.naver.lucy.util;
import java.util.Date;
import 구절은 아래와 같은 순서로 그룹을 묶어서 선언한다.
1. static imports
2. java.
3. javax.
4. org.
5. net.
6. 8~10을 제외한 com.*
7. 1~6, 8~10을 제외한 패키지에 있는 클래스
8. com.nhncorp.
9. com.navercorp.
10. com.naver.
import java.util.Date;
import java.util.List;
import javax.naming.NamingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import com.google.common.base.Function;
import com.naver.lucy.util.AnnotationUtils;
메서드의 선언이 끝난 후 다음 메서드 선언이 시작되기 전에 빈줄을 삽입한다.
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
식별자와 여는 소괄호(() 사이에는 공백을 삽입하지 않는다.
생성자와 메서드의 선언, 호출, 애너테이션 선언 뒤에 쓰이는 소괄호가 그에 해당한다.
// Good Examples
public StringProcessor() {} // 생성자
@Cached("local")
public String removeEndingDot(String original) {
assertNotNull(original);
...
}
// Bad Examples
public StringProcessor () {} // 생성자
@Cached ("local")
public String removeEndingDot (String original) {
assertNotNull (original);
...
}
제네릭스(Generics) 선언에 쓰이는 산괄호(<, >) 주위의 공백은 다음과 같이 처리한다.
- 제네릭스 메서드 선언 일 때만 < 앞에 공백을 삽입한다.
- < 뒤에 공백을 삽입하지 않는다.
- > 앞에 공백을 삽입하지 않는다.
- 아래의 경우를 제외하고는 `>`뒤에 공백을 삽입한다.
- 메서드 레퍼런스가 바로 이어질 때
- 여는 소괄호('(')가 바로 이어질 때
- 메서드 이름이 바로 이어질 때
public static <A extends Annotation> A find(AnnotatedElement elem, Class<A> type) { // 제네릭스 메서드 선언
List<Integer> l1 = new ArrayList<>(); // '(' 가 바로 이어질때
List<String> l2 = ImmutableList.Builder<String>::new; // 메서드 레퍼런스가 바로 이어질 때
int diff = Util.<Integer, String>compare(l1, l2); // 메서드 이름이 바로 이어질 때
}
콤마(,)와 반복문(while, for)의 구분자로 쓰이는 세미콜론(;)에는 뒤에만 공백을 삽입한다.
// Good Examples
for (int i = 0; i < length; i++) {
display(level, message, i)
}
// Bad Examples
for (int i = 0;i < length;i++) {
display(level,message,i)
}
반복문과 삼항연산자에서 콜론(:)의 앞 뒤에는 공백을 삽입한다.
라벨 선언 뒤에는 아무런 문자열이 없으므로 앞에만 공백을 삽입한다.
for (Customer customer : visitedCustomers) {
AccessPattern pattern = isAbnormal(accessLog) ? AccessPattern.ABUSE : AccessPattern.NORMAL;
int grade = evaluate(customer, pattern);
switch (grade) {
case GOLD :
sendSms(customer);
case SILVER :
sendEmail(customer);
default :
inreasePoint(customer)
}
}
if (pattern == Access.ABNORMAL) {
return 0;
}
finalScore += weight * rawScore - absentCount;
if (finalScore > MAX_LIMIT) {
return MAX_LIMIT;
}
- 전위 연산자 : 연산자 뒤에 공백을 삽입하지 않는다.
- 전위 증감/감소 연산자 : ,++--
- 부호로 쓰이는 , +-
- NOT 연산자 : , ~!
- 후위 연산자 : 연산자 앞에 공백을 삽입하지 않는다.
- 후위 증감/감소 연산자 : ,++--
// Good Examples
int point = score[++index] * rank-- * -1;
// Bad Examples
int point = score[++ index] * rank -- * - 1;
- 명령문과 같은 줄에 주석을 붙일 때 "//" 앞
- 주석 시작 기호 "//" 뒤
- 주석 시작 기호 "/*" 뒤
- 블록 주석을 한 줄로 작성시 종료 기호 "*/" 앞
/*
* 공백 후 주석내용 시작
*/
System.out.print(true); // 주석 기호 앞 뒤로 공백
/* 주석내용 앞에 공백, 뒤에도 공백 */