Clean Code that Works.


Factory Method Pattern(클릭) 
대충은 알아 먹겠는데 해석 하기는 어려운 .. OTL

Singleton Pattern(클릭)

public class Singleton {
private static final Singleton INSTANCE = new Singleton();
// Private constructor prevents instantiation from other classes
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE; }
}
일반 적인 방법
 
public class Singleton {
   // Private constructor prevents instantiation from other classes
   private Singleton() {}
 
   /**
    * SingletonHolder is loaded on the first execution of Singleton.getInstance() 
    * or the first access to SingletonHolder.INSTANCE, not before.
    */
   private static class SingletonHolder { 
     private static final Singleton INSTANCE = new Singleton();
   }
 
   public static Singleton getInstance() {
     return SingletonHolder.INSTANCE;
   }
 }
Lazy loading 스타일.

작년에 패턴책을 보긴 봤는데
기억은 한개도 나지 않는다 -_-..

이건 뭐 적용을 해 봤어야.

그래서 이번 상반기에 꼭 익숙해 져야할 패턴 4가지를 정했다.
  • Factory pattern
  • Composite pattern
  • Decorator pattern
  • Singleton pattern

이 4가지에 대하여 꼭 익숙해 지도록 하자.

자료는 위키 백과에 많다 -ㅅ-;;

한글 위키 백과 보다는 영문 위키 백과
UML 및 더 자세한 설명, 자바 샘플이 있기 때문에 영어 공부도 할 겸해서
영문 위키를 참고 하여 공부할 것을 목표로 하고
번역하고 다시 정리해서 블로그에 올리는 것을 목표로 하자.

이번주 목표는 팩토리 패턴.

디자인 패턴에 관한 소개.
아직 안읽어봄 ;

Design pattern (computer science)




아. 먼가 기술적인 내용이..
포스팅이 안되고 있다 -ㅅ-..

기술적인 내용은 사이트 개발 들어가면서 포스팅 해 봅시다..
그럼 시작!

일반적인 프로젝트는 거의 100% 계획된 일정을 넘긴다. 여러분이 일정을 넘겼을 때, 시간의 양을 늘리는 것이 반드시 필요하다. 그런 경우에는 그렇게 하고, 만약 그렇게 할 수 없다면 다음과 같은 다른 해결책을 시도해 볼 수 있다.

일정에 맞출 수 있다는 희망을 가져라.
 - 희망적인 낙관론은 프로젝트가 일정을 넘겼을 때 보이는 일반적인 반응이다. 전형적인 합리화는 다음과 같다. "요구 사항이 우리가 예상했던 것보다 조금 더 오랜 시간이 걸렸지만, 더 이상 변하기 않기 때문에 나중에 시간을 절약할 수 있을 것이다. 그리고 코드 작성과 테스트 시에 부족한 부분을 보충할 것이다." 하지만 이런 경우는 좀처럼 일어나지 않는다. 300개의 소프트웨어 프로젝트를 대상으로 한 조사에서는 일정을 늦추거나 초과하는 것이 일반적으로 프로젝트의 마무리 단계에서 증가한다는 결론을 내렸다. 프로젝트는 나중에 잃어버린 시간을 보충하지 않는다. 결국 더욱 늦춰질 뿐이다.

