이펙티브 자바 8장: 메서드

Adam·2024년 8월 12일
0

이펙티브 자바

목록 보기
7/10
post-thumbnail

매개변수가 유효한지 검사하라

메서드에서 받는 매개변수에 대한 제약은 문서화해야 하며 몸체가 시작되기 전에 검사

매개변수 검사를 제대로 못했을 때 문제

  1. 메서드가 수행되는 중간에 모호한 예외를 던지며 실패할 수 있다
  2. 메서드가 잘 수행되더라도 잘못된 결과를 반환할 수 있다

java.util.Objects.requireNonNull 메서드를 사용하면 null 검사를 수동으로 하지 않아도 된다

this.strategy = Objects.requireNonNull(strategy, "전략");

공개되지 않은 메서드라면 패키지 제작자가 메서드가 호출되는 상황을 통제할 수 있어서 오직 유효한 값이 메서드에 넘겨지는 것을 보증할 수 있다

유효성 검사의 비용이 너무 높거나 암묵적으로 검사가 수행될때는 예외적으로 메서드 몸체 실행 전에 매개변수 유효성 검사를 해야된다는 원칙에서 예외이다

적시에 방어적 복사본을 만들라

자바는 안전한 언어이지만 클라이언트가 이 안정성을 깨뜨리는것을 고려해서 방어적으로 프로그래밍 해야 한다

외부 공격으로부터 내부를 보호하려면 생성자에서 받은 가변 매개변수 각각을 방어적으로 복사하고 원본이 아닌 복사본을 이용하는 것도 고려해야 한다

매개변수가 제3자에 의해 확장될 수 있는 타입이라면 방어적 복사본을 만들 때 clone을 사용해서는 안된다

변경될 수 있는 객체가 클래스에 남겨진 뒤 임의로 변경되어도 그 클래스가 문제 없이 동작할지를 따저본 후 확신할 수 없다면 복사본을 만들어 저장해야 한다

방어적 복사를 사용하지 않을 케이스

  1. 성능이 중요한 경우(지나친 방어적 복사는 성능저하를 유발할 수 있다)
  2. 클라이언트와 클래스가 상호 신뢰할 수 있을때, 혹은 불변식이 깨지더라도 클라이언트에만 영향이 갈 때

메서드 시그니처를 신중히 설계하라

  1. 메서드 이름을 신중히 짓자
  2. 편의 메서드를 너무 많이 만들지 말자
  3. 매개변수 목록은 짧게 유지하자(왠만하면 4개 이하)
    • 매개변수가 길면 여러 메서드로 쪼갠다
    • 매개변수 여러개를 묶어주는 도우미 클래스를 만든다
    • 객체 생성에 빌더 패턴을 사용하는것 처럼 메서드 호출에도 추상화한 객체를 정의하고 세터로 필요한 값 설정
  4. 매개 변수의 타입으로는 클래스보다 인터페이스가 낫다
  5. boolean 보다는 원소 2개짜리 열거 타입이 낫다(boolean을 받아야 더 의미가 명확할때는 제외)

다중정의는 신중히 사용하라

재정의 메서드는 동적으로 선택되고 다중정의한 메서드는 정적으로 선택된다

메서드를 재정의했다면 해당 객체의 런타임 타입이 어떤 메서드를 호출할지의 기준이 된다

안전하고 보수적으로 가려면 매개변수 수가 같은 다중정의는 만들지 않는 것이 좋다

다중정의하는 대신 메서드 이름을 다르게 지어주는 것도 고려해야 한다

메서드를 다중정의할 때, 서로 다른 함수형 인터페이스라도 같은 위치의 인수로 받아서는 안된다

가변인수는 신중히 사용하라

가변인수 메서드는 명시한 타입의 인수를 0개 이상 받을 수 있다

static int sum(int... args){
	int sum = 0;
	for (int arg : args)
		sum += arg;
	return sum;
}

메서드를 정의할 때 필수 매개변수는 가변인수 앞에 두어야 오류 방지할 수 있다

static int min(int firstArg, int... remainingArgs){
	int min = firstArg;
	for (int arg: reaminingArgs)
		if (arg < min)
			min = arg;
		return min;
	}

가변인수가 성능에 걸림돌이 될 수 있으니 성능에 민감한 상황일 때는 사용에 주의해야 한다

null이 아닌, 빈 컬렉션이나 배열을 반환하라

빈 컬랙션을 반환하는 쪽이 오류 방지에도 좋고, 빈 불변 객체를 생성하고 이를 반환하면 성능에도 영향을 주지 않는다

옵셔널 반환은 신중히 하라

옵셔널을 반환하는 메서드에서는 절대 null을 반환하지 말아야 한다

옵셔널 활용

  1. 기본값 설정
String lastWordInLexicon = max(words).orElse("단어 없음");
  1. 원하는 예외를 던진다
Toy myToy = max(toys).orElseThrow(TemperTantrumException::new);
  1. 옵셔널에 항상 값이 채워저 있다고 가정
Element lastNobleGas = max(Elements.NOBLE_GASES).get();

여전히 적합한 메서드를 찾지 못했다면 isPresent로 옵셔널이 채워져 있으면 true, 비어 있으면 false를 반환

컬렉션, 스트림, 배열, 옵셔널 같은 컨테이너 타입은 옵셔널로 감싸면 안된다

옵셔널을 맵의 값으로는 왠만한 경우에서는 사용하면 안된다

공개된 API 요소에는 항상 문서화 주석을 작성하라

API를 올바로 문서화하려면 공개된 모든 클래스, 인터페이스, 메서드, 필드 선언에 문서화 주석을 달아야 한다

메서드용 문서화 주석에는 해당 메서드와 클라이언트 사이의 규약을 명료하게 기술해야 한다

전제조건과 사후조건뿐만 아니라 부작용도 문서화해야 한다

열거 타입을 문서화할 때는 상수들에도 주석을 달아야 한다

애너테이션 타입을 문서화할 때는 맴버들에도 모두 주석을 달아야 한다

클래스 혹은 정적 메서드가 스레드 안전하든 그렇지 않든, 스레드 안전 수준을 반드시 API 설명에 포함해야 한다

profile
Keep going하는 개발자

0개의 댓글