Skip to content

9. 일반적인 프로그래밍 원칙

HyoSang edited this page Jun 4, 2019 · 1 revision

아이템 57. 지역 변수의 범위를 최소화하라

  • 지역변수의 범위를 줄이는 가장 강력한 기법은 가장 처음 쓰일 때 선언하기
  • 거의 모든 지역 변수는 선언과 동시에 초기화해야 한다.
    • 초기화에 필요한 정보가 충분하지 않다면 충분할 때 까지 선언을 미루자
    • 단 변수를 초기화할 때 검사 예외의 가능성이 있다면 try-catch문에서 초기화 (그렇지 않으면 예외가 블록을 넘어 메서드에 까지 전파)
  • 반복 변수의 값을 반복문 이후에도 써야하는 상황이 아니라면 while문보다는 for문을 쓰는것이 낫다.
for(Element e : c) {
  ...
}

Iterator<Element> i = c.iterator(); 
while(i.hasNext()) {
  Element e = i.next();
  ...
}
  • 메서드를 작게 유지하고 한 가지 기능에 집중하라.

아이템 58. 전통적인 for 문보다는 for-each 문을 사용하라

for(Iterator<Element> i = c.iterator(); i.hasNext();) {
  Element e = i.next();
  ...
}
for(Element e : elements) {
  ...
}
  • 반복자와 인덱스 변수는 모두 코드를 지저분하게 할 뿐이므로 이를 생략할 수 있는 for-each문을 사용하라

for-each 문을 사용할 수 없는 세가지 상황

  1. 컬렉션을 순회하면서 선택된 원소를 제거해야 한다면 반복자의 remove 메서드를 호출해야 한다.
  2. 리스트나 배열을 순회하면서 그 원소의 값 일부 혹은 전체를 교체해야 한다면 리스트의 반복자나 배열의 인덱스를 사용해야 한다.
  3. 여러 컬렉션을 병렬로 순회해야 한다면 반복자와 인덱스 변수를 사용해 엄격하고 명시적으로 제어해야 한다.

아이템 59. 라이브러리를 익히고 사용하라

라이브러리 사용의 이점

  1. 그 코드를 작성한 전문가의 지식과 앞서 사용한 다른 프로그래머들의 경험을 활용할 수 있다.
  2. 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 된다.
  3. 따로 노력하지 않아도 성능이 지속해서 개선된다.
  4. 기능이 점점 많아진다
  5. 코드가 많은 사람에게 낯익은 코드가 된다.
  • 자바 프로그래머라면 적어도 java.lang, java.util, java.io와 그 하위 패키지들에는 익숙해져야 한다.
  • 코드 품질에도 규모의 경제가 적용된다.

아이템 60. 정확한 답이 필요하다면 float와 double은 피하라

  • float와 double 타입은 넓은 범위의 수를 빠르게 정밀한 근사치로 계산하도록 설계되었다.
  • 정확한 답이 필요하다면 BigDecimal을 사용하라
  • BigDecimal이 쓰기 불편하거나 성능이 중요하다면 int 혹은 long을 활용하라

아이템 61. 박싱된 기본 타입보다는 기본 타입을 사용하라

박싱 타입과 기본 타입의 차이점

  1. 박싱 타입은 값이 같아도 서로 다르게 식별될 수 있다.
  2. 박싱 타입은 null을 가질 수 있다.
  3. 기본 타입이 박싱 타입보다 시간과 메모리 사용면에서 더 효율적이다.

오류가 발생할 수 있는 상황

  • 박싱된 기본타입에 == 연산자를 사용하면 오류가 일어난다.
  • 기본 타입과 박싱된 기본 타입을 혼용한 연산에서는 박싱된 기본 타입의 박싱이 자동으로 풀린다.
    • null 참조를 언박싱하면 NPE가 발생한다.

박싱 타입을 사용해야 하는 경우

  • 매개변수화 타입이나 매개변수화 메서드의 타입 매개변수로는 박싱된 기본 타입을 써야 한다.
  • 리플렉션을 통해 메서드를 호출할 때도 박싱된 기본타입을 사용해야 한다.

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

  • 문자열은 다른 값 타입을 대신하기에 적합하지 않다.
  • 문자열은 열거 타입을 대신하기에 적합하지 않다.
  • 문자열은 혼합 타입을 대신하기에 적합하지 않다.
    • 타입이 혼합되어 있으면 전용 클래스를 선언하라
  • 문자열은 권한을 표현하기에 적합하지 않다.
    • 문자열이 권한의 고유성을 보장하지 못하므로 멀티 스레드 환경에서의 사용 혹은 외부 공격으로부터 위험할 수 있다.

아이템 63. 문자열 연결은 느리니 주의하라

  • 문자열은 불변이므로 문자열 연결 연산자로 문자열 n개를 연결한다면 시간은 n제곱에 비례한다.
  • 성능을 포기하고 싶지 않다면 StringBuilder를 사용하라

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

  • 적합한 인터페이스만 있다면 매개변수뿐 아니라 반환값, 변수, 필드를 전부 인터페이스 타입으로 선언하라
    • 인터페이스를 타입으로 사용하게되면 프로그램이 훨씬 유연해질 수 있다.
  • 적합한 인터페이스가 없다면 당연히 클래스로 참조해야 한다.
    • 값 클래스, 클래스 기반으로 작성된 프레임 워크가 제공하는 객체등이 해당한다.
    • 인터페이스에 없는 메소드를 제공하는 클래스의 경우에도 클래스로 참조해야 한다.

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

