Effective Java 2/E - Chatper 08 일반적인 프로그래밍 원칙들 (2)

Rule 51 - 문자열 연결 시 성능에 주의하라

n개의 문자열에 연결 연산자(+ or concat)를 반복 적용해서 연결하는데 드는 시간은 n^2에 비례한다.

문자열은 불변객체이기 때문이다

반복적으로 문자열을 연결해야한다면 StringBuilder을 사용해야한다.

example

public String statement() {
    StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH);
    for (int i = 0; i < numItems(); i++)
        b.append(lineForItem(i));
    return b.toString();
}

StringBuffer의 경우 동기화가 되기 때문에 성능이 저하된다. 쓰레드 안정성이 필요하지 않다면 (예를 들면 지역변수라면) StringBuilder를 쓰도록하자.

Rule 52 - 객체를 참조할 때는 그 인터페이스를 사용하라

인터페이스를 자료형으로 쓰는 습관을 들이면 프로그램은 더욱 유연해진다.

example

// 좋은 예제
List<Subscriber> subscribers = new Vector<Subscriber>();
// 나쁜 예제
Vector<Subscriber> subscribers = new Vector<Subscriber>();

인터페이스를 자료형으로 사용하면 구현체를 변경할 수 있으므로 훨씬 유연하다. 하지만 실제 구상클래스가 특별한 기능(예를 들면 동기화)을 제공한다면 해당 기능을 유지하도록 해야한다.

적당한 인터페이스가 없는 경우에는 객체를 클래스로 참조하는 것이 당연하다.

  • 값객체
  • final 클래스
  • 유틸성 클래스(Random)

인터페이스가 없고 기반클래스가 있다면 그것을 사용하는 것도 한 방법이다.

결론

  • 인터페이스를 통한 참조를 하면 유연해진다.
  • 적절한 인터페이스가 없다면 가장 일반적인 클래스(super class)를 사용하도록 하라

Rule 53 - 리플렉션 대신 인터페이스를 이용하라.

리플렉션

클래스의 정보를 가져오는 프로그램을 작성할 수 있게 하는 기능. 클래스의 맴버 이름이나 필드 자료형, 메서드 시그너처 등의 정보를 얻어낼 수 있다.

  • Class, Constructor, Method, Field

그리고 위 객체들을 이용하면 실제 행위나 상태들을 반영적으로(reflectively) 조작할 수 있다.

리플렉션의 단점

  1. 실행시점 오류 가능성이 큼
  2. 가독성이 매우 떨어짐
  3. 성능이 낮음

결론

컴파일 시점에 알수 없는(실행시점에 알 수 있는) 클래스를 이용하고 싶다면, 리플렉션을 사용하되 가능하면 객체를 만들 때만 이용하고, 객체를 참조할 때는 컴파일 시에 알고 있는 인터페이스나 상위 클래스를 이용하라

Rule 54 - 네이티브 메서드는 신중하게 사용하라

JNI : Java Native interface**

C나 C++ 등의 네이티브 프로그래밍 언어로 작성된 네이티브 메서드를 호출하는데 이용되는 기능

용도

  1. OS(플랫폼) 고유 기능 이용 가능
  2. 네이티브 라이브러리 재사용
  3. 성능 향상

그러나 네이티브 메서드를 통한 성능개선은 추천하지 않는다.

  • 과거에 비해 JVM의 성능 향상
  • Java 만으로 필적한 성능 가능

네이티브 메서드 직접 사용 시 단점

  1. 안전하지 않음
  2. 메모리 참조 이슈
  3. 플랫폼 종속정 (이식성이 낮음)
  4. 디버깅 어려움
  5. 잘못 사용할 경우 성능하락
  6. 가독성이 떨어짐

결론

가능하면 네이티브 메서드는 사용하지 않는다. 만약 사용한다면 최소한의 용도로만 이용하고, 검증을 확실히 한다.

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

MJ

MJ
Backend 개발자 사람입니다. 어플리케이션의 복잡성을 다루는 DDD에 관심이 많습니다. 어제보다 더 나은 개발자가 되려고 항상 노력합니다.

spring boot 2.4.x 에서 openfeign + hystrix 통합하기

spring-boot 2.4.x spring-cloud 2020.x 의존성 상황에서 feign.hystrix.enabled=true가 안됨`feign.circuitbreaker.enabled=true` 로 바꿔보지만 openfeign과 hystr...… Continue reading

IDDD 14장. 애플리케이션

Published on June 19, 2018