SOLID 원칙

SRP (Single Responsibility Principle), 단일 책임 원칙 

 - SRP에서 책임의 기본 단위는 객체를 지칭

 - 책임이란 해야 하는것, 할 수 있는 것으로 간주할 수 있다 

 - 즉 객체는 단 하나의 책임만을 가져야 한다는 것이다 

 - 객체에 책임을 할당할 때는 어떤 객체보다도 작업을 잘 할 수 있는 객체에 책임을 할당해야 한다

 - 또한 객체는 책임에 수반되는 모든 일을 자신만이 수행할 수 있어야 한다

 - 좋은 설계란 시스템에 새로운 요구사항이나 변경이 있을 때 가능한 한 영향 받는 부분을 줄이는 것이다.

   한 객체가 많은 책임을 지고 있다면 클래스 내부에서 다른 역할을 수행하는 코드들간의 결합도가 높아지게 된다.

   이는 클래스에 변경이 있을때마다 영향을 받는 부분이 많다는것이며 또한 변경 후 기존의 기능에 영향을 주는지를

   평가하는 회귀 테스트 비용도 늘어난다는 것을 의미하기 때문에 좋은 설계라고 할 수 없다. 

 - 위와 같은 문제를 해결하기 위해서는 한 클래스에 너무 많은 책임을 부여하지 말고 단 하나의 책임만을 수행하도록 해

   변경 사유가 될 수 있는것을 하나로 만들어주어야 하며 이를 책임 분리라고 한다. 

한 클래스에 너무 많은 책임이 부여되어 있다. Student 클래스에서 굳이 수행할 필요가 없는 print 메서드들을 분리하여 설계해 주어야 한다.

Student 클래스에 대해 책임 분리를 해주어 개선한 디자인이다.

 

 

OCP (Open-Closed-Principle), 개방-폐쇄 원칙 

 - 개방-폐쇄 원칙이란 기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 설계해야 한다는 것이다

 - 가장 중요한 점은 무엇이 변하는 것인지, 무엇이 변하지 않는 것인지를 구분하는 것이다 이를 통해 변해야 하는 것은 쉽게 변하

   게, 변하지 않는 것은 변하는 것에 영향을 받지 않게 해야한다. 

 - 변화의 단위 = 클래스 

 

 - OCP를 만족하는 어떤 학생이 오더라도 프린트할 수 있게 해주도록 설계한 디자인  - 변해야 하는 Student 클래스는 쉽게 변하도록 하였고, 변하지 않아야할 print 클래스들은 Student 클래스에 영향을 받지 않도   록 개별적인 클래스를 처리하지 않고, 인터페이스에서 구체적인 print 클래스를 캡슐화해 처리하도록 하였다. - 위와 비슷하게 상속을 통한 다형성으로도 OCP를 만족하는 설계가 가능하다. 

 

 

LSP (Liskov Substitution Principle), 리스코프 치환 원칙 

 - 일반화 관계를 적절히 사용했는지를 점검하는 원칙

 - 부모 클래스와 자식 클래스 사이의 행위가 일관성이 있어야 한다.

 - 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 대신하여도 의미는 변화되지 않도록 설계하는 것이다.

 - 행위 일관성 = pre -> pre' (선조건 pre가 만족된다면 pre'가 만족되어야 한다) 

                         post' -> post (후조건 post'가 만족된다면 post가 만족되어야 한다)

 - 행위 일관성을 지키기 위해서는 부모 클래스의 행위를 더 명확하게 정의할 수 있어야 한다.

 

 - 왼쪽의 Bag 클래스는 가격을 설정하고 반환해주는 기능을 한다. 

 - 오른쪽의 DiscountedBag 클래스는 할인율을 설정해 할인된 가격을 계산해주는 기능을 한다. 

 - DiscountedBag 클래스는 Bag 클래스의 가격을 설정하고 반환해주는 기능을 변경없이 상속받았다. 

 - 자식 클래스에서 부모 클래스의 기능을 재정의하지 않았으므로 부모 클래스와 자식 클래스의 행위는 일관성이 있다. 

 - 따라서 위의 클래스들의 상속관계는 LSP를 위반하지 않는다.

 

ISP (Interface Segregation Principle), 인터페이스 분리 원칙

 - 인터페이스를 클라이언트에 특화되도록 분리시키라는 원칙 

 - 클라이언트 관점에서 클라이언트 자신이 이용하지 않는 기능에는 영향을 받지 않아야 한다.

 - 비대한 인터페이스 -> 작고 특화된 인터페이스 

 - 여러가지 메서드(기능)을 포함하는 비대한 클래스는 클라이언트와 무관하게 발생한 변화임에도 클라이언트에게 영향

   을 끼칠 우려가 있다. 

 - 비대한 클래스에 ISP 원칙을 적용하여 인터페이스를 클라이언트에 특화되도록 적용하였다. 

 - 위와 같이 설계하면 인터페이스가 일종의 방화벽 역할을 수행해 클라이언트는 자신이 사용하지 않는 메서드(기능)에

   생긴 변화로 인한 영향을 받지 않게 된다. 

 

 

DIP (Dependency Inversion Principle), 의존 역전 원칙

 - 의존 관계를 맺을 때 변화하기 쉬운 것보다는 변화하기 어려운 것에 의존하라는 원칙

 - 구체적인 것 -> 변화하기 쉬운 것,  추상적인 것 -> 변화하기 어려운 것 

 - DIP를 만족하기 위해서는 구체적인 클래스보다는 인터페이스나 추상 클래스와 의존 관계를 맺도록 설계해야 한다

 - 인터페이스 -> 변하지 않는 것,  구체 클래스 -> 변하기 쉬운 것

 - DIP를 만족하면 의존성 주입을 통해 변화를 쉽게 수용하는 코드를 작성할 수 있다

 - 상위 모듈은 하위 모듈에 의존하면 안된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다. 

 - 추상화된 것은 구체적인 것에 의존하면 안된다. 구체적인 것이 추상화된 것에 의존해야 한다.

 - DIP의 위반은 OCP의 위반을 초래한다.

 

 - 변하기 쉬운 구체 클래스들을 추상 클래스와 의존관계를 맺도록 설계한다.

 

 

 

'설계 패턴' 카테고리의 다른 글

템플릿 메서드 패턴  (0) 2020.11.12
Decorator 패턴  (0) 2020.11.09
Strategy 패턴  (0) 2020.10.06
빌더 패턴 (Builder Pattern)  (0) 2020.10.06
클래스 다이어그램  (0) 2020.09.17
TAGS.

Comments