블로그 개편해야 것다.

한동안 개인적으로 많은 일들이 있었다.
바쁘다는 이유로 블로그를 방치해두니 맘이 항상 찜찜했다.
그간 생각한 결과 블로그를 개편(?)해야 겠다.
지금것 기술 위주의 정리에 초점을 맞췄는데 그 보다는 개인적인 생각과 이야기...
그리고 소중한 경험들을 위주로 개편할 예정이다.

시기는....

음...

가급적 빠른 시일내에...

끝과 시작을 준비하는 시간... My Life

현재 몸담고 있는 곳에서 마지막을 준비하고 있다.
그리고 새로운 곳에서의 시작도 준비하고 있다.

맡은 일에 충실해서 끝과 시작을 잘 해야겠다.

Effective Java (3) JAVA

5. 메소드

5.1. 인자의 유효성을 검사하라
유효성 검사를 통해 인자가 유효하지 않을 때 적절한 예외를 발생시키면, 빠르고 깔끔하게 메소드를 종료할 수 있다.

5.2. 메소드 시그니처를 신중하게 설계하라
1. 메소드 이름을 신중하게 결정하라. 이름은 항상 표준 명명 규칙을 따라야 한다.
2. 편리한 메소드를 제공하기 위해 너무 애쓰지 마라.
3. 인자를 너무 많이 받지 마라. 현실적으로 인자 개수가 세 개를 넘으면 문제가 있다.

5.3. null이 아닌 길이가 0인 배열을 리턴하라

 

5.4. 외부에 제공하는 API의 모든 구성요소에 대해 문서화 주석을 달아라
API를 문서화하려면, 외부에 제공하는 모든 클래스, 인터페이스, 생성자, 메소드, 필드에 문서화 주석을 달아야 한다.

6. 예외처리

6.1. 예외는 예외상황에서만 써야 한다
예외 기반의 구현패턴은 코드의 목적을 애매하게 만들고 성능도 떨어뜨린다.


6.2. 처리해야 하는 예외와 런타임 예외를 구분해서 던져라
1. 처리해야 하는 예외
  호출자가 예외상황을 복구할 수 있다고 기대할 수 있을 때 던진다.
 
2. 처리하지 않는 예외
  런타임 예외와 에러가 있다. 이 둘의 행동 방식은 똑같다. 이것들을 잡을 필요도 없고
  특별한 경우가 아니라면 잡아서도 안 된다. 이는 복구할 수 없는 상황이기 때문에 더
  이상 프로그램을 실행하는 것은 위험할 수도 있다.

6.3. 표준 예외를 써라

예외

용도

IllegalArgumentException

인자 값이 적절하지 못할 때

IllegalStateException

호출을 받은 객체상태가 적절하지 못할 때

NullPointerException

null을 금지한 인자 값이 null일 때

IndexOutOfBoundsException

인덱스 값이 범위를 벗어났을 때

ConcurrentModificationException

동시 수정을 금지한 객체를 동시에 수정할 때

UnsupportedOperationException

객체가 메소드를 지원하지 않을 때


6.4. 예외처리 전략
1. 비즈니스 로직을 수행하는 중 발생하는 비즈니스적인 Exception을 제외하고는 모든 Exception을 Unchecked Exception으로 처리한다.

2. Checked Exception 중 고객이 인지해야 하는 Exception은 메시징 처리를 통해 display 해주며, 시스템 관리자에게 메일로도 통보해 줄 수 있도록 해준다. (에러 메시지를 처리하는 페이지를 따로 두어 처리한다.)

3. Unchecked Exception이 발생하는 경우 Exception 내용을 시스템 관리자에게 메일로 통보해준다.

4. database 다운과 같이 프로그램적으로 해결하기 힘든 에러가 발생할 경우에는  Unchecked Exception을 사용한다.

5. Unchecked Exception 이나 Checked Exception 중 처리되지 않는 Exception은 servlet container에서 제공하는 에러 처리 기능을 활용하여 처리토록 한다. 예를 들어, 404, 500에러 발생시 특정페이지로 이동토록 설정한다.

 

public String socketGet(String host, int port, String uri, String argv) {
    StringBuffer result = new StringBuffer();

    try {
        URL url = new URL("http", host,  port, uri + argv);
        URLConnection conn  = url.openConnection();
        InputStream is = conn.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));

        try {
            String line = "";
           
            while (line != null) {
                line = reader.readLine();
                if (line != null) result.append(line);
            }
        } finally {
            reader.close();
        }

        return result.toString();
    } catch (Exception e) {
        System.err.println(e.getMessage());
        return null;
    }
}

 


Effective Java (2) JAVA

3. 객체 생성과 파괴