리플렉션 사용의 단점

  • 컴파일타임 타입 검사가 주는 이점을 하나도 누릴 수 없다.

  • 리플렉션을 이용하면 코드가 지저분하고 장황해진다.

  • 성능이 떨어진다

  • 인터페이스나 상위 클래스를 이용할 수 있다면 인스턴스 생성에만 리플렉션을 사용하고 참조는 인터페이스나 상위 클래스로 참조하라

  • 리플렉션 예외를 잡을 때 ReflectiveOperationException을 사용해 코드 길이를 줄일 수 있다(자바 7 이후)

아이템 66. 네이티브 메서드는 신중히 사용하라

  • 성능을 개선할 목적으로 네이티브 메서드를 사용하는 것은 거의 권장되지 않는다.
  • 네이티브 메서드를 사용하는 애플리케이션은 메모리 훼손 오류로부터 더이상 안전하지 않다.
  • 가비지 컬렉터는 네이티브 메모리를 자동 회수 하지 못하고 추적도 불가능하다.

아이템 67. 최적화는 신중히 하라

  • 설계 단계에서 성능을 반드시 염두해야 하고 구현에서는 빠른 프로그램보다는 좋은 프로그램을 작성하라
    • 아키텍처의 결함이 성능을 제한한다면 시스템 전체를 모두 바꿔야할 수도 있다.
  • 성능을 제한하는 설계를 피하라
    • 추후에 변경하기가 거의 불가능할 수 있으며 성능을 심각하게 제한할 수 있다.
  • API를 설계할 때 성능에 주는 영향을 고려하라. 다만 성능을 위해 API를 왜곡해서는 안된다.
  • 최적화를 수행한다면 알고리즘을 우선 살펴야하고 시도 전후로 성능을 측정하라

아이템 68. 일반적으로 통용되는 명명 규칙을 따르라

철자 규칙

  1. 패키지와 모듈 이름은 각 요소를 점(.)으로 구분하여 계층적으로 짓는다
    • 조직 바깥에서 사용된다면 인터넷 도메인 이름을 역순으로 사용한다.
    • 각 요소는 일반적으로 8자 이하의 짧은 단어로 한다.(약어 추천)
    • ex) com.google, com.naver
  2. 클래스와 인터페이스의 이름은 하나 이상의 단어로 이뤄지며 각 단어는 대문자로 시작한다.
    • 널리 통용되는 줄임말을 제외하고는 단어를 줄여 쓰지 않는다.
    • 약자의 경우 첫 글자만 대문자로 하는 쪽이 훨씬 많다(HttpUrl vs HTTPURL)
  3. 메서드와 필드 이름은 클래스 명명 규칙을 따르되 첫 글자를 소문자로 쓴다.
    • 단 상수 필드는 모두 대문자로 쓰고 단어 사이를 밑줄로 구분한다(NEGATIVE_INFINITY)
  4. 지역 변수는 문맥에서 유추하기 쉬우므로 약어를 사용해도 좋다.
  5. 타입 매겨변수 이름은 보통 한 문자로 표현한다.
    • T : 임의의 타입
    • E : 컬렉션 원소의 타입
    • K : 맵의 키
    • V : 맵의 값
    • X : 예외
    • R : 메서드의 반환 타입
    • T U V 혹은 T1 T2 T3 : 임의 타입의 시퀀스

문법 규칙

  1. 객체를 생성할 수 있는 클래스의 이름은 단수 명사나 명사구를 사용한다(Thread, PriorityQueue, ChessPiece)
  2. 객체를 생성할 수 없는 클래스의 이름은 보통 복수형 명사로 짓는다(Collectors, Collections)
  3. 인터페이스의 이름은 클래스와 똑같이 짓거나 able 또는 ible로 끝나는 형용사로 짓는다(Runnable, Iterable, Accessible)
  4. 어떤 동작을 수행하는 메서드의 이름은 동사나 동사구로 짓는다(append, drawImage)
  5. boolean 값을 반환하는 메서드는 보통 is나 드물게 has로 시작하고 명사나 명사구 혹은 형용사로 기능하는 아무 단어나 구로 끝나도록 짓는다.(isDigit, isProbablePrime, isEmpty, isEnabled, hasSiblings)
  6. 반환 타입이 boolean이 아니거나 해당 인스턴스의 속성을 반환하는 메서드의 이름은 보통 명사, 명사구, 혹은 get로 시작하는 동사구로 짓는다(size, hashCode, getTime)
  7. 객체의 타입을 바꿔서 다른 타입의 또 다른 객체를 반환하는 인스턴스 메서드의 이름은 toType 형태로 짓는다(toString, toArray)
  8. 객체의 내용을 다른 뷰로 보여주는 메서드의 이름은 asType 형태로 짓는다(asList)
  9. 객체의 값을 기본 타입 값으로 반환하는 메서드의 이름은 보통 typeValue 형태로 짓는다(intValue)
  10. 정적 팩터리의 이름은 from, of, valueOf, instance, getInstance, newInstance, getType, newType을 흔히 사용한다.
  11. boolean 타입의 필드 이름은 접근자 메서드에서 앞단어(is, has)를 뺀 형태다.
  12. 그 이외의 필드는 명사나 명사구를 사용한다(height, digits, bodyStyle)
Clone this wiki locally