티스토리 뷰

728x90

 

우아한테크코스 프리코스에서 권고하는 NAVER CAMPUS HACKDAY의 Java Code Conventions를 학습하고 이를 적용시켜 보려한다.

 

📌 캠퍼스 핵데이 Java 코딩 컨벤션 (naver.github.io)

 

캠퍼스 핵데이 Java 코딩 컨벤션

중괄호({,}) 는 클래스, 메서드, 제어문의 블럭을 구분한다. 5.1. K&R 스타일로 중괄호 선언 클래스 선언, 메서드 선언, 조건/반복문 등의 코드 블럭을 감싸는 중괄호에 적용되는 규칙이다. 중괄호

naver.github.io

 

아래의 내용은 다음을 참고하여 IntelliJ에 적용시킬 수 있다. 

📌 [우아한테크코스/프리코스] Java Code Conventions를 IntellJ에 적용하기 (tistory.com)

 

[우아한테크코스/프리코스] Java Code Conventions를 IntellJ에 적용하기

우리는 지금까지 NAVER CAMPUS HACKDAY의 Java Code Conventions를 학습하였다. [우아한테크코스/프리코스] Java Code Conventions (tistory.com) [우아한테크코스/프리코스] Java Code Conventions 우아한테크코..

programmer-ririhan.tistory.com

 

🍑 파일 공통 요건

파일의 끝에 개행 추가 [newline-eof]

파일의 마지막은 새줄 문자 LF로 끝나야 한다.

ref : 파일 끝에 개행을 추가해야 하는 이유 | Coderifleman's blog

🍑 이름 (Naming)

대문자로 표기할 약어 명시 [list-uppercase-abbr]

약어의 중간단어를 소문자로 표기하고 프로젝트 별로 모두 대문자로 표기할 약어의 목록을 명시하는 방식이 가독성을 높이고 규칙을 단순화하는데 유리하다. 

예) HTTP+API+URL의 클래스 이름의 경우
- 대문자로 표기할 약어의 목록을 정의하지 않은 경우 : HttpApiUrl
- API만 대문자로 표기할 약어의 목록에 있을 경우 : HttpAPIUrl
- HTTP, API, URL 모두 대문자로 표기할 약어의 목록에 있을 경우 : HTTPAPIURL

패키지 이름은 소문자로 구성 [package-lowercase]

패키지 이름은 소문자를 사용하여 작성한다.

단어별 구분을 위해 언더스코어 '_' 나 대문자를 섞지 않는다.

// Good Exemples
package com.navercorp.apigateway

// Bad Exemples
package com.navercorp.apiGateway
package com.navercorp.api_gateway

클래스, 인터페이스 이름에 대문자 카멜표기법 적용 [class-interface-lower-camelcase]

클래스 이름은 단어의 첫 글자를 대문자로 시작하는 대문자 카멜표기법(Upper camel case)를 사용한다.

→ 파스칼표기법(Pascal case)으로도 불린다.

// Good Exemples
public class Reservation;
public class AccessToken;

// Bad Exemples
public class reservation;
public class Accesstoken;

클래스 이름에 명사 사용 [class-noun]

클래스 이름은 명사나 명사절로 짓는다.

인터페이스 이름에 명사/형용사 사용 [interface-noun-adj]

인터페이스(interface)의 이름은 명사/명사절로 혹은 형용사/형용사절로 짓는다.