객체를 생성하고 파괴하는 방법을 다룰 것이다. 객체를 생성해야 할 때와 생성하지 말아야할 때, 객체를 생성하는 방법과 생성을 피할 수 있는 방법, 객체가 정확한 시기에 파괴되었다는 것을 확인할 수 있는 방법, 객체를 파괴하기 전에 반드시 처리해야 하는 작업들을 관리하는 방법들에 대해 생각해 볼 것이다.

3.1. 생성자 대신 static factory method를 고려하라
 1. 장점
   - static factory method는 생성자와 달리 알맞은 이름을 줄 수 있다.
   - 생성자와 달리 호출될 때마다 새로운 객체를 생성하지 않아도 된다.
     이를 이용하면 특정 시점에 존재하는 인스턴스들을 엄격하게 관리할 수 있다.

     1) 특정 클래스가 싱글톤 이라는 것을 보장
     2) 내용이 동등한 불변 클래스의 인스턴스가 여러 개 존재하지 않는다.
   - 생성자는 자신이 정의된 클래스의 인스턴스만 리턴할 수 있지만, static factory method는 자신이 선언된 것과 같은 타입의
     인스턴스는 모두 리턴할 수 있다.

 2. 단점
   - 메소드를 정의한 클래스가 public 이나 protected 생성자를 제공하지 않으면, 다른 클래스가 이 클래스를 상속받을 수 없다.
   - 다른 스택틱 메소드와의 차이를 명시할 수 없다.

3.2. private 생성자를 써서 싱글톤을 유지하라
 1. 모든 조건을 고려해 보고, 영원히 싱글톤으로 남는 클래스라면 스태틱 필드를 쓰고, 그렇지 않으면 스태틱 팩토리 메소드를 쓰는 것이 좋다.
 2. 싱글톤을 보장하려면, 반드시 readResolve 메소드를 제공해야한다. 그렇지 않으면, 인스턴트들을 역직렬화 할 때마다 새로운 인스턴스가 생겨난다.

   Private Object readResolve() throws ObjectStreamException {
       /*
         * 진짜 인스턴스만 리턴한다.
         * 역직렬화로 태어난 가짜 인스턴스들은 태어나자마자 GC에게 던져진다.
         */

        Return INSTANCE;
   }

3.3. private 생성자로 인스턴스를 만들지 못하게 하라
 다른 클래스에서 해당 클래스를 생성 또는 상속하지 못하게 할 때 사용한다.


3.4. 쓸데없는 객체를 중복 생성하지 마라
 아주 특별한 경우가 아니라면, 동등한 기능을 하는 객체를 필요할 때마다 생성하는 것보다는 한 객체를 재사용하는 것이 더 낫다.
 재사용이 속도나 효율적인 코드 생산에 이바지 한다.


3.5. 쓸모 없는 객체 참조는 제거하라
 쓸모 없는 객체를 참조하게 된다면 이는 GC 대상에서 제외되므로 메모리 누수가 발생된다.
 보통 자신만의 메오리 영역을 가지는 클래스를 쓸 때, 프로그래머는 메모리 누수에 대해 항상 생각해야 한다.
 구성요소를 비울 때마다 null을 대입하여 보관하던 객체 참조를 제거해야 한다. (쓸모 없는 참조에 null 을 대입해 버리면 된다.)

3.6. 종료자들을 쓰지 마라
 종료자는 호출되자마자 즉각 실행되지 않는다. 어떤 객체에 대한 모든 참조가 없어진 후, 이 객체의 종료자가 수행될 때까지 시간은 얼마나 걸릴지 아무도 모른다. 따라서 알맞은 시간 안에 반드시 수행해야 하는 작업을 종료자에서 처리하면 절대 안 된다.(중요한 영속 상태를 갱신하는 작업을 종료자에서 처리하지 말아야 한다.)
 명시적인 종결처리 메소드를 제공하고, 이 클래스의 인스턴스를 쓰고 난 다음에 반드시 이 메소드를 호출하게 하라. 또, 이 클래스에 각 인스턴스가 종료되었는지 알 수 있는 private 필드를 두어야 한다. 명시적인 종결처리 메소드는 종결처리를 끝마치면 해당 인스턴스를 더 이상 쓸 수 없다는 사실을 이 필드에 기록해 두어야 한다. 다른 메소드들은 항상 이 필드를 먼저 확인하고, 이미 해당 인스턴스가 더 이상 쓸 수 없는 상태라면 IllegalStateException 을 던져야 한다.
 명시적인 종결처리 메소드는 즉각적인 종결처리를 위해 try-finally 구문과 함께 쓰는 것이 좋다. 이때 명시적인 종결처리 메소드는 finally 블록에서 호출해야 어떤 상황에서도 명시적인 종결처리 메소드가 호출된다는 것을 보장할 수 있다.

 Foo foo = new Foo(…);
 try {
     //foo 로 뭔가 작업하고

 } finally {
     Foo.terminate(); // 명시적인 종결처리 메소드
 }

 종료자를 쓰는 경우는?
 첫째, 앞에서 설명한 명시적인 종결처리 메소드를 호출하는 것을 잊었을 경우를 대비한 “안전망” 역할을 한다. 물론, 종료자가 바로바로 호출된다거나 반드시 호출된다는 보장은 없지만, 만약 클라이언트가 명시적인 종결처리 메소드를 호출하지 않았을 때, 중요한 자원을 아예 반환하지 않는 것보다 늦게라도 반환할 수 있는 가능성을 열어 두는 편이 더 낫다.
 예를 들면, InputStream, OutputStream, Timer 등의 클래스에는 이런 “안전망” 역할을 하는 종료자들이 정의되어 있다.
 둘째, native peer와 관련된 객체를 쓸 때 종료자를 쓴다. native peer란 일반 자바 객체가 native 메소드 호출을 통해 자신의 역할을 맡길 수 있는 native 객체를 의미한다.


