객체지향 프로그래밍에서 설계의 품질을 높이기 위해 사용하는 5가지 원칙인 SOLID 원칙에 대해 알아보겠습니다. SOLID 원칙은 유지보수성과 확장성을 높이고, 코드의 품질을 개선하는 데 도움을 줍니다. 하나씩 자세히 살펴보겠습니다! ✨
1. 단일 책임 원칙 (Single Responsibility Principle, SRP) 🛠️
"클래스는 단 하나의 책임만 가져야 한다."
- 하나의 클래스는 하나의 기능이나 역할만 담당해야 합니다.
- 클래스가 여러 책임을 가지게 되면, 하나의 변경이 다른 기능에 영향을 미칠 수 있습니다.
- 예시:위 코드에서 calculateTotal과 printInvoice는 다른 책임을 가지므로, 별도의 클래스로 분리하는 것이 좋습니다.
public class Invoice {
public void calculateTotal() {
/* 총액 계산 */
}
public void printInvoice() {
/* 청구서 출력 */
}
}
2. 개방-폐쇄 원칙 (Open-Closed Principle, OCP) 🚪🔒
"소프트웨어 엔티티는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다."
- 기존 코드를 수정하지 않고도 기능을 추가할 수 있어야 합니다.
- 확장성을 높이기 위해 인터페이스와 상속을 적극 활용합니다.
- 예시:새로운 도형을 추가할 때 기존 코드를 변경하지 않고 새로운 클래스를 추가하면 됩니다.
public interface Shape {
double calculateArea();
}
public class Circle implements Shape {
private double radius;
public double calculateArea() {
return Math.PI * radius * radius;
}
}
public class Rectangle implements Shape {
private double width, height;
public double calculateArea() {
return width * height;
}
}
3. 리스코프 치환 원칙 (Liskov Substitution Principle, LSP) 🔄
"서브타입은 언제나 자신의 기반 타입으로 대체할 수 있어야 한다."
- 부모 클래스의 기능을 자식 클래스가 완벽히 수행해야 합니다.
- 자식 클래스가 부모 클래스의 규칙을 위반하면 안 됩니다.
- 예시:펭귄은 날 수 없는 새이므로 Bird를 상속받아 fly 메서드를 오버라이딩하지 않는 방식으로 설계를 바꿔야 합니다.
public class Bird {
public void fly() {
System.out.println("Flying");
}
}
public class Penguin extends Bird {
@Override public void fly() {
throw new UnsupportedOperationException("Penguins can't fly");
}
}
4. 인터페이스 분리 원칙 (Interface Segregation Principle, ISP) 🧩
"인터페이스는 구체적인 클라이언트를 기준으로 분리되어야 한다."
- 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 합니다.
- 하나의 커다란 인터페이스보다는 여러 개의 작은 인터페이스로 나누는 것이 좋습니다.
- 예시:위 코드는 fly 메서드가 필요 없는 Dog 클래스에 비효율적입니다. 이를 인터페이스로 분리해야 합니다.
public interface Eater {
void eat();
}
public interface Flyer {
void fly();
}
public class Dog implements Eater {
public void eat() {
System.out.println("Dog is eating");
}
}
public interface Animal {
void eat();
void fly();
}
public class Dog implements Animal {
public void eat() {
System.out.println("Dog is eating");
}
public void fly() {
throw new UnsupportedOperationException("Dogs can't fly");
}
}
5. 의존 역전 원칙 (Dependency Inversion Principle, DIP) 🔄🔌
"상위 모듈은 하위 모듈에 의존해서는 안 된다. 둘 다 추상화에 의존해야 한다."
- 구현이 아닌 추상화(인터페이스)에 의존해야 합니다.
- 의존성을 주입(DI, Dependency Injection)하여 유연성을 높입니다.
- 예시:위 코드는 Switch가 Light 구현체에 의존하므로, 인터페이스를 활용하는 방식으로 개선해야 합니다.
public interface Device {
void turnOn();
}
public class Light implements Device {
public void turnOn() {
System.out.println("Light on");
}
}
public class Switch {
private Device device;
public Switch(Device device) {
this.device = device;
}
public void toggle() {
device.turnOn();
}
}
public class Light {
public void turnOn() {
System.out.println("Light on");
}
}
public class Switch {
private Light light;
public Switch(Light light) {
this.light = light;
}
public void toggle() {
light.turnOn();
}
}
'IT 개발 라이프 > Back_End' 카테고리의 다른 글
자바 ReflectionUtils: 리플렉션을 쉽게 활용하는 방법 🛠️ (0) | 2024.12.16 |
---|---|
추상 클래스와 인터페이스 (0) | 2024.12.11 |
Java에서 equals()와 hashCode() 메서드 오버라이딩의 중요성 (1) | 2024.12.06 |
ORM(Object-Relational Mapping) 이란? 🔍 (1) | 2024.12.06 |
🍪 쿠키(Cookie)와 세션(Session) 이란? (3) | 2024.12.06 |