// Good Exemples
public interface RowMapper {
public interface AutoClosable {

테스트 클래스는 'Test’로 끝남 [test-class-suffix]

JUnit 등으로 작성한 테스트 코드를 담은 클래스는 'Test’을 마지막에 붙인다.

// Good Exemples
public class WatcherTest {

🍑 메서드

메서드 이름에 소문자 카멜표기법 적용 [method-lower-camelcase]

메서드의 이름에는 첫 번째 단어를 소문자로 작성하고, 이어지는 단어의 첫 글자를 대문자로 작성하는 소문자 카멜표기법(Lower camel case)를 사용한다.

✔️ 테스트 클래스의 메서드 이름에서는 언더스코어를 허용한다.

메서드 이름은 동사/전치사로 시작 [method-verb-preposition]

메서드명은 기본적으로 동사로 시작한다.

✔️ 다른 타입으로 전환하는 메서드나 빌더 패턴을 구현한 클래스의 메서드에서는 전치사를 쓸 수 있다. 

- 동사사용 : renderHtml()
- 전환메서드의 전치사 : toString()
- Builder 패턴 적용한 클래스의 메서드의 전치사 : withUserId(String id)

🍑 상수

상수는 대문자와 언더스코어로 구성[constant_uppercase]

"static final"로 선언되어 있는 필드일 때 상수로 간주한다.

상수 이름은 대문자로 작성하며, 복합어는 언더스코어'_'를 사용하여 단어를 구분한다.

public final int UNLIMITED = -1;
public final String POSTAL_CODE_EXPRESSION = “POST”;

🍑 변수

변수에 소문자 카멜표기법 적용 [var-lower-camelcase]

상수가 아닌 클래스의 멤버변수/지역변수/메서드 파라미터에는 소문자 카멜표기법(Lower camel case)을 사용한다.

private boolean authorized;
private int accessToken;

임시 변수 외에는 1 글자 이름 사용 금지 [avoid-1-char-var]

메서드 블럭 범위 이상의 생명 주기를 가지는 변수에는 1글자로 된 이름을 쓰지 않는다.

반복문의 인덱스나 람다 표현식의 파라미터 등 짧은 범위의 임시 변수에는 관례적으로 1글자 변수명을 사용할 수 있다.

HtmlParser parser = new HtmlParser();

🍑 선언 (Declarations)

클래스, 필드, 메서드, 변수값, import문 등의 소스 구성요소를 선언할 때 고려해야할 규칙이다.

static import에만 와일드 카드 허용 [avoid-star-import]

클래스를 import 할때는 와일드카드(*) 없이 모든 클래스명을 다 쓴다.

static import에서는 와일드카드(*)를 허용한다.

// Good Examples
import java.util.List;
import java.util.ArrayList;

// Bad Examples
import java.util.*;

제한자 선언의 순서 [modifier-order]

클래스/메서드/멤버변수의 제한자는 Java Language Specification에서 명시한 아래의 순서로 쓴다.

public protected private abstract static final transient volatile synchronized native strictfp

배열에서 대괄호는 타입 뒤에 선언 [array-square-after-type]

배열 선언에 오는 대괄호([])는 타입의 바로 뒤에 붙인다.

변수명 뒤에 붙이지 않는다.

// Good Examples
String[] names;

// Bad Examples
String names[];

long형 값의 마지막에 `L`붙이기 [long-value-suffix]

long형의 숫자에는 마지막에 대문자 'L’을 붙인다.

소문자 'l’보다 숫자 '1’과의 차이가 커서 가독성이 높아진다.

long base = 54423234211L;

🍑 들여쓰기 (Indentation)

들여쓰기는 코드의 계층을 구분하기 위해 추가하는 문자이다.

탭의 크기는 4개의 스페이스 [4-spaces-tab]

1개의 탭의 크기는 스페이스 4개와 같도록 에디터에서 설정한다.

🍑 중괄호 (Braces)

중괄호({})는 클래스, 메서드, 제어문의 블럭을 구분한다.

K&R 스타일로 중괄호 선언 [braces-knr-style]

클래스 선언, 메서드 선언, 조건/반복문 등의 코드 블럭을 감싸는 중괄호에 적용되는 규칙이다.

중괄호 선언은 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;
    }
}

else, catch, finally, while은 닫는 중괄호와 같은 줄에 선언 [sub-flow-after-brace]

✔️ while은 do-while문에서의 while을 의미한다.

// 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);

빈 블럭에 새줄 없이 중괄호 닫기 허용 [permit-concise-empty-block]

내용이 없는 블럭을 선언할 때는 같은 줄에서 중괄호를 닫는 것을 허용한다.

public void close() {}

조건/반복문에 중괄호 필수 사용 [need-braces]

조건, 반복문이 한 줄로 끝더라도 중괄호를 활용한다.

이 문서에 언급된 중괄호의 전후의 공백, 제어문 앞 뒤의 새줄 규칙도 함께 고려한다.

💡 평소 나쁜 예와 같이 사용하는 경우가 많아서 반성하게 되었다.

// 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;

🍑 줄바꿈 (Line-wrapping)

줄바꿈은 작성한 명령어가 줄 너비를 초과했을 경우 코드 가독성을 위해서 강제로 줄을 바꾸는 것을 말한다.

최대 줄 너비는 120 [line-length-120]

최대 줄 사용 너비는 120자까지 가능하다.

줄바꿈 후 추가 들여쓰기 [indentation-after-line-wrapping]

줄바꿈 이후 이어지는 줄에서는 최초 시작한 줄에서보다 적어도 1단계의 들여쓰기를 더 추가한다. 

AbstractAggregateRootTest.AggregateRoot proxyAggregateRoot =
        em.getReference(AbstractAggregateRootTest.AggregateRoot.class, aggregateRoot.getId());

🍑 빈 줄(Blank lines)

빈 줄은 명령문 그룹의 영역을 표시하기 위하여 사용한다.

pakags 선언 후 빈 줄 삽입 [blankline-after-package]

package com.naver.lucy.util;

import java.util.Date;

import 선언의 순서와 빈 줄 삽입 [import-grouping]

import 구절은 아래와 같은 순서로 그룹을 묶어서 선언한다.

✔️ 각 그룹 사이에는 빈줄을 삽입한다.

✔️ 같은 그룹 내에서는 알파벳 순으로 정렬한다.

💡 평소 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;

메소드 사이에 빈 줄 삽입 [blankline-between-methods]

메서드의 선언이 끝난 후 다음 메서드 선언이 시작되기 전에 빈줄을 삽입한다.

public void setId(int id) {
    this.id = id;
}

public void setName(String name) {
    this.name = name;
}

🍑 공백 (Whitespace)

식별자와 여는 소괄호 사이에 공백 미삽입 [no-space-between-identifier-parentheses]

식별자와 여는 소괄호(() 사이에는 공백을 삽입하지 않는다.

생성자와 메서드의 선언, 호출, 애너테이션 선언 뒤에 쓰이는 소괄호가 그에 해당한다.

// 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);
    ...
}

제네릭스 산괄호의 공백 규칙 [generic-whitespace]

제네릭스(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); // 메서드 이름이 바로 이어질 때
}

