한 클래스는 하나의 책임만 가져야 한다.
소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다.
객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다. 즉, 부모와 자식클래스의 객체를 교환해도 앱의 동작에는 변함이 없어야 한다.
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
→ 사용하지 않는 명세가 있는 인터페이스라면 분리한다.
프로그래머는 추상화에 의존해야지 구체화에 의존하면 안된다.
→ 구체 클래스가 아닌 인터페이스에 의존해야 한다.
여기서 가장 헷갈릴 수 있는 요소는 아무래도 SRP인데 SRP의 하나의 책임 이란, 클래스가 정말로 한 가지만 한다기 보다는 변경을 요구하는 액터에 대한 책임이다.
예를 들어 회사의 급여 지급 시스템에서 Salary라는 클래스가 있는데 인사팀과, 재정 지원팀에서 각기 요구하는 Salary에 대한 기능과 정의가 다르다면 각 변경의 요구사항 주체에 맞게 다른 클래스 즉, SalaryHr 과 SalarySp로 분리하는 것이다.
스프링은 이 SOLID 소프트웨어 설계 원칙을 지킬 수 있도록 도와주는 프레임워크이며 이중에서 특히 OCP와 DIP에 초점이 맞춰져 있다.
소프트웨어에서의 의존서이란 쉽게 말하면 A 가 B에 의존하는 것이다. 따라서 B가 없으면 A가 존재할 수 없는 상태를 의미한다.
아래의 코드는 Dog 라는 클래스가 있으며 이 클래스는 Person 클래스가 필요하다. 이때 생성시 Person객체가 주어지지 않ㅇ면 Dog 클래스의 인스턴스는 존재할 수 없다. 이를 의존성이라고 한다.
class Dog {
int leg = 4;
Person master;
public Dog(Person person) {
this.master = person;
}
public void run() {
person.runWith(this);
}
public void bark() {
person.makeBark(this);
}
}
의존성을 주입하는 방법에는 아래의 세 가지 방법이 있다.
class Dog {
int leg = 4;
Person master;
public Dog(Person person) {
this.master = person;
}
//...
}
class Dog {
int leg = 4;
Person master;
public void setMaster(Person person) {
this.master = person;
}
}
class Dog {
int leg = 4;
Person master = new Person("zenon", "developer");
//...
}