아이템 49. 매개변수가 유효한지 검사하라.
- 메서드 몸체 실행 전에 매개변수를 확인한다면 잘못된 값이 넘어왔을 때 즉각적으로 예외를 던질 수 있다. Fail fast!
- public, protected 메서드는 매개변수 값이 잘못됐을 때의 예외를 문서화해야 한다 (@throws 태그 활용)
- 클래스 수준 주석은 모든 public 메서드에 적용된다.
- public이 아닌 메서드는 assert를 사용해 검증할 수 있다.
- 메서드가 직접 사용하지 않으나 나중에 사용하려고 저장하는 매개변수는 특히 더 조심하자
일찍 못잡으면 추적하기 어려워진다. Fail fast!
- 매개변수가 유효한지 검사하라는 의미는, 매개변수에 제약을 두는 것이 좋다가 아닌, 메서드를 최대한 범용적으로 설계해야한다는 것
- https://hibernate.org/validator/ 같은것들을 잘 쓰자
아이템 50. 적시에 방어적 본사본을 만들라 (Make defensive copies when needed)
- 외부 공격으로부터 인스턴스 내부를 보호하려면 생성자로부터 받은 가변 매개변수를 각각 방어적으로 복사해서 사용해야한다. (생성자, 접근자)
- "복사본 생성 -> 유효성 검사"의 순서로 이루어지는 것이 안전하다 (멀티스레딩 환경)
- 매개변수가 확장될 수 있는 타입이라면 복사에 clone을 사용하지 말자
- 되도록 불변 객체들을 조합해 객체를 구성해야 방어적 복사를 할 일이 줄어든다
- 클라이언트와 상호 신뢰할 수 있을 때, 불변식 깨진 영향이 오직 호출한 클라이언트로 국한될 때는 방어적 복사를 생략할 수 있다 (하지만 잘 판단하자)
아이템 51. 메서드 시그니처를 신중히 설계하라
- 메서드 이름을 신중히 짓자
- 편의 메서드를 남발하지 말자. 메서드, 클래스는 각자의 책임을 다해야한다.
- 매개변수 목록은 4개 이하가 좋다.
같은 타입 매개변수 여러개 연달아 나오면 컴파일은 되는데, 의도와 다른 동작을 하기 때문에 최악
- 매개변수 타입으로는 적합한 인터페이스가 있다면 클래스보다는 인터페이스를 쓰자
- boolean 보다는 enum이 낫다. 적절히 판단하자
- 직교성이 높다
= 공통점이 없는 기능들이 잘 분리되어 있다
= 기능을 원자적으로 쪼개 제공한다
msa는 직교성이 높고, monolithic 아키텍처는 직교성이 낮다.
아이템 52. 다중정의는 신중히 사용하라
- 재정의한 메서드는 동적으로 선택, 다중정의한 메서드는 정적으로 선택된다.
다중정의된 메서드 사이에서는 오직 컴파일타임 타입에 의해 선택이 이뤄진다.
재정의된 메서드에서는 가장 하위에서 정의한 재정의 메서드가 실행된다.
- 매개변수 수가 같은 다중정의는 만들지 말자 (보수적으로)
가변인수 쓸 때는 다중정의 아예 하지마라
- 매개변수 중 하나 이상이 근본적으로 다르다(두 타입의 값을 어느 쪽으로든 형변환할 수 없다)면, 매개변수 수가 같은 다중정의 메서드가 있어도 된다.
- 다중정의 메서드들이 하는 일이 같다면 신경 안써도 된다.
아이템 53. 가변인수는 신중히 사용하라
- 가변인수 메서드를 호출하면, 인수의 개수와 길이가 같은 배열을 만들고, 인수들을 이 배열에 저장하여 가변인수 메서드에 넘긴다.
→ 매번 배열이 새로 할당, 초기화되므로 성능 이슈 있을 수 있음
→ 성능 최적화를 위해, 개수별로 오버로딩, n개 이상부터 가변인수 사용할수도 있음
- 메서드를 정의할 때, 필수 매개변수는 가변인수 앞에 둬야한다.
아이템 54. null이 아닌, 빈 컬렉션이나 배열을 반환하라
- 배열, 컬렉션 같은 컨테이너가 비었을 때 null이 아닌, 빈 컬렉션이나 배열을 반환하자
null을 반환하면 반환하는 쪽에서나, 처리하는 쪽에서나 이 상황을 특별이 취급해줘야 해서 코드가 복잡해진다.
- 매번 빈 불변 컬렉션을 반환하도록 하면, 최적화 가능
아이템 55. 옵셔널 반환은 신중히 하라
- 옵셔널은 원소를 최대 1개 가질 수 있는 불변 컬렉션
- 옵셔널을 반환하는 메서드에서 절대 null을 반환하지 말자
- 옵셔널은 검사 예외와 취지가 비슷 (API 사용자에게 명확히 알려주기 위함)
검사예외 : 어플리케이션 수행 중 일어날 법한 예외를 검사, 대비하라는 목적으로 사용 (ex. IOException, SQLException)
- 컨테이너 타입은 옵셔널로 감싸면 안된다
- 박싱된 기본 타입을 담은 옵셔널을 반환하지말자
primitive 전용 옵셔널을 사용할 때의 장점
1. 불필요한 박싱, 언박싱 X
2. stream 사용 시, 일관성을 유지할 수 있음
https://stackoverflow.com/questions/33190768/optionalint-vs-optionalinteger
https://homoefficio.github.io/2019/10/03/Java-Optional-%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%93%B0%EA%B8%B0/
아이템 56. 공개된 API 요소에는 항상 문서화 주석을 작성하라
- 공개된 API는 자바독을 이용하여 문서화를 잘하자
- 나중에 자바독을 사용할 일이 있을 때 다시보면 좋을 아이템