Java Best Practices

Programing Principles

  • KISS - “Keep It Simple, Stupid”
  • DRY - “Don’t Repeat Yourself”
  • YAGNI - “You Ain’t Gonna Need It” - 필요할 때에 구현해라
  • Avoid premature optimization - 최적화는 뒤로 미뤄라
  • Single responsibility
  • Composition over Inheritance - 상속보다는 구성
  • Fail fast, fail hard

Packages

  1. technical layers package
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    /project
    ├─ controller
    │ ├─ BoardController
    │ ├─ UserController
    │ ├─ ...
    ├─ dao
    │ ├─ BoardDao
    │ ├─ UserDao
    │ ├─ ...
    ├─ service
    │ ├─ BoardService
    │ ├─ UserService
    │ ├─ ...
  2. domain concern package
    1
    2
    3
    4
    5
    6
    7
    8
    9
    /project
    ├─ User
    │ ├─ UserController
    │ ├─ UserService
    │ ├─ UserDao
    ├─ Board
    │ ├─ BoardController
    │ ├─ BoardService
    │ ├─ BoardDao

    개인적으로 기술적 레이어 보단 도메인 개념을 선호함

Classes

static

  • static 클래스의 인스턴스화를 막아라 -> private constructor
  • should be stateless, immutable, not allow subclassing, and thread-safe

inheritance

  • 상속보다는 구성을 사용하라

    effective java의 유명한 hashset.add() 예제가 있음 ㅎㅎ

    상속은 a is b 일때 타입을 강제할 때만 사용하자

  • Do not expose protected field

  • class 변수에 final를 사용할 수 있다면 하는게 좋다

  • 상속할 필요가 없는 class는 final class로 만들어라. 메서드도 마찬가지

  • 빈 기본 생성자는 만들지마라 (자바가 알아서 만들어 줌)

Interfaces

  • Do not use the constant interface pattern

    static class를 사용하자

  • Avoid Interface overuse

    확장 가능성이 없는데 interface 만들고, abstract class 만들고 구현체 만드는 것은 오버 엔지니어링

  • interface는 최대한 작게 유지. client는 사용법만 알면됨

Generics

  • 가능하면 base class 나 interface 대신에 type inference를 리턴하라
    1
    2
    3
    public <T extends MyObject> T getObject(int type) {
    return (T) factory.create(type);
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class MySpecialObject extends MyObject<SpecialType> {
    public MySpecialObject() {
    super(Collections.emptyList()); // This is ugly, as we loose type
    super(Collections.EMPTY_LIST(); // This is just dumb
    // But this is beauty
    super(new ArrayList<SpecialType>());
    super(Collections.<SpecialType>emptyList());
    }
    }
  • PECS 공식 : Producer-extends, Consumer-super

Exceptions

  • 복구 가능한 예외는 checked Exception을 사용
  1. BAD
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Integer value = null;
    try {

    }catch(NumberFormatException e) {

    }
    if(value == null) {
    //handle bad string
    }else {
    //business logic
    }
  2. GOOD
    1
    2
    3
    4
    5
    6
    if ( (str != null) && str.matches("-?\\d++") ) {
    Integer value = Integer.valueOf(str);
    //business logic
    }else {
    //handle bad string
    }
  • 예외처리는 도메인 레벨에서 하자
  1. BAD
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class UserDao {
    public List<User> getUser() {
    try {
    ps = conn.prepareStatement("SELECT * from users");
    rs = ps.executeQuery();
    //... return result
    }catch{
    log.error("exception~");
    return null;
    }finally {
    //close resource
    }
    }
    }
  2. GOOD
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class UserDao {
    public List<User> getUser() {
    try {
    ps = conn.prepareStatement("SELECT * from users");
    rs = ps.executeQuery();
    //... return result
    }catch{
    throw new DataBaseLevelExcpetion(e);
    }finally {
    //close resource
    }
    }
    }
  • 로깅은 에러발생 시점이 아니라 예외 핸들링 시점에 해야한다
  • Use Standard Exception
  • 에러 코드 리턴보다 Exception을 사용해라