팀을 확장하라
 - Fred Brooks의 법치에 따르면, 늦어진 소프트웨어 프로젝트에 사람을 추가하는 것은 프로젝트의 일정을 더 늦춘다고 한다(Brooks 1995). 이는 마치 불난 데 기름을 붓는 것과 같다. Brooks의 설명은 설득력이 있다. 새로운 사람은 무언가를 생산할 수 있기 전에 프로젝트에 익숙해주기 위한 시간이 필요하기 때문이다. 그들의 훈련은 이미 훈련은 받은 사람들의 시간을 빼앗게 된다. 그리고 단순히 사람의 수를 늘리는 것은 프로젝트의 복잡성과 의사 소통의 양을 증가 시킨다. Brooks는 한 여성이 9개월만에 한 아이를 낳을 수 있다고 해서 9명의 여성이 한 달에 한 아이를 낳을 수 있는 것은 아니라는 사실을 지적하였다.
  당연히 여러분은 Brook의 법칙에 있는 경고를 훨씬 자주 주의해야 한다. 프로젝트에 사람을 투입하면, 그들이 프로젝트를 제 시간에 완성시킬 것이라고 기대하기 쉽다. 하지만 경영진들은 소프트웨어 개발이 금속 박판에 못을 박는 일과는 다르다는 것을 이해할 필요가 있다. 더 많은 사람들이 작업을 한다고 해서 반드시 더 많은 작업이 수행된다는 것을 의미하지는 않는다.
  하지만 늦어진 프로젝트에 사람을 추가하는 것이 프로젝트를 더 늦춘다는 단순한 문장은, 어떤 환경에서는 새로운 사람을 추가하여 프로젝트의 속도를 높일 수 있는 가능성을 있다는 사실을 감추고 있다. Brooks가 그의 관점에서 지적했듯이, 독립적으로 나누어져서 수행될 수 없는 소프트웨어 프로젝트에 새로운 사람을 추가하는 것은 도움이 안 된다. 하지만 만약 프로젝트의 작업이 나뉠 수 있다면, 프로젝트의 일정이 늦어졌다고 하더라도 프로젝트를 나누어 서로 다른 사람들에게 일을 할당할 수 있다. 다른 연구자들은 프로젝트의 일정을 늦추지 않고 늦어진 프로젝트에 사람을 추가할 수 있는 환경을 공식적으로 규명하였다.

프로젝트의 범위를 축소하라
 - 프로젝트의 범위를 축소하는 가장 강력한 기법이 종종 간과된다. 만약 어떤 기능을 제거하면, 설계와 코드 작성, 디버깅, 테스트, 그리고 해당 기능에 대한 문서를 제거할 수 있다. 또한, 다른 기능에 대한 해당 기능의 인터페이스도 제거할 수 있다.
  여러분이 제품을 초기에 계획할 때, 제품의 능력을 "반드시 갖추어야 할 것", "가지면 좋은 것", 그리고 "선택적인 것"으로 분류한다. 만약 일정이 늦어지게 되면, "선택적인 것"과 "가지면 좋은 것"에 대한 우선순위를 매겨서 가장 덜 중요한 것을 뺀다.
  어떠한 기능을 완전히 제거할 수 없다면, 같은 기능을 수행하는 보다 값싼 버전을 제공할 수 있다. 아마도 일정에 맞추기는 했지만 성능을 위해서 최적화는 되지 않는 버전을 제공할 것이다. 그리고 최소한의 중요한 기능만이 미숙하게 구현된 버전을 제공할 것이다.
  또한, 느린 버전을 제공하는 것이 훨씬 쉽기 때문에 속도에 대한 요구 사항을 무시하기로 결정할 것이다. 그리고 메모리 집약적인 버전을 제공하는 것이 쉽기 때문에 공간에 대한 요구 사항도 무시할 것이다.
  최소한의 중요한 기능에 대한 개발 시간을 재측정하라. 어떤 기능을 두 시간이나 이틀, 또는 2주 내에 제공할 수 있는가? 이틀 버전 대신 2주 버전, 또는 두 시간 버전 대신 이틀 버전을 작성하여 얻는 것이 무엇인가?

리팩토링은 코드의 품질을 향상시키기 위한 강력한 기법이다.
다른 모든 강력한 도구들처럼, 리팩토링도 만약 잘못 사용된다면 이롭기보다는 해를 끼칠 수 있다.
다음에 소개하는 몇 가지 간단한 지침들이 리팩토링의 실수들을 예방할 수 있다.

리팩토링을 시작하는 코드를 저장한다.
 - 리팩토링을 시작하기 전에, 여러분이 시작한 코드를 얻을 수 있도록 한다. 변경 사항 관리 시스템에 저장하거나 정확한 파일들을 백업디렉토리에 복사한다.
 
작동중인 시스템을 여는 것은 싱크대를 열어서 세면대를 교체하는 것과 같이 간단하고 쉬운 일이 아니라, 인간의 뇌를 열고 뇌의 신경 세포들을 교체하는 것과 같다. 만약 "소프트웨어 뇌수술"과 같은 용어를 사용했다면 유지 보수 작업이 더 쉬워질까?
                                                                                                        - Gerald Weinberg

