Effective Java 2/E - Chatper 08 일반적인 프로그래밍 원칙들 (2)
Rule 51 - 문자열 연결 시 성능에 주의하라
n개의 문자열에 연결 연산자(+
or concat
)를 반복 적용해서 연결하는데 드는 시간은 n^2에 비례한다.
문자열은 불변객체이기 때문이다
반복적으로 문자열을 연결해야한다면 StringBuilder
을 사용해야한다.
example
StringBuffer
의 경우 동기화가 되기 때문에 성능이 저하된다. 쓰레드 안정성이 필요하지 않다면 (예를 들면 지역변수라면)StringBuilder
를 쓰도록하자.
Rule 52 - 객체를 참조할 때는 그 인터페이스를 사용하라
인터페이스를 자료형으로 쓰는 습관을 들이면 프로그램은 더욱 유연해진다.
example
인터페이스를 자료형으로 사용하면 구현체를 변경할 수 있으므로 훨씬 유연하다. 하지만 실제 구상클래스가 특별한 기능(예를 들면 동기화)을 제공한다면 해당 기능을 유지하도록 해야한다.
적당한 인터페이스가 없는 경우에는 객체를 클래스로 참조하는 것이 당연하다.
- 값객체
- final 클래스
- 유틸성 클래스(
Random
)
인터페이스가 없고 기반클래스가 있다면 그것을 사용하는 것도 한 방법이다.
결론
- 인터페이스를 통한 참조를 하면 유연해진다.
- 적절한 인터페이스가 없다면 가장 일반적인 클래스(super class)를 사용하도록 하라
Rule 53 - 리플렉션 대신 인터페이스를 이용하라.
리플렉션
클래스의 정보를 가져오는 프로그램을 작성할 수 있게 하는 기능. 클래스의 맴버 이름이나 필드 자료형, 메서드 시그너처 등의 정보를 얻어낼 수 있다.
Class
,Constructor
,Method
,Field
그리고 위 객체들을 이용하면 실제 행위나 상태들을 반영적으로(reflectively) 조작할 수 있다.
리플렉션의 단점
- 실행시점 오류 가능성이 큼
- 가독성이 매우 떨어짐
- 성능이 낮음
결론
컴파일 시점에 알수 없는(실행시점에 알 수 있는) 클래스를 이용하고 싶다면, 리플렉션을 사용하되 가능하면 객체를 만들 때만 이용하고, 객체를 참조할 때는 컴파일 시에 알고 있는 인터페이스나 상위 클래스를 이용하라
Rule 54 - 네이티브 메서드는 신중하게 사용하라
JNI : Java Native interface**
C나 C++ 등의 네이티브 프로그래밍 언어로 작성된 네이티브 메서드를 호출하는데 이용되는 기능
용도
- OS(플랫폼) 고유 기능 이용 가능
- 네이티브 라이브러리 재사용
- 성능 향상
그러나 네이티브 메서드를 통한 성능개선은 추천하지 않는다.
- 과거에 비해 JVM의 성능 향상
- Java 만으로 필적한 성능 가능
네이티브 메서드 직접 사용 시 단점
- 안전하지 않음
- 메모리 참조 이슈
- 플랫폼 종속정 (이식성이 낮음)
- 디버깅 어려움
- 잘못 사용할 경우 성능하락
- 가독성이 떨어짐
결론
가능하면 네이티브 메서드는 사용하지 않는다. 만약 사용한다면 최소한의 용도로만 이용하고, 검증을 확실히 한다.
Rule 55 - 신중하게 최적화하라
최적화의 3가지 격언
맹목적인 어리석음(blind stupidity)을 비롯한 다른 어떤 이유보다도, 효율성이라는 이름으로 저질러지는 죄악이 더 많다(효율성을 반드시 성취하는 것도 아니면서 말이다)
작은 효율성(small efficiency)에 대해서는, 말하자면 97% 정도에 대해서는, 잊어버려라. 섣부른 최적화(premature optimization)는 모든 악의 근원이다.
최적화를 할 때는 아래의 두 규칙을 따르라 규칙 1 : 하지마라 규칙 2 : (전문가들만 따를 것) 아직은 하지마라 - 완벽히 명료한, 최적화되지 않은 해답을 얻을 때 까지는.
즉 성능 최적화는 신중하게 생각하고 적용하라
원칙
성능 때문에 구조적인 원칙(architectural principle)을 희생하지 마라.
구조가 좋은데, 성능이 안 나오면 내부 모듈을 수정을 통해서 유연하게 성능을 향상하면서 구조를 유지할 수 있다. 구조가 안 좋은데, 성능이 안 나오면 구조 자체를 변경하거나 나쁜 구조가 더 나빠질 수 있다.
설계를 할 때는 성능을 제약할 가능성이 있는 결정들을 피하라.
API를 설계할 때 내리는 결정들이 성능에 어떤 영향을 끼칠지를 생각하라.
잘 설계된 API는 일반적으로 좋은 성능을 보인다. 좋은 성능을 내기 위해 API를 급진적으로 바꾸면 호환성 때문에 더 큰 문제가 발생할 수 있다.
최적화는 객관적인 수치를 바탕으로 진행하라.
결론
빠른 프로그램을 만들고자 애쓰지 말라는 것이다. 대신 좋은 프로그램을 짜기 위해 노력하라. 성능은 따라올 것이다.
Rule 56 - 일반적으로 통용되는 작명 관습을 따르라
자바는 작명 관습(naming convention)이 잘 정립되어 있음
철자 작명 관습
식별자 자료형 | 예제 | 비고 |
---|---|---|
패키지 | com.edu , com.sun |
소문자와 .으로 구분 |
타입 | Timer , FutureTask |
|
메서드, 필드 | remove , ensureCapacity |
|
상수 | VALUES , NEGATIVE_INFINITY |
|
지역변수 | i , xref , houseNumber |
약어가능 |
자료형인자(제네릭타입) | <E> , <T> , <IN> |
대문자 |
문법 작명 관습
클래스
- enum : 단수형 명사
- 클래스, 인터페이스 : 명사, 형용사격(~able, ~ible) 어미
- 어노테이션 : 이것저것 다
메서드
- 동사
getter
,setter
- boolean 일 시 :
is~
,has~
- 객체 변환 : toType, asType, typeValue