4. 클래스와 인터페이스

강건하고(robust), 유연하고(flexible), 쓸모있게(usable) 만들기 위해 이 도구들을 어떻게 써야 하는지 알아보도록 하겠다.

4.1. 클래스와 멤버에 대한 접근은 최소화하라
우선 클래스의 public API를 신중하게 모두 설계한 다음, 나머지 멤버들은 모두 습관처럼 private로 만들어야 한다.
즉, 현재 개발한 패키지를 다시 한번 살표보고 클래스 사이의 의존성을 더 줄일 수 있는 방법은 없는지 생각해 보아야 한다.

4.2. 불변 클래스를 써라
불변 클래스(immutable class)란 인스턴스의 내용을 절대로 바꿀 수 없는 클래스이다.
이 클래스의 각 인스턴스가 저장하는 정보는 인스턴스를 생성할 때 단 한번 만든 후에 인스턴스가 소명될 때까지 변하지 않는다.
불변 클래스를 만들려면 다음과 같은 규칙을 따라야 한다.

1. 객체를 변경하는 메소드를 제공하지 않는다.
2. 재정의 할 수 있는 메소드를 제공하지 않는다.
3. 모든 필드를 final로 만든다.
4. 모든 필드를 private로 만든다.
5. 가변 객체를 참조하는 필드는 배타적으로 접근해야 한다.


4.3. 상속보다 컴포지션을 써라
상속이 비록 강력한 기능이긴 하지만 캡슐화를 위반하기 때문에 문제를 발생시킬 수 있다.
상위 클래스와 하위 클래스가 정말로 서브타입 관계가 있을 때만 상속을 쓸 수 있다.
하지만 이런 경우라도 하위 클래스와 상위 클래스가 다른 패키지에 있거나 상위 클래스가 상속을 위해 설계되지 않았다면 상속받은 하위 클래스에 문제가 생기기 쉽다. 컴포지션과 포워딩을 쓰면 상속의 폐해를 막을 수 있다. 특히, 적절한 인터페이스가 있어서 래퍼 클래스를 구현할 수 있다면 금상첨화이다. 래퍼 클래스는 강건할 뿐만 아니라 기능도 막강하다.


4.4. 상속받을 수 있도록 설계하고 문서화하라. 아니면 상속을 금지하라
클래스 명세문서에 메소드를 재정의하면 발생할 수 있는 모든 파급 효과를 자세하고 정확하게 기술해야 한다. 관례에 따라, 이런 경우에 메소드 명세문서 마지막 부분에 “이번 구현에서는” 으로 시작하는 설명을 달아 놓는 것이 좋다.

4.5. 추상 클래스보다는 인터페이스를 써라
인터페이스를 쓰면 깔끔하게 mixin 타입을 정의할 수 있다. 즉, 어떤 클래스가 자신의 기본 타입 외에 새로운 기능을 위해 마음대로 골라서 추가할 수 있는 타입이다.


로또 4등 My Life

10월초에 사둔 로또를 오늘 맞춰보았다.

순간 숨이 막히며 긴장되었지만 허탈해 졌다.

처음 3번째 숫자까지 연속으로 일치해서 긴장했는데 나머지 세 개의 숫자들 중에 한개만 일치했다.

그래도 4개 맞춰서 4등...

잽싸게 금액을 확인해 보니 57,706원...

사람 욕심이 끝이 없다보니 아쉬웠지만 그래도 좋다.. ㅋㅋ

오늘도 로또를 사야지~~~

1 2 3 4 5 6 7 8 9 10 다음