Link
Today
Total
10-17 00:15
Archives
관리 메뉴

초보개발자 긍.응.성

(이펙티브 자바 3) 9장 일반적인 프로그래밍 원칙 정리 본문

책 정리/이펙티브 자바 3

(이펙티브 자바 3) 9장 일반적인 프로그래밍 원칙 정리

긍.응.성 2020. 12. 3. 20:44
반응형

지역변수의 범위를 최소화하라

  • 지역변수는 가장 처음 쓰일 때 선언하고, 선언과 동시에 초기화하도록 하자.
  • 변수를 초기화하는 표현식에서 검사 예외를 던질 가능성이 있다면 try 블록 안에서 초기화하라.
  • 메서드를 작게 유지하고 한 가지 기능에 집중하게 하라.

전통적인 for 문 보다는 for-each 문을 사용하라

전통적인 for 문은 반복자와 인덱스 변수가 여러 번 등장된다. 향상된 for-each문을 반복자와 인덱스 변수를 사용하지 않기에 코드가 더 깔끔해지고 오류가 날 일도 없다. for-each문은 배열은 물론 Iterable 인터페이스를 구현한 객체라면 무엇이든 순회할 수 있다. 아래와 같은 상황이 아니면 for-each문을 사용하자.

  1. 파괴적인 필터링 (destructive filtering) - 컬렉션을 순회하며 선택된 원소를 제거해야 할 때 (반복자의 remove 메서드를 호출해야 할 때). 자바 8 부터는 Collection.removeIf 메서드로 컬렉션을 명시적으로 순회하는 일을 피할 수 있다.
  2. 변형 (transforming) - 리스트나 배열을 순회하면서 그 원소의 값 일부 혹은 전체를 교체해야 한다면 리스트의 반복자나 배열의 인덱스를 사용해야한다.
  3. 병렬 반복 (parallel iteration) - 여러 컬렉션을 병렬로 순회해야 한다면 각각의 반복자와 인덱스 변수를 사용해 엄격하고 명시적으로 제어해야 한다.

라이브러리를 익히고 사용하라

라이브러리가 있다면 라이브러리를 사용하자. 그 이유는 다음과 같다.

  1. 표준 라이브러리를 사용하면 그 코드를 작성한 전문가의 지식과 여러분보다 앞서 사용한 다른 프로그래머들의 경험을 활용할 수 있다.
  2. 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 된다.
  3. 노력하지 않아도 성능이 지속해서 개선된다.
  4. 기능이 점점 많아진다
  5. 작성한 코드가 많은 사람들에게 낯익은 코드가 된다.

정확한 답이 필요하다면 float과 double은 피하라

float과 double은 넓은 범위의 수를 빠르게 정밀한 근사치로 계산하도록 설계되었기에, 정확한 결과가 필요할 때는 사용하면 안 된다. 특히 금융 관련 계산과는 맞지 않는다. 이 대신 BigDecimal을 사용하자. 성능면에서 아쉽다면 int 혹은 long 타입을 쓸 수 있는데 그럴 경우 다룰 수 있는 값의 크기가 제한되고, 소수점을 직접 관리해야 한다.

  • 아홉 자리 십진수로 표현 가능 - int
  • 열여덟 자리 십진수로 표현 가능 - long
  • 그 이상 - BigDecimal

박싱된 기본 타입보다는 기본 타입을 사용하라

  • 기본 타입은 값만 갖고 있으나, 박싱 된 기본 타입은 값에 더해 식별성(identity)을 갖는다.
  • 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입은 유효하지 않은 값, null을 가질 수 있다.
  • 기본 타입이 박싱된 기본 타입보다 시간과 메모리 사용면에서 효율적이다.
  • 기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀린다.

박싱된 기본 타입을 써야 할 때

  1. 컬렉션의 원소, 키, 값으로 쓸 때 (타입 매개변수로는 기본 타입을 지원하지 않음)
  2. 리플렉션을 통해 메서드를 호출할 때

다른 타입이 적절하다면 문자열 사용을 피하라

문자열은 다른 값 타입을 대신하기에 적합하지 않다. 또한 열거 타입, 혼합 타입, 권한을 표현하기에 적합하지 않다.

문자열 연결은 느리니 주의하라

문자열 연결 연산자로 문자열 n개를 잇는 시간은 $n^2$에 비례한다. 많은 문자열을 연결할 때는 문자열 연결 연산자(+) 대신 StringBuilder의 append 메서드를 사용하라.

객체는 인터페이스를 사용해 참조하라

적합한 인터페이스만 있다면 매개변수뿐 아니라 반환 값, 변수, 필드를 전부 인터페이스 타입으로 선언하라. 인터페이스 타입으로 사용하는 습관을 길러두면 프로그램이 훨씬 유연해질 것이다.

적합한 인터페이스가 없다면 클래스를 참조해야 한다.

  • 값 클래스
  • 클래스 기반으로 작성된 프레임워크가 제공하는 객체들 (최대한 (추상) 기반 클래스 이용)
  • 인터페이스에 없는 특별한 메서드를 제공하는 클래스 (PriorityQueue::comparator)

