JAVA
-
equals는 일반 규약을 지켜 재정의 하라JAVA/Effective java 2021. 1. 11. 13:41
equals 메서드는 재정의하기 쉬워 보이지만 자칫 잘못된 결과를 초래할 수 있다. 따라서 가장 쉬운 길은 아예 재정의 하지 않는 것이다. 그냥 두면 그 클래스의 인스턴스는 오직 자신과만 같게 된다. 따라서 다음 열거한 상황 중 하나에 해당되면 재정의하지 않는 것이 최선이다. 1. 각 인스턴스가 본질적으로 고유할 때 값을 표현하는 게 아닌 동작하는 개체를 표현하는 클래스, Thread 클래스는 하나의 좋은 예다. 2. '논리적 동치성'을 검사할 일이 없을 때 Object에 기본 equals는 객체를 식별하기 위해 주소 값을 비교한다. 만일 Pattern에 equals나 String에 equals 등 '논리적 동치성'의 경우가 없을 경우 재정의 하지 않아도 된다. 3. 상위 클래스에 재정의한 equals가..
-
AGGREGATE와 REPOSITORY 5부JAVA/DDD 2021. 1. 8. 19:48
ENTRY POINT와 REPOSITORY 주문은 주문 AGGREGATE의 ENTRY POINT이다. 따라서 주문이 필요한 경우 OrderRepository를 통해 해당 주문 객체를 얻을 수 있다. 그럼 특정한 고객에 대한 주문 목록을 얻어야 한다면 어떻게 해야 할까? 쉽게 생각해 볼 수 있는 방법은 CustomerRepository로부터 고객 객체를 얻은 후 연관을 통해 해당하는 Order 객체들에게 접근하는 것이다. 그러나 이 방법은 Order와 Customer 클래스 간에 양방향 연관 관계를 추가한다. 특정 객체에 속하는 다른 객체들을 조회하는 요구사항마다 양방향 연관 관계를 설정한다면 감당하기 어려울 정도로 모델이 복잡해질 것이다. 고객에 해당하는 주문 목록을 조회하는 적절한 방법은 OrderRe..
-
AGGREGATE와 REPOSITORY 4부JAVA/DDD 2021. 1. 5. 16:39
OrderLineItem은 상품 정보를 알고 있는 책임을 지닌 Product 클래스와 연관 관계를 가지며, 상품의 수량을 속성으로 포함한다. OrderLineItem의 생성자에 전달된 productName은 Product ENTRY POINT를 검색하기 위해 사용하는 검색 키이다. Product은 REFERENCE OBJECT인 동시에 ENTRY POINT이므로 productName을 가지는 Product 인스턴스는 시스템 내에서 유일해야 한다. 따라서 Product를 관리하는 ProductRepository로부터 해당 인스턴스를 얻어 OrderLineItem의 product 속성에 할당한다. getPrice() 메서드는 현재 주문 항목의 가격을 반환하는 메서드로 상품 가격에 상품 수량을 곱한 금액을 반..
-
Try-Finally 대신 Try-with-Resource 사용하라JAVA/Effective java 2021. 1. 4. 10:31
자바 라이브러리에는 InputStream, OutputStream 그리고 java.sql.Connection과 같이 정리(close)가 가능한 리소스가 많다. 하지만 그런 리소스를 사용하는 클라이언트 코드가 보통 리소스 정리를 잘 안 하거나 잘못하는 경우가 있다. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class FirstError extends RuntimeException { } public class SecondException extends RuntimeException { } public class MyResource implements AutoCloseable { public void doSomething() throws FirstEr..
-
Finalizer와 Cleaner는 피하라JAVA/Effective java 2021. 1. 3. 23:16
Finalizer는 예측 불가능하고, 위험하며, 대부분 불필요하다. 그걸 쓰면 이상하게 동작하기도 하고, 성능도 안 좋아지고, 이식성에도 문제가 생길 수 있다. Finalizer를 유용하게 쓸 수 있는 경우는 극히 드물다. finalizer는 GC가 돌때 호출이 되는데 언제 호출되는지 예측할 수 없다. GC에 대상이 된다고 해서 바로 GC가 되는 것이 아니기 때문이다. 다음의 코드는 run() 실행 후 1초 있다가 종료되게 된다. run() 호출후의 finalizerExample의 레퍼런스는 유효하지 않게 되지만 실행해보면 Clean Up을 실행하지는 않는다. GC에 대상은 되지만 바로 되지는 않는다. 그럼 언제 써야 될까? 딱 두가지 경우 안전망 역할로 자원을 반납하고자 하는 경우. 네이티브 리소스를 ..
-
더이상 쓰지 않는 객체 레퍼런스는 없애자 + Weak ReferenceJAVA/Effective java 2021. 1. 2. 20:41
메모리 직접 관리 자바에 GC (가비지 콜렉터)가 있기 때문에 메모리 관리에 대해 신경 쓰지 않아도 될 거라고 생각하기 쉽지만 그렇지 않다. 다음 코드를 살펴보자. 여기서의 size는 index에 역할을 하고 있다. pop()을 보면 내가 넣을 장소가 아닌 뺄 장소로 이동해야 하기 때문에 먼저 --size를 하고 반환한다. 배열은 계속해서 값을 넣기만 하고 없어지지는 않는다. 스택에 계속 쌓다가 많이 빼냈다고 치자, 그래도 스택이 차지하고 있는 메모리는 줄어들지 않는다. 왜냐면 저 스택의 구현체는 필요없는 객체에 대한 레퍼런스를 그대로 가지고 있기 때문이다. 가용한 범위라는 것은 실제 유의미한 element를 가지고 있는 범위이고 이는 size 보다 작은 부분들이다. 그 값 보다 큰 부분에 있는 값들은 ..
-
불필요한 객체를 만들지 말자JAVA/Effective java 2021. 1. 1. 22:37
기능적으로 동일한 객체를 새로 만드는 대신 객체 하나를 재사용하는 것이 대부분 적절하다. 재사용하면 새로운 객체를 만들지 않기 때문에 성능적으로 더 빠르다. 그리고 불변 객체들은 항상 재사용할 수 있다. 문자열 객체 생성 자바의 문자열, String을 new로 생성하면 항상 새로운 객체를 만들게 된다. == 로 주소값을 비교한 name과 name2의 값은 false가 나온다. name에서 힙에 메모리가 할당되고 new로 또 다시 생성했기 때문에 name2에서 새로운 메모리가 할당되어 힙에 생성된다. 따라서 다음과 같이 String 객체를 생성하는 것이 올바르다. String s = "bikini"; 문자열 리터럴을 재사용하기 때문에 해당 자바 가상 머신에 동일한 문자열 리터럴이 존재한다면 그 리터럴을 재..
-
리소스를 엮을 때는 의존성 주입을 선호하라JAVA/Effective java 2020. 12. 31. 18:28
대부분의 클래스는 여러 리소스에 의존한다. 여기서 말하는 리소스는 의존성이다. 이 책에서는 SpellChecker와 Dictionary를 예로 들고 있다. SpellChecker 클래스는 스펠링이 맞는지 확인하는 클래스이고 Dictionary는 사전 클래스이다. 이때 SpellCheck가 Ditionary를 사용하고, 이를 의존하는 리소스 또는 의존성이라고 부른다. 이때 SpellChecker를 다음과 같이 구현하는 경우가 있다. 부적절한 구현 static 유틸 클래스 static 유틸리티 클래스이고 인스턴스로 만들 이유가 없기에 private 한 생성자를 만들었다. public static 한 메서드를 사용해서 클라이언트들이 SpellChecker.isValid 식으로 유틸 클래스를 사용하도록 한다. ..