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
- 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
│ ├─ ... - 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
3public <T extends MyObject> T getObject(int type) {
return (T) factory.create(type);
}1
2
3
4
5
6
7
8
9public 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을 사용
- BAD
1
2
3
4
5
6
7
8
9
10
11Integer value = null;
try {
}catch(NumberFormatException e) {
}
if(value == null) {
//handle bad string
}else {
//business logic
} - GOOD
1
2
3
4
5
6if ( (str != null) && str.matches("-?\\d++") ) {
Integer value = Integer.valueOf(str);
//business logic
}else {
//handle bad string
}
- 예외처리는 도메인 레벨에서 하자
- BAD
1
2
3
4
5
6
7
8
9
10
11
12
13
14class 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
}
}
} - GOOD
1
2
3
4
5
6
7
8
9
10
11
12
13class 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을 사용해라