본문 바로가기

전체 글

(33)
8. finalizer와 cleaner 사용을 피하라
7. 다 쓴 객체 참조를 해제하라 자바같은 가비지 컬렉션을 가진 언어에서는 메모리 누수를 찾기가 매우 어렵다.객체 참조를 하나라도 살려두면 가비지 컬렉터는 그 객체뿐 아니라 그 객체가 참조하는 모든 객체를 회수하지 못 한다. 이를 해결하는 방법은 간단하다. 해당 참조를 다 썻을 때 null 처리 해주면 된다. public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { this.elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { this.ensureCapa..
6. 불필요한 객체 생성을 피하라 다음은 정규표현식을 활용한 예제이다. static boolean isRomanNumera(String s) { return s.matches("^(?-.)M* ....; } 성능을 개선하려면 필요한 인스턴스를 클래스 초기화과정에서 생성해 캐싱하여, 나중에 해당 인스턴스를 재사용한다.이 방식은 쉬운 방식이지만 성능이 중요한 곳에서는 반복적으로 사용하기 적합치 않다. 이 메서드가 내부에서 만드는 인스턴스는 한 번 쓰이고 버려져 곧바로 가비지 컬렉션 대상이 된다. public class RomanNumerals { private static final Pattern ROMAN = Patterm.compile( "^(?-.)M* .... ); static boolean isRomanNumeral(String s..
5. 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 사용하는 자원에 따라 동작이 달라지는 클래스에는 정적 유틸리티 클래스나 싱글턴 방식이 적합하지 않다. public class SpellChecker { // 유연하지 않고 테스트하기 어렵다. private final Lexicon dictionary = ...; public SpellChecker(Lexicon dictionary) { this.dictionary = Objects.requireNonNull(dictionary); } }​ 클래스가 여러 자원 인스턴스를 지원해야 하며, 클라이언트가 원하는 자원을 사용해야 한다. 이 조건을 만족하는 패턴이 있으니, 바로 인스턴스를 생성할 때 생성자에 필요한 자원을 넘겨주는 방식이다. public class SpellChecker { // 유연하지 않고 테스..
4. 인스턴스화를 막으려거든 private 생성자를 사용하라 가끔 정적 메서드와 정적 필드만을 담은 클래스가 필요할 경우가 있다. 유틸리티 클래스를 만들 때 주로 사용되는데, 이런 클래스들은 인스턴스화 되는 것을 되도록 막아야 한다. 자바에서는 생성자를 개발자가 작성하지 않아도, 내부적으로 생성자를 제공해준다. 그렇기에 이를 막기 위해서는 private로 생성자를 임의로 명시해주는 것이 좋다. 또한 이 방식은 상속을 불가능하게 만든다. 상속을 받으려면 해당 부모 클래스의 생성자를 호출할 수 있어야 하는데, private 선언을 통해 부모 클래스를 상속할 길이 막혀버린다. public class Utility { private Utility() { throw new AssertionError(); } } 결론 유틸리티 클래스들을 정적 메서드로 채우게 된다면 생성자는..
3. private 생성자나 열거 타입으로 싱글턴임을 보증하라 싱글턴(singleton)이란 인스턴스를 오직 하나만 생성할 수 있는 클래스이다. 싱글턴을 만드는 방식은 둘 중 하나다. 두 방식 모두 private으로 감추고, 인스턴스에 접근할 수 있는 수단으로 public static 멤버를 하나 만든다. public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() {...} public void leaveTheBuilding() {...} } 생성자는 INSTANCE 를 초기화할 때 한 번만 호출된다. 그렇기에 전체 시스템에서 해당 클래스는 하나만 생성됨을 보장할 수 있게된다.(단 향후 배울 리플랙션에서 private 생성자를 호출하는 법을 알게된다.) 해당 코드의 장점..
2. 생성자에 매개변수가 많다면 빌더를 고려하라 정적 팩토리와 생성자에는 똑같은 제약이 있다. 매개변수가 많을 때 적절히 대응하기 어렵다는 점이다. 옛 프로그래머들은 이럴 때 점층적 생성자 패턴(telescoping constructor pattern)을 주로 사용했다. public class NutritionFacts { private final int servingSize; // required private final int servings; // required private final int calories; // optional private final int fat; // optional public NutritionFacts(int servingSize, int servings) { this(servingSize, servings, 0)..
02. 카프카의 구성요소 카프카의 주요 구성 요소는 다음 5가지다. 프로듀서 : 데이터 생산자이며 브로커에 메시지를 보내는 애플리케이션 메시지 : 카프카에서 데이터를 다루는 최소 단위 브로커 : 데이터 수신 및 전달하는 서비스 컨슈머 : 브로커에게 메시지를 전달받는 애플리케이션 토픽 : 메시지를 종류별로 관리하는 스토리지. 브로커에 배치되어 관리된다. 프로듀서와 컨슈머는 특정 토픽을 지정하여 메시지를 송수신한다. 프로듀서 -> 브로커 -> 컨슈머의 흐름에서, 프로듀서 -> 브로커는 PUSH형 / 브로커 -> 컨슈머는 PULL형으로 이루어진다. PULL형의 장점은 컨슈머 고장 시 브로커에 미치는 영향이 적으며, 컨슈머의 증감에 효율적으로 대응할 수 있게 된다. 카프카의 브로커에서 분산 처리를 위한 관리 도구로 주키퍼가 필요하다. ..