프로그래밍/DesignPattern

디자인 원칙

모지사바하 2007. 7. 2. 20:18
* 1. 애플리케이션에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로부터 분리 시킨다.

"바뀌는 부분은 따로 뽑아서 캡슐화시킨다. 그렇게 하면 나중에 바뀌지 않는 부분에는 영향을 미치지 않은 채로 그 부분만 고치거나 확장할 수 있다"

- 모든 패턴은
'시스템의 일부분을 다른 부분과 독립적으로 변화시킬 수 있는 방법'
을 제공하기 위함

2. 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.

3. 상속보다는 구성을 활용한다.

4. 서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.

- 느슨하게 결합하는 디자인을 사용하면 변경 사항이 생겨도 무난히 처리할 수 있는 유연한 객체지향 시스템을 구축할 수 있다. 객체 사이의 상호의존성을 최소화할 수 있기 때문이다.

* 5.OCP(Open-Closed Principle) - 클래스는 확장에 대해서는 열려 있어야하지만 코드 변경에 대해서는 닫혀있어야 한다.

- 기존 코드는 건드리지 않은 채로 확장을 통해서 새로운 행동을 간단하게 추가할 수 있도록.
- 새로운 기능을 추가하는 데 있어서 매우 유연해서 급변하는 주변 환경에 잘 적응할 수 있으면서도 강하고 튼튼한 디자인을 만들수 있다.

6. 의존성 뒤집기 원칙(Dependency Inversion Principle) - 추상화된 것에 의존하도록 만들어라. 구상 클래스에 의존하도록 만들지 않도록 한다.

- 이 원칙은 2번 항목과 똑같다고 느낄수 있다. 물론 비슷하긴 하지만 의존성 뒤집기 원칙에서는 추상화를 더 많이 강조한다. 이 원칙에는 고수준 구성요소가 저수준 구성요소에 의존하면 안 된다는 것이 내포되어 있다. <- "고수준" 구성요소는 다른 "저수준" 구성 요소에 의해 정의되는 행동이 들어있는 구성요소를 뜻한다.

의존성 뒤집기 원칙에 의하면, 구상 클래스처럼 구체적인 것이 아닌 추상 클래스나 인터페이스와 같이 추상적인 것에 의존하는 코드를 만들어야 한다. 이 원칙은 고수준 모듈과 저수준 모듈에 모두 적용될 수 있다.

7. 최소 지식 원칙 - 정말 친한 친구하고만 얘기하라.

- 이게 무슨 뜻인고 하니 , 시스템을 디자인할 때, 어떤 객체든 그 객체와 상호작용을 하는 클래스의 개수에 주의해야 하며, 그런 객체들과 어떤 식으로 상호작용을 하는지에도 주의를 기울여야 한다 는 뜻이다.

- 이 원칙을 잘 따르면 여러 클래스들이 복잡하게 얽혀서 시스템의 한 부분을 변경했을 때 다른 부분까지 줄줄이 고쳐야 되는 상황을 미리 방지할 수 있다. 여러 클래스들이 서로 복잡하게 의존하고 있다면 관리하기도 힘들고, 남들이 보기에도 이해하기 어려운, 불안정한 시스템이 되고만다.

- 어떻게 하면 여러객체하고 인연을 맺는 것을 피할 수 있을까..
- 최소지식 원칙에서는  여러객체하고 인연을 맺는 것을 피할 수 있는 몇가지 가이드라인을 제공한다. 어떤 메소드에서든지 다음 네 종류의 객체의 메소드만을 호출하면 된다.

① 객체 자체
② 메소드에 매개변수로 전달된 객체
③ 그 메소드에서 생성하거나 인스턴스를 만든 객체
④ 그 객체에 속하는 구성요소

- 이가이드 라인에 따르면 다른 메소드를 호출해서 리턴 받은 객체의 메소드를 호출하는 것도 바람직하지 않다.
- ④ 의 "구성요소"는 인스턴스 변수에 의해 참조되는 객체를 의미한다. 즉 "A에는 B가 있다"라는 관계에 있는 객체를 생각하면 된다.

