객체 지향의 특성을 올바르게 사용하기 위한 원칙들이다.
객체 지향 4대 특성을 발판으로 하고 디자인 패턴의 뼈대이며 스프링 프레임워크의 근간이기도 하다.
어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다. -로버트 C.마틴-
소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야 한다.” - 로버트 C.마틴 -
자신의 확장에는 열려 있고, 주변의 변화에 대해서는 닫혀 있어야 한다.
A 객체에서 B 객체를 참조하고 있고 B 객체에게 어떤 기능을 요청하는 부분이 있을때, B 클래스의 코드가 변경 되어도 A 클래스에서 영향을 받으면 안 된다.
가장 좋은 예가 JDBC 다.
https://docstore.mik.ua/orelly/java-ent/servlet/ch09_02.htm
DB 의 확장에는 열여 있고 어플리케이션 쪽에서는 DB 확장에 영향받지 않는다.
서브 타입은 언제나 자신의 기반 타입으로 교체할 수 있어야 한다. - 로버트 C.마틴 -
LSP 규칙
자료형 S 가 자료형 T 의 하위형이라면, 프로그램에서 자료형 T의 객체는 프로그램의 속성을 변경하지 않고 자료형 S 의 객체로 교체할 수 있어야 한다.
시그니처에 관한 몇 가지 표준적인 요구사항
Shape[] circleArray = new Circle[]{};
// Using Comparator<? super T> for contravariance
Comparator<Shape> shapeComparator = new Comparator<Shape>() {
@Override
public int compare(Shape shape1, Shape shape2) {
return shape1.name.compareTo(shape2.name);
}
};
하위형이 만족해야 하는 행동 조건
Preconditions cannot be strengthened in the subtype.
서브 타입에서 선행조건은 강화될 수 없다.
서브 타입에서 오버라이딩한 메서드에서는 상위 타입보다 조건이 강화되어 부모 타입으로 대체할 수 없는 경우를 말한다.
class Animal {
public void eat() {
System.out.println("Animal is eating.");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("Dog is eating.");
}
}
class Dog extends Animal {
@Override
public void eat() {
if (hasFood()) {
System.out.println("Dog is eating.");
} else {
System.out.println("Dog has no food.");
}
}
private boolean hasFood() {
// Check if dog has food
// ...
}
}
Postconditions cannot be weakened in the subtype.
서브 타입에서 후행조건은 약화될 수 없다.
Invariants must be preserved in the subtype.
서브 타입에서 상위형의 불변조건은 반드시 유지되어야 한다.
class Shape {
protected double area;
public double getArea() {
return area;
}
}
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
**this.area = calculateArea();**
}
**private** double calculateArea() {
return width * height;
}
}
class Square extends Rectangle {
public Square(double side) {
super(side, side);
}
}
클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다. - 로버트 C.마틴 -
~ 할 수 있는 (is able to)
기준으로 만들어라“추상화된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다.”
”자주 변경되는 구체 클래스에 의존하지 마라” - 로버트 C.마틴 -
OCP 사례에 소개된 JDBC 인터페이스도 DIP 역시 잘 지킨 사례다.
어플리케이션이 구체화된 DB Driver 에 바로 의존했다면 DB 변경에 영향을 크게 받을 것이다.
추상화된 JDBC 인터페이스에 의존함으로써 어플리케이션은 구체화된 DB Driver 변경에 영향을 받지 않는다.
저도 개발자인데 같이 교류 많이 해봐요 ㅎㅎ! 서로 화이팅합시다!