하나의 클래스는 하나의 책임만 가져야한다. 책임이란 기준이 모호하기 때문에 변경을 책임의 기준으로 삼으면 설계에 용이할 수 있다.
어떠한 역할에 대해 변경사항이 발생했을 때, 영향을 받는 기능만 모아둔 클래스라면 동일한 책임을 지닌 기능이 모인 집합으로써 SRP원칙이 적용된 설계로 볼 수 있다.
즉, 변경사항이 있을 때, 어플리케이션의 파급 효과가 적으면 SRP원칙을 잘 따른 것으로 판단한다.
[높은 응집도]
응집도가 높다는건 하나의 모듈, 클래스가 하나의 책임에만 집중되어 있다는 의미이다. 같은 책임, 관심사를 기반으로 하나의 객체로 설계하기 때문에 객체에 변경이 발생하더라도 다른 곳에 미치는 영향이 제한적이다.
[낮은 결합도]
책임과 관심사가 다른 객체 또는 모듈과는 낮은 결합도를 유지해야한다. 결합도란 하나의 오브젝트가 변경이 일어날 때 관계를 맺고있는 다른 오브젝트에게 변화를 요구하는 정도로 설명한다.
즉, 낮은 결합도란 하나의 변경이 발생할 때 다른 모듈과 객체로 변경에 대한 요구가 전파되지 않는 상태이다.
[확장에 열려있다]
모듈의 확장성을 보장하는 것을 의미한다. 새로운 변경사항이 발생했을 때 유연하게 코드를 추가 또는 수정할 수 있기 때문이다.
[변경에 닫혀있다]
객체를 직접적으로 수정하는 것은 제한해야 한다. 기능이 추가되거나 수정할 때, 객체를 직접적으로 수정해야 한다면 새로운 변경사항에 대해 유연하게 대응할 수 없는 어플리케이션이다.
즉, OCP는 추상화를 의미하는 것으로 해석된다. 객체를 추상화함으로써 확장엔 열려있고 변경엔 닫혀있는 유연한 구조를 만들 수 있는 것이다.
OCP를 구현하기 위해서는 DI, IOC가 필요하다.
객체는 프로그램의 정확성을 깨지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
하위 클래스는 인터페이스 규약을 지켜서 작성해야한다. 다형성을 지원하기 위한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면 LSP가 필요하다.
범용 인터페이스 하나보다는 특정 클라이언트를 위한 여러 개의 인터페이스 분리가 더 좋다.
운전자가 자동차를 운전한다.
라는 명제를 객체간 관계로 비유하면 자동차에 대한 인터페이스, 운전자에 대한 인터페이스를 각각 분리하는 것이다.
그럼 운전자는 택시기사가 될 수 있고, 우버 드라이버가 될 수 있다. 자동차는 버스가 될 수 있고, 스포츠카가 될 수 있다. 즉, 확장성이 커지는 셈이다.
프로그래머는 구체화가 아니라 추상화에 의존해야 한다고 한다. 즉, 구현 클래스가 아니라 인터페이스에 의존하라는 이야기이다.
연극을 예로 들면 배역(인터페이스)와 배우(구현체)를 예로 들 수 있다. 이 때 연극은 특정 배우를 염두에 두고 기획되기보다 배역에 집중해서 기획되어야 한다.
특정 배우에 의존했는데 만약 그 배우가 스케줄 또는 당일 컨디션 때문에 연극에 출연이 불발될 경우 해당 연극은 차질이 불가피해진다. 따라서 연극은 배우가 아닌 배역에 의존해야한다.
[변경에 닫혀있다]