적합한 인터페이스가 없다면 클래스의 계층구조 중 필요한 기능을 만족하는 가장 덜 구체적인 클래스를 타입으로 사용하자.

728x90

리플렉션보다는 인터페이스를 사용하라

리플렉션은 강력하지만 이런 단점이 존재한다.

  • 컴파일 타임 타입 검사가 주는 이점을 누릴 수 없다.
  • 리플렉션을 이용하면 코드가 지저분하고 장황해진다.
  • 성능이 떨어진다(단순 int변수 get에 11배 성능 저하).

리플렉션은 아주 제한된 형태로만 사용해야 그 단점을 피하고 이전만 취할 수 있다. 되도록 객체 생성에만 사용하고, 생성한 객체를 이용할 때는 적절한 인터페이스나 컴파일 타임에 알 수 있는 상위 클래스로 형 변환해 사용해야 한다.

네이티브 메서드는 신중히 사용하라

자바 네이티브 인터페이스(Java Native Interface, JNI)는 자바 프로그램이 네이티브 메서드를 호출하는 기술이다.

네이티브 메서드란?
    - C나 C++ 같은 네이티브 프로그래밍 언어로 작성한 메서드

전통적으로 네이티브 메서드의 쓰임은 세 가지다.

  1. 레지스트리 같은 플랫폼 특화 기능을 사용할 때
  2. 네이티브 코드로 작성된 기존 라이브러리를 사용할 때
  3. 성능 개선을 목적으로 성능에 결정적인 영향을 주는 영역만 따로 네이티브 언어로 작성

성능을 개선할 목적으로 네이티브 메서드를 사용하는 것은 권장하지 않는다. 현재 JVM은 많이 발전되어 느리지 않다. 또한 네이티브 언어는 안전하지 않으므로 네이티브 메서드를 사용하는 애플리케이션도 메모리 훼손 오류로부터 더 이상 안전하지 않다. 또한 네이티브 언어는 자바보다 플랫폼을 많이 타서 이식성이 낮고 디버깅도 더 어렵다. 가비지 컬렉터가 네이티브 메모리는 자동 회수하지 못하고, 심지어 추적조차 할 수 없다. 자바 코드와 네이티브 코드의 경계를 넘나들 때마다 비용도 추가된다. 마지막으로 네이티브 메서드와 자바 코드 사이의 접착 코드(glue code)를 작성해야 하는데, 이는 귀찮은 작업이며 가독성도 떨어진다.

최적화는 신중히 하라

빠른 프로그램보다 좋은 프로그램을 작성하자. 대신 설계단계에 성능을 제한하는 설계를 피하고 API 설계 시 성능에 주는 영향을 고려하자. 또한 최적화 시 각각의 최적화 시도 전후로 성능을 측정하자.

일반적으로 통용되는 명명 규칙을 따르라

자바 플랫폼의 명명규칙을 따르자.

  • 패키지와 모듈
    • 조직 바깥에서도 사용될 패키지는 조직의 인터넷 도메인 이름의 역순 (com.google)
    • 표준 라이브러리는 java와 javax로 시작
    • 패키지 이름은 8자 이하의 짧은 단어로 한다 (utilities → util)
  • 클래스와 인터페이스
    • 대문자로 시작하며 Camel Case
    • 통용된 줄임말(max, min...)이 아니면 약어를 사용하지 말자
    • 대문자 단어가 혼합된 경우도 첫 글자만 대문자로 하는 게 가독성이 좋다 (HttpUrl)
    • 객체를 사용할 수 있는 클래스는 명사구를 사용하며 객체를 생성할 수 없는 클래스는 복수형 명사로 사용한다
    • 인터페이스는 클래스와 똑같이 짓거나, able 혹은 ible로 끝나는 형용사로 짓는다
    • 애너테이션은 다양하게 짓는다.
  • 메서드
    • 클래스와 인터페이스와 동일하지만 첫 글자는 소문자로
    • 동사나 동사구로 짓는다
    • boolean 값을 반환할 때는 is 혹은 has로 시작하게 짓는다
    • 반환 타입이 boolean이 아니며 해당 인스턴스의 속성을 반환할 시 get으로 시작하는 동사구로 짓는다 (Java 빈 명세)
    • 객체의 타입을 바꿔서 또 다른 객체를 반환하는 인스턴스 메서드 이름: toType
    • 객체의 내용을 다른 뷰로 보여주는 메서드: asType
    • 객체의 값을 기본 타입 값으로 반환하는 메서드: typeValue
    • 정적 팩터리의 이름 (다양함): from, of, valueOf, instance, getInstance, newInstance, getType, newType
  • 상수 필드
    • 모두 대문자로 쓰며 단어 사이는 언더바(_)로 구분한다
  • 지역 변수
    • 메서드와 비슷한 명명 규칙이 적용되지만 조금 더 약어를 사용하도록 한다
    • 그래도 이름을 짓는데 신경을 쓰자
  • 타입 매개변수
    • T: 임의의 타입
    • E: 컬렉션 원소 타입
    • K, V: 맵의 키와 값
    • X: 예외
    • R: 메서드 반환 타입
반응형
Comments