리팩토링을 작게 유지한다.
 - 어떤 리팩토링들은 다른 것보다 크며, 정확하게 무엇이 "하나의 리팩토링"을 구성하는지는 분명하지 않을 수 있다. 리팩토링을 작게 유지하여 여러분이 변경한 것들이 미치는 모든 영향을 완전하게 이해하고 있어야 한다. Refactoring(Fowler 1999)에서 설명하고 있는 상세한 리팩토링들은 여러분이 이를 어떻게 처리할 것인지에 대한 여러가지 좋은 예제들을 제공하고 있다.

리팩토링은 한 번에 하나만 수행한다.
 - 어떤 리팩토링들은 다른 것보다 복잡하다. 매우 간단한 리팩토링을 제외하고는, 리팩토링을 한 번에 하나만 수행하고, 다음 리팩토링을 하기 전에 재 컴파일하고 다시 테스트 한다.

여러분이 취할 단계에 대한 목록을 만든다.
 
- 여러분이 A 위치에서 B 위치로 가기 위한 리팩토링 목록을 작성하는 것은 의사코드 프로그래밍 프로세스를 확장한 개념이다. 목록을 작성하면 상황에 맞게 변경하는데 도움을 준다.

주차장을 만든다.
 - 여러분이 리팩토링을 수행하고 있을 때, 때로는 다른 리팩토일을 해야 할 필요가 있을 것이다. 또 새로운 리팩토링을 수행하고 있을 때, 또 다른 리팩토링이 도움이 된다는 것을 발견하게 될 것이다. 지금 당장 필요하지 않은 변경을 위해서 "주차장"을 만들어 놓는다. 즉, 지금 당장은 변경해야 할 필요가 없지만 어느 시점에서 변경해야 하는 변경사항에 대한 목록을 만들어둔다.

빈번하게 체크 포인트를 설정한다.
 - 리팩토릭을 하다보면 코드가 갑자기 엉뚱한 방향으로 가기쉽다. 여러분이 시작한 코드를 저장하는 것뿐만 아니라, 리팩토링을 하면서 여러 곳에 체크 포인트를 저장하여 막다른 골목에 갔을 때, 작동하는 프로그램으로 돌아올 수 있도록 한다.

컴파일러의 경고를 활용한다.
 - 컴파일러는 슬그머니 지나가는 작은 오류들을 만들기가 쉽다. 컴파일러의 경고 수준을 가장 까다롭게 설정하면 많은 오류들을 즉시 잡는 데 도움이 될 것이다.

다시 테스트한다.
 - 변경된 코드에 대한 컴토는 반드시 재테스트를 통해서 보완되어야 한다. 물론, 이것은 처음부터 좋은 테스트 케이스를 갖고 있는지에 의존한다.

테스트 케이스를 추가한다.
 - 이전 테스트로 다시 테스트할 뿐만 아니라, 새로운 코드를 살펴보기 위한 새로운 단위 테스트를 추가한다. 리팩토링으로 인해서 더 이상 사용되지 않은 테스트 케이스들은 제거한다.

변경 사항을 컴토한다.
 - 만약 컴토가 처음부터 중요하다면, 나중에 코드를 변경할 때에는 더욱 중요하다.

리팩토링의 위험 수준에 따라서 접근 방법을 조절한다.
 - 어떤 리팩토링들은 다른 리팩토링보다 위험하다. "매직 넘버를 명명된 상수로 대체한다"와 같은 리팩토링은 상대적으로 위험 요소가 없다. 클래스나 루틴의 인터페이스를 변경하거나, 데이터베이스 스키마를 변경하거나, 불린 테스트를 변경하는 리팩토링은 다른 리팩토링들보다 위험하다. 쉬운 리팩토링의 경우에는 한 번에 하나 이상의 리팩토링을 하기 위해서 리팩토링 프로세스를 능률적으로 처리할 수 있으며, 공식적으로 검사를 거치지 안혹 간단하게 재테스트할 수 있다.

