설계패턴(Design Pattern)

2. Design Principles (SOLID)

긍.응.성 2019. 10. 28. 01:51
반응형

1. Hierarcy of Pattern Knowledge

 

Design Principle은 설계단계가 아니다. 지켜야할 원리들을 기술한 것이며 이를 지키는것이 자연스럽게 패턴을 가진 소스를 작성하게 해주므로 OO Principles을 따라 소스를 작성하는 습관을 기르는 것이 좋다.

 

 

2. OO Principles

 

  • Program to interface not implementations - 직접 구현하는것 보다 interface를 이용하라
  • Favor object composition over class inheritance - 클래스 상속보다는 멤버 변수로 클래스를 가져라 (Composition & Delegation)
  • Encapsulate what varies - 변하는 것들을 묶어내라
  • Strive for loosely couple designs between objects that interact - 소통하는 객체사이 관계의 정도를 줄여라
  • SOLID principle

 

3. SOLID Principle

 

1) SRP (Single Responsibility Principle)

 

하나의 클래스는 한개의 Responsibility를 가지게 하는 설계원칙이다. 이때 Responsibility는 변경의 요인을 뜻하며 여러개의 Responsibility를 가진다는 것은 종류가 상이한 여러 기능을 한 클래스에서 제공한다는 것이다. 이때 해당 클래스가 수정된다면 이를 참조하는 두개 이상의 클래스들은 모두 재컴파일되어야 한다. 이를 해결하기 위해 SRP원칙을 적용하여 하나의 Responsibility를 가지게 하여 클래스의 변화에도 그를 참조하는 하나의 클래스만 재컴파일 되게 할 수있다. (Minimize Change Propagation)

 

하지만 무분별한 SRP의 적용은 너무 많은 클래스를 만들고 이는 가독성, 속도를 늦춘다. 여러 기능을 가지더라도 반드시 함께 수행되어야만 하는 기능이라면 굳이 나누지 않아도 된다.

 

 

2) OCP (Open Closed Principle)

 

Open for extension, Closed for modification (기능 확장에는 열려있고 수정에는 닫혀있다)

예를 들어 케이스에 대해서 다른 객체를 메서드를 호출해야할때, 조건문으로 도배되어 있는 코드를 볼 수 있다. 이때 새로운 케이스가 추가된다면 이 부분이 변경점이 되며 조건문을 추가, 클라이언트 코드도 맞춰서 수정해야하는 문제가 존재한다. 이러한 디자인은 Design Smells 중 Rigid, Fragile, Immobile의 문제를 갖고 있으며, 이때 Abstraction을 이용하여 문제를 해결해줄 수 있다. 케이스 마다 다른 객체를 호출하는것이 아닌 상위클래스만 호출, Polymorphism을 이용하여 각 하위클래스에서 필요한 기능을 알아서 수행하도록 구현할 수 있다. 이를 통해 불필요한 수정을 줄이고 상위클래스를 상속하는 하위클래스를 생성하는 것으로 기능을 추가 할수 있다.

 

이 또한 과하면 좋지않다. 상속을 통한 Polymorphism을 이용하기 때문에 수행속도가 느려질 수 밖에 없다. 이는 전체적인 프로그램의 비용을 증가시킨다.

 

 

3) LSP (Liskov Substitution Principle)

 

Subtypes must be substitutable for their base types.

Subclass는 Superclass의 pre-condition을 유지 혹은 약화 시킬 수 있으며, post-condition을 유지 혹은 강화 시킬 수 있다.

 

subclass가 언제나 superclass를 대신할 수 있어야 하며 이러한 원칙을 엄격히 지키지 못하는 상황에서의 상속의 사용은 기대와 다른 결과물을 내놓을 수 있다. 주로 behavior에 대하여 IS_A 관계를 만족할 때 상속을 사용하는것이 좋다.

 

 

4) ISP (Interface Segregation Principle)

 

여러 기능이 묶여진 Interface가 있다면 사용 의도에 맞게 작은 Interface로 나누어 제공해야 한다.

 

느낌이 Interface에 사용하는 SRP와 같은 느낌이다. 대신 SRP는 클래스 단위로 단 하나의 기능을 갖도록 만들어 주는것이라면 ISP는 이미 구성된 큰 인터페이스에 대하여 여러 사용 의도에 따라 입맞에 맞게 가져가서 쓸 수 있도록 나누어 주는것이 차이다. 이를 이용하여 하나의 인터페이스에 대하여 여러 관계를 가지던 클래스들이 기능에 따라 나뉘어진 인터페이스를 각자 사용할 수 있게하여 Change Propagation을 줄일 수 있다.

 

 

5) DIP (Dependency Inversion Principle)

 

High-level module은 Low-level module에 의존해서는 안된다.

 

기존 프로그램은 클래스를 가지고 호출하며 이어서 그 클래스는 변수로 또 다른 클래스들을 가지며 호출한다. 이런 구조일 경우 하위 클래스의 변화는 최상위 클래스까지 재컴파일 되어야하는 문제를 가진다.

이때 Class 가지는것이 아닌 Interface를 갖도록 수정. 이 변화는 하위클래스의 변화가 상위 모듈로 영향을 끼치지 않도록 해준다.

 

 

이러한 설계원리는 Dependency를 잘 관리할 수 있도록 도와주며, 유지보수, 유연성, 재사용성을 향상시켜준다.

반응형