본문 바로가기

프로그래밍 놀이터/디자인 패턴, 리펙토링125

[Effective Java] 스레드 그룹보다는 실행자와 작업을 사용하자. [Effective Java] 스레드 그룹보다는 실행자와 작업을 사용하자. - 자바 1.5 배포판 이후에 java.util.concurrent 패키지가 추가되었다. 여기에는 실행자 프레임워크(Executor Framework) 가 포함되어 있다. 이 녀석을 사용하면 Work queue 를 쉽게 관리할 수 있다. ExecutorService executor = Executors.newSingleThreadExecutor();executor.execute(runnable);executor.shutdown(); // 추가된 task 들의 실행은 보장한다. shutdownNow() 도 있다. 위와 같은 간단한 코드로 쉽게 queue 를 만들어 실행시킬 수 있고, shutdown 시킬 수 있다. - Executo.. 2017. 3. 10.
[Effective Java] 지나친 동기화는 피하자 [Effective Java] 지나친 동기화는 피하자 - 지나친 동기화는 성능을 저하시키고 교착상태(dead lock)을 유발시키며, 심지어 예기치 않은 행동을 초래할 수 있다. - 동기화된 메소드나 블록 안에서 절대로 클라이언트에게 제어권을 넘기면 안 된다. 즉, 동기화된 영역 내부에서는 오버라이딩된 메소드를 호출하지 않아야 하며, 함수 객체의 형태로 클라이언트가 제공하는 메소드도 호출하지 말아야 한다. 동기화된 영역을 갖는 클래스의 관점에서 그런 메소드들은 매우 이질적인 녀석들이다. 그 메소드가 무슨 일을 하는지 알지 못하며, 이질적인 일을 하는 것을 제어하지도 못한다. 외계인 메소드가 하는 일에 따라 다르겠지만, 동기화된 영역에서 그 메소드를 호출하면 예외나 dead lock 또는 데이터 손상까지 .. 2017. 3. 9.
[Effective Java] 공유하는 가변 데이터에 접근 시 동기화하자. [Effective Java] 공유하는 가변 데이터에 접근 시 동기화하자. - 동기화를 하지 않으면, 하나의 스레드에서 변경한 내용을 다른 스레드에서 못 볼 수 있다. 동기화는 불안정 상태의 객체를 스레드가 볼 수 없도록 하는 것은 물론, 동기화된 메소드나 블록에 진입하는 각 스레드가 앞에서의 모든 변경(같은 락으로 보호되었던)이 반영된 결과를 볼 수 있게 해준다. - 자바 언어 명세에서는 long 이나 double 타입이 아닌 변수의 값을 읽거나 쓸 때는 원자성을 보장한다. long 이나 double 타입이 아닌 변수의 값을 읽으면 어떤 스레드가 그 변수에 저장했던 값을 반환 받을 수 있다는 것. 실제로 동기화하지 않고 여러 스레드가 그 변수를 동시에 수정해도 그때그때 수정된 값이 반영된다. 스레드가 .. 2017. 3. 7.
[Effective Java] 예외를 묵살하지 말자. [Effective Java] 예외를 묵살하지 말자. - 비어있는 catch 블록을 갖는 try 문으로 메소드 호출을 둘러싸며 예외를 묵살하기가 매우 쉽다. - 최소한 catch 블록에는 예외를 무시한 이유를 설명하는 주석이라도 한 줄 들어 있어야 한다. - 예외를 무시해도 좋은 그런 경우의 예는 FileInputStream 을 닫을 때이다. catch, Effective JAVA, fineinputstream, TRY, [Effective Java] 예외를 묵살하지 말자., 무시한 이유, 예외 무시, 예외 묵살, 주석 2017. 3. 6.
[Effective Java] 실패 원자성을 갖도록 노력하자 [Effective Java] 실패 원자성을 갖도록 노력하자 - 일반적으로 호출된 메소드가 실행에 실패하더라도 객체 상태는 메소드 호출 전과 같아야 한다. 이런 특성을 갖는 메소드를 실패 원자성(failure atomic) 메소드라 한다. - 가장 간단한 방법은 불변 객체로 설계하는 것이다. 객체가 불변이면 실패 원자성과는 아예 무관하다. - 가변 객체를 처리하는 메소드의 경우에 실패 원자성을 성취하는 가장 보편적인 방법은 연산 수행 전에 매개 변수의 유효성을 검사하는 것이다. - 실패 원자성을 성취하는 더 좋은 방법은, 객체를 변경하는 코드 부분에 앞서 실패할 수 있는 코드 부분이 실행되도록 연산 순서를 조정하는 것이다. - 또 다른 방법은 ( 흔하지 않지만 ) 연산 도중에 발생하는 실패를 가로채는 복.. 2017. 3. 3.
[Effective Java] 실패 상황 정보를 상세 메세지에 포함하자. [Effective Java] 실패 상황 정보를 상세 메세지에 포함하자. - 예외를 발생시킬 때 toString 메소드에서 실패 원인과 연관된 가능한 많은 정보를 반환하도록 상세 메세지를 포함시켜 주는 것이 좋다. 실패 상황 정보를 잡으려면, "예외 발생에 기여한" 모든 매개 변수와 필드의 값이 예외의 상세 메세지에 포함되어야 한다. IndexOutOfBoundsException 이 좋은 예이다. - 실패 상황정보를 알려주는 접근자 메소드를 해당 예외에서 제공하는 것이 좋을 수 있다. 특히 checked 예외에 대한 접근자 메소드를 제공하는 것이 더 중요하다. 실패에 따른 장애 복구에 유용하기 때문이다 unchecked 예외의 상세 내역을 프로그래머가 사용하는 경우는 거의 없다. 그러나 unchecked.. 2017. 3. 2.
[Effective Java] 메소드가 던지는 모든 예외를 문서화하자. [Effective Java] 메소드가 던지는 모든 예외를 문서화하자. - Javadoc 의 @throws 태그를 사용해서 항상 checked 예외는 별도로 선언하고, 각 예외가 발생하는 상황을 정확하게 문서화하자. 메소드가 던지는 예외가 많다고 해서 메소드 명세에 각 예외를 정확하게 선언하지 않고, 그 예외 클래스의 대표적인 슈퍼 클래스만 함축해서 나타내면 안 된다. - unchecked 예외의 문서 내역은 메소드가 성공적으로 실행되기 위한 사전조건(precondition)을 효과적으로 나타낸다. - 인터페이스에 정의된 메소드의 경우 자신이 던질 수 있는 unchecked 예외를 문서화하는 것이 "특히" 중요하다. 그 인터페이스의 보편적 계약 중 일부분이 되며, 인터페이스를 구현하는 여러 구현체들 간의.. 2017. 2. 28.
[Effective Java] 하위 계층의 예외 처리를 신중하게 하자. [Effective Java] 하위 계층의 예외 처리를 신중하게 하자. - 상위 계층에서 하위 계층의 예외를 반드시 catch 해야 한다. 그리고 그 예외대신에 상위 계층의 추상체가 알 수 있는 예외로 바꿔 던져야 한다. 이 이디엄을 예외 변환(exception translation)이라 한다. 그렇지 않으면 구현 내용을 공개하는 것처럼 되어 나중에 호환성 이슈를 겪게 된다. - 만약 예외 변환을 사용하면서 근본적인 이유까지 확실히 알고 싶다면 변화할 때 excpetion 을 담아서 전달할 수 있다. 예를 들어 throw new HigherLevelException( lowerLevelException ) - 예외 연쇄 - 하위 계층(저수준)에서 발생한 예외를 분별 없이 전파하는 것보다는 예외 변환을 사.. 2017. 2. 27.
[Effective Java] 표준 예외를 사용하자 [Effective Java] 표준 예외를 사용하자 - 기본 예외를 재사용하면 여러 가지 장점이 있다. 프로그래머들이 이미 익숙해진 내용과 일치하기 때문에 우리 API 를 배우고 사용하기 쉽게 해준다. 생소한 예외를 사용하지 않으므로 코드를 이해하기 쉽다. 메모리 사용도 적게하고 클래스를 메모리로 로딩하는 시간도 줄어든다. - 자주 재사용되는 형태의 exception 은 IllegalArgumentException, IllegalStateException, NullPointerException, UnSupportedOperationException 등이 있다. API, Effective JAVA, IllegalArgumentException, illegalstateexception, NullPointer.. 2017. 2. 24.