좀 더 위험한 리팩토링에 대해서는 상당히 주의해야 한다. 리팩토링을 한 번에 하나만 수행한다. 일반적인 컴파일러 검사와 단위 테스트뿐만 아니라, 리팩토링을 한 결과를 다른 사람들이 검토하도록 하거나 리팩토링을 위해서 짝 프로그래밍을 사용한다.

from COME COMPLETE 2/E

패턴이란 특정 컨텍스트 내에서 주어진 문제에 대한 해결책이다.

컨텍스트(context)란 패턴이 적용되는 상황을 뜻한다. 반복적으로 일어날 수 있는 상황이어야만 한다.
ex) 객체들의 컬렉션이 주어져 있다.

문제(problem)란 그 컨텍스트 내에서 이루고자 하는 목적을 뜻한다. 하지만 컨텍스트 내에서 생길 수 있는 제약조건도 문제에 포함된다
ex) 컬렉션의 구현을 드러내지 않으면서 그 안에 있는 각 객체들에 대해서 순환 작업을 할 수 있어야 한다

해결책(solution)이 바로 우리가 찾아내야 하는 것이다. 누구든지 적용해서 일련의 제약조건 내에서 목적을 달성할 수 있는 일반적인 디자인을 뜻한다.
ex) 반복 잡업을 별도의 클래스로 캡슐화시킨다.

 어떤 컨텍스트 내에서 일련의 제약조건에 의해 영향을 받을 수 있는 문제에 봉착 했다면, 그 제약 조건 내에서 목적을 달성하기 위한 해결책을 찾아낼 수 있는 디자인을 적용하면 된다.

패턴이 아닌 디자인에 정신을 집중해야 한다. 반드시 필요한 경우에만 패턴을 사용해야 하고 더 간단한 해결책이 있다면 그 방법을 쓰는 것이 옳은 것이다.

알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만든다.
스트래티지을 활용하면 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.

디자인 원칙
1. 애플리케이션에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로 부터 분리 시킨다.
  - 달라지는 부분을 찾아서 나머지 코드에 영향을 주지 않도록 '캡슐화' 한다. 그러면 코드를 변경하는 과정에서 의도하지 않는 일이 일어나는 것을 줄이면서 시스템의 유연성을 향상시킬 수 있다.
2. 구현이 아닌 인터페이스에맞춰서 프로그래밍 한다.
3. 상속보다는 구성을 활용한다.

1. Serializable 인터페이스는 신중하게 implements 하라

2. 맞춤 직혈화 형태를 사용하라

3. readObject 메소드는 모든 공격을 방어할 수 있도록 작성하라..

4. 필요하다면 readResolve 메소드를 제공하라

1. 변경가능한 공유 데이터에 접근할 때 동기화하라

2. 지나친 동기화는 피하라

3. wait 메소드는 반복문 안에서만 호출하라

4. 스레드 스케줄러에 의존하지 마라

5. 스레드 안정성을 문서화 하라

6. 스레드 그룹을 쓰지 마라

1. 예외는 예외상황에서만 써야 한다.

2. 처리해야 하는 예외와 런타임 예외를 구분해서 던져라

3. 처리해야 하는 예외는 꼭 필요할 때만 던져라

4. 표준 예외를 써라

5. 예외를 적절하게 추상화하라

6. 메소드가 던지는 모든 예외를 명세문서에 기술하라

7. 실패에 대한 자세한 정보를 상세 메시지 문자열에 담아라

8. 실패의 원자성을 얻기 위해 노력하라

9. 예외를 잡아서 버리지 마라

1. 지역 변수의 유효범위를 최소화 하라

2. 라이브러리를 배우고 익혀서 써라

3. 정확한 게산에 float이나 double 타입을 쓰지 마라

4. 적절한 타입 대신 문자열을 쓰지 마라

5. 성능을 떨어뜨리는 문자열 연결을 조심하라

6. 인터페이스타입으로 객체를 참조하라

7. 리플렉션 보다는 인터페이스를 써라

8. 네이티브 메소드는 신중하게 써라

9. 신중하게 최적화 하라

10. 일반 작명규칙을 지켜라