콤마/구분자 세미콜론의 뒤에만 공백 삽입 [space-after-comma-semicolon]

콤마(,)와 반복문(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)
}

콜론의 앞 뒤에 공백 삽입 [space-around-colon]

반복문과 삼항연산자에서 콜론(:)의 앞 뒤에는 공백을 삽입한다.

라벨 선언 뒤에는 아무런 문자열이 없으므로 앞에만 공백을 삽입한다.

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)
    }
}

이항/삼항 연산자의 앞 뒤에 공백 삽입 [space-around-binary-ternary-operator]

if (pattern == Access.ABNORMAL) {
    return 0;
}

finalScore += weight * rawScore - absentCount;

if (finalScore > MAX_LIMIT) {
    return MAX_LIMIT;
}

단항 연산자와 연산 대상 사이에 공백을 미삽입 [no-space-increament-decrement-operator]

- 전위 연산자 : 연산자 뒤에 공백을 삽입하지 않는다.
	- 전위 증감/감소 연산자 : ,++--
	- 부호로 쓰이는 , +-
	- NOT 연산자 : , ~!
- 후위 연산자 : 연산자 앞에 공백을 삽입하지 않는다.
	- 후위 증감/감소 연산자 : ,++--
// Good Examples
int point = score[++index] * rank-- * -1;

// Bad Examples
int point = score[++ index] * rank -- * - 1;

주석문 기호 전후의 공백 삽입 [space-around-comment]

💡 주석문을 명령문의 위에 작성하는 지 오른쪽에 작성하는 지에 대해서도 궁급했는데 이에 대한 내용은 나와있지 않았다. 

- 명령문과 같은 줄에 주석을 붙일 때 "//" 앞
- 주석 시작 기호 "//" 뒤
- 주석 시작 기호 "/*" 뒤
- 블록 주석을 한 줄로 작성시 종료 기호 "*/" 앞
/*
 * 공백 후 주석내용 시작
 */

System.out.print(true); // 주석 기호 앞 뒤로 공백

/* 주석내용 앞에 공백, 뒤에도 공백 */

 

728x90
댓글
공지사항
최근에 올라온 글