객체지향은 4대 특성인 캐슐화, 상속, 추상화, 다형성을 가지고 있다. 이 특성들을 이용하여 객체 지향을 올바르게 설계할 수 있도록 도와주는 원칙들이 있다.
"어떤 클래스를 변경해야 하는 이유는 오직 하나 뿐이어야 한다."
-로버트 C. 마틴
하나의 클래스는 하나의 책임만 가져야 한다.
여기서 책임이란 기준이 모호하기 때문에 변경을 책임의 기준으로 삼으면 될 것이다. 소프트웨어는 변화에 대응해야 하기 때문에 유지보수가 가장 중요하다. 유지보수성을 높이기 위해서는 클래스가 가진 기능에 따른 관련된 책임만 줘야한다.
SRP를 잘 지킨다면 책임의 영역이 확실해지기 때문에 한 책임의 변경에서 다른 책임의 변경으로의 연쇄작용을 끊어낼 수 있으며 코드의 가독성 향상까지 누릴 수 있다.
따라서 SRP는 다른 원리들을 적용하는 기초가 되는 아주 중요한 원리이다.
"소프트웨어 엔티티(클래스,모듈,함수 등)는 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야 한다."
-로버트 C. 마틴
즉 자신의 확장에는 열려있고, 주변의 변화에 대해서는 닫혀 있어야 한다는 말이다. 또 변경을 위한 비용은 가능한 줄이고 확장을 위한 비용은 가능한 극대화 해야 한다는 의미로, 요구사항의 변경이나 추가사항이 발생하더라도 기존의 요소들은 수정이 일어나면 안되고, 확장은 쉽게 할 수 있어 재사용이 용이해야 한다는 뜻이다.
"서브 타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다."
-로버트 C. 마틴
의역하면 객체는 프로그램의 정확성을 깨지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다라는 뜻이다.
더 구체적으로 생각하자면 하위 클래스의 인스턴스는 상위형 객체 참조 변수에 대입해 상위 클래스의 인스턴스 역할을 하는데 문제가 없어야 한다고 볼 수 있는 것이다.
Animal a = new Dog()
Person p = new Programmer()
강아지가 동물의 역할을 한다.
개발자가 사람의 역할을 한다.
"클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안된다."
-로버트 C. 마틴
상황과 관련있는 메서드만 제공하라는 뜻인데 즉 각 기능, 역할에 맞게 인터페이스를 분리하라고 생각하면 된다. 하나의 일반적인 인터페이스보다 여러개의 구체적인 인터페이스가 낫다.
"추상화 된 것은 구체적인 것에 의존하면 안된다. 구체적인 것이 추상화 된 것에 의존해야 한다."
"자주 변경되는 구체(Concrete) 클래스에 의존하지 마라"
-로버트 C. 마틴
즉 구현클래스가 아니라 인터페이스에 의존하라는 이야기이다. 연극을 예로 들면 배역과 배우를 생각해 볼 수 있다. 연극은 특정 배우를 염두에 두고 기획되기보다 배역에 집중해서 기획되어야 한다. 만약 특정 배우에 의존해서 기획했는데 그 배우의 출연이 불발된다면 연극 진행에 차질이 빚어질 것이다. 하지만 배역에 의존한다면 어느 배우를 써도 무방하기 때문에 배우를 자유롭게 바꿔가며 연극을 진행할 수 있다. 여기서 배역은 인터페이스, 배우는 구체클래스라고 생각하면 된다.