https://sundaland.tistory.com/59
OCP는 소프트웨어 개발에서 객체지향 설계 원칙 중 하나로, 개방-폐쇄 원칙이라고 불리며, 소프트웨어 개발에서 확장성을 고려하여 설계를 할 때 적용되는 원칙이다.
OCP는 S/W 개발에서 변경에 대한 비용과 위험을 최소화기 위해, 기본의 코드를 수정하지 않고도 기등을 추가하거나 변경할 수 있도록 하는 것을 목표로한다.
- 개발 (O) : 모듈은 확장에 대해 열려있어야 한다. 즉 새로운 요구사항이나 기능이 추가되어도 기존 코드의 수정 없이도 새로운 코드를 추가할 수 있어야 한다. UserDao는 DB 커넥션 기능을 확장하는데 오픈되어 있어, UserDao에 전혀 영향을 주지 않고도 얼마든지 기능을 확장할 수 있다.
- 폐쇄 (C) : 모듈은 수정에 대해 닫혀있어야 한다. 즉 기존 코드를 수정하지 않고도 모듈의 기능을 확장하거나 변경할 수 있어야 한다. UserDao 자신의 핵심 기능을 구현한 코드는 변경(DB 커넥션 기능 확장)에 영향 받지 않고 유지할 수 있으므로 변경에는 닫혀 있다고 할 수 있다.
UserDao의 ConnectionMaker 인터페이스를 통해 제공되는 확장 포인트는 확장을 위해 Open으로 되어 있지만, 이러한 확장을 위해 UserDao 자신의 변화가 불필요하게 일어나지 않도록 Close되어 있다.
이러한 OCP를 지키기 위해 다양한 디자인 패턴이 존재하며 상속, 추상화, 인터페이스 등의 개념을 활용하여 객체 간의 결합도를 낮추고, 유연하고 확장 가능한 설계를 만들어낸다.
OCP는 S/W 개발에서 중요한 원칙 중 하나이며, 유지보수와 확장성을 고려한 잘 설계된 S/W를 만드는데 큰 역할을 한다.
- 추상화 : 추상하를 사용하여 코드의 일부를 인터페이스나 추상 클래스로 분리하고, 이를 기존 코드와 분리한다. 이렇게 분리된 코드는 변경에 대해 폐쇄적이며, 기능을 추가할 때는 새로운 클래스를 만들어서 이를 구현하면 된다.
- 다형성 : 다형성을 사용하여, 인터페이스나 추상 클래스에 대한 구현 클래스를 다양하게 만들 수 있다. 이렇게 구현된 클래스는 기존 코드에 영향을 주지 않으면서 기능을 확장할 수 있다.
- 상속 : 상속을 사용하여, 부모 클래스를 확장하여 새로운 클래스를 만들 수 있다. 이렇게 만들어진 새로운 클래스는 기존 코드와 독립적으로 동작하므로, 가능을 확장할 때 영향을 주지 않는다.
▼ OCP가 적용되지 않은 코드
class Rectangle {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double getArea() {
return width * height;
}
}
class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getArea() {
return Math.PI * radius * radius;
}
}
class AreaCalculator {
public double calculateTotalArea(Object[] shapes) {
double totalArea = 0;
for (Object shape : shapes) {
if (shape instanceof Rectangle) {
Rectangle rectangle = (Rectangle) shape;
totalArea += rectangle.getArea();
} else if (shape instanceof Circle) {
Circle circle = (Circle) shape;
totalArea += circle.getArea();
}
// 다른 도형이 추가될 때마다 이곳에 새로운 조건을 추가해야 합니다.
}
return totalArea;
}
}
▼ OCP가 적용된 코드
// Abstract class for Shapes
abstract class Shape {
public abstract double area();
}
// Concrete class for Circle
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double area() {
return Math.PI * radius * radius;
}
}
// Concrete class for Rectangle
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double area() {
return width * height;
}
}
// Client class to calculate areas of shapes
class AreaCalculator {
public double calculateArea(Shape shape) {
return shape.area();
}
}
위 코드에서 Shape 클래스는 추상 클래스로, area() 메서드는 추상 메서드이다. Circle과 Rectangle 클래스는 이 Shape 클래스를 상속받으며, 각 도형의 넓이릴 계산하는 area() 메서드를 구현한다.
AreaCalculator 클래스는 도형의 넓이를 계산하는 클래스이다. 이 클래스는 Shape 클래스의 인스턴스를 인수로 받아 해당 도형의 넓이를 계산한다.
아래의 방법을 사용하여 위 코드에서 OCP를 지킬 수 있다.
- Shape 클래스는 추상 클래스로, 도형의 공통점을 정의한다.
- Circle과 Rectangle 클래스는 이 추상 클래스를 상속받아 각 도형의 특성을 구현한다.
- AreaCalculator 클래스는 Shape 클래스의 인스턴스를 인수로 받기 때문에, Circle과 Rectangle 클래스의 인스턴스를 모두 처리할 수 있다. 이렇게 함으로써, AreaCalculator 클래스는 Circle과 Reactangle 클래스의 변경 없이(Close) 새로운 도형 클래스를 추가(Open) 할 수 있다.
OCP의 장점
- 유지 보수 용의상 : 새로운 기능을 추가할 떄 기존 코드를 변경하지 않으므로, 코드의 버그가 발생할 가능성이 줄어든다.
- 유연한 설계 : 코드가 확장 가능하도록 설계되기 때문에 새로운 요구사항을 쉽게 반영할 수 있다.
- 테스트 용의성 : 코드 변경이 적으므로 테스트해야할 범위가 줄어들어 테스트가 더 쉬워진다.
OCP를 통해 S/W 모듈을 설계하면, 변경이 최소화되고 확장성이 높아져 더욱 견고한 시스템을 구축할 수 있다.
'Toby Spring 3.1' 카테고리의 다른 글
관심사의 분리 (Separation of Concerns) (0) | 2024.08.08 |
---|---|
아티팩트, DAO, JAVA Bean (0) | 2024.08.08 |
UML (Unified Modeling Language) (0) | 2024.08.05 |