- 다른 메소드를 호출해서 리턴 받은 객체의 메소드를 호출하는 것이 바람직 하지 않은 이유는 무엇인가?(어떤 단점이 있는가?) 그렇게 하면 다른 객체의 일부분에 대해서 요청을 하게 되는 것이고, 그러다 보면 직접적으로 알고 지내는 객체의 개수가 늘어나게 된다. 그런 경우에 최소 지식 원칙을 따르려면 그 객체 쪽에서 대신 요청을 하도록 만들어야 한다. 그러면 그 객체의 한 구성요소를 알고 지낼 필요도 없어진다.(친구의 수를 줄이는 데도 도움이 된다)

ex source)
① 원칙을 따르지 않은 경우
public float getTemp(){
  Termometer thermometer = station.getThermometer();
  return thermometer.getTemperature();
} // station으로부터 thermometer라는 객체를 받은 다음, 그 객체의 getTemperature() 메소드를 직접 호출한다.

② 원칙을 따르는 경우
public float getTemp(){
  return station.getTemperature();
} // 최소 지식 원칙을 적용하여 Station클래스에 thermometer에 요청을 해 주는 메소드를 추가 했다. 이렇게 하면 의존해야 하는 클래스의 개수를 줄일 수 있다.


자바에서 일상적으로 사용하는 것 중에 최소 지식 원칙에 위배되는 것 -
System.out.println();

8. 헐리우드 원칙 - 먼저 연락하지 마세요. 저희가 연락 드리겠습니다.

헐리우드 원칙을 활용하면 "의존성 부패(dependency rot)"를 방지 할 수 있다. 어떤 고수준 구성요소가 저수준 구성요소에 의존하고, 그 저수준 구성요소는 다시 고수준 구성요소에 의존하고, 그 고수준 구성요소는 다시 또 다른 구성요소에 의존하고, 그 다른 구성요소는 또 저수준 구성요소에 의존하는 것과 같은 식으로 의존성이 복잡하게 꼬여있는 것을 의존성 부패라고 부른다. 이렇게 의존성이 부패되면 시스템이 어떤 식으로 디자인된 것인지 거의 아무도 앙ㄹ아볼 수 없게 된다.

헐리우드 원칙을 사용하면, 저수준 구성요소에서 시스템에 접속을 할 수는 있지만, 언제 어떤 식으로 그 구성요소들을 사용할지는 고수준 구성요소에서 결정하게 된다. 즉, 고수준 구성요소에서 저수준 구성요소에게 " 먼저 연락하지 마세요. 제가 먼저 연락 드리겠습니다" 라고 얘기를 하는것과 같다.

헐리우드 원칙과 의존성뒤집기 원칙의 차이 :
 
의존성 뒤집기 원칙은 될 수 있으면 구상 클래스 사용을 줄이고 대신 추상화된 것을 사용해야 한다는 원칙이다.

헐리우드 원칙은 저수준 구성요소가 컴퓨테이션에 참여할 수는 있으면서도 저수준 구성요소과 고수준 계층 사이에 의존성을 만들어내지 않도록 프레임워크 또는 구성요소를 구축하기 위한 기법이다.

따라서 이 두 원칙은 객체를 분리시킨다는 하나의 목표를 공유하고 있긴하지만, 디자인 상의 의존성을 피하는 방법에 있어서 의존성 뒤집기 원칙이 훨씬 더 강하고 일반적인 내용을 담고 있다고 할 수 있다.
헐리우드 원칙은 저수준 구성요소들을 다양하게 사용할 수 있으면서도, 다른 클래스가 그러한 구성요소에 너무 의존하지 않게 만들어주는 디자인을 구현하기 위한 기법을 제공한다.

9. 단일 역할 원칙 - 클래스를 바꾸는 이유는 한 가지 뿐이어야 한다.

클래스를 고치는것은 최대한 피해야 한다. 코드를 변경하다보면 온갖 문제가 생겨날 수 있기때문이다. 코드를 변경할 만한 이유가 두 가지가 되면 그만큼 그 클래스를 나중에 고쳐야 할 가능성이 커지게 될 뿐 아니라, 디자인에 있어서 두 가지 부분에 동시에 영향이 미치게 된다.

이 원칙에 따르면 한 역할은 한 클래스에서만 맡게 해야 한다.