SOLID 원칙은 객체 지향 프로그래밍 및 소프트웨어 설계에서의 다섯 가지 기본 원칙을 나타낸다. 이 원칙들은 소프트웨어를 더 이해하기 쉽고, 유연하며, 유지 보수가 용이하게 설계하는데 도움을 준다.
프로그래밍을 할 때 좋은 코드를 짜기 위한 기본적인 규칙!
SOLID는 다음과 같은 원칙들의 첫 글자를 따서 만든 약어이다.
하나의 클래스는 하나의 일만 해야한다!
먄약 '책' 클래스가 있다면 책에 관련된 일만 해야한다. 인쇄나 판매 같은 다른 일은 할 수 없다.
// 좋은 예: 클래스가 하나의 책임만 가짐
public class UserSettings {
public void changeEmail(User user) {
// 이메일 변경 로직
}
}
// 나쁜 예: 클래스가 여러 책임을 가짐
public class User {
public void changeEmail(User user) {
// 이메일 변경 로직
}
public void saveUser(User user) {
// 유저 저장 로직
}
}
코드를 새로운 기능으로 확장할 수 있어야 하지만 기존 코드를 바꾸지는 않아야 한다!
'도형' 클래스가 있고 '원'이나 '사각형'을 추가하고 싶을 때, '도형' 클래스를 바꾸지 않고도 새로운 도형을 추가할 수 있어야 한다.
public abstract class Shape {
public abstract double area();
}
public class Circle extends Shape {
private double radius;
public double area() {
return Math.PI * radius * radius;
}
}
public class AreaCalculator {
public double calculateArea(Shape[] shapes) {
double area = 0;
for (Shape shape : shapes) {
area += shape.area();
}
return area;
}
}
부모 클래스 대신 자식 클래스를 사용해도 문제가 없어야 한다!
'새'클래스가 있고 '참새'클래스가 '새'의 자식 클래스라면, '새'를 사용한느 모든 곳에서 '참새'를 사용해도 잘 작동해야 한다.
public class Rectangle {
protected int width, height;
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public int getArea() {
return width * height;
}
}
public class Square extends Rectangle {
public void setWidth(int width) {
this.width = this.height = width;
}
public void setHeight(int height) {
this.width = this.height = height;
}
}
너무 많은 기능을 하나의 인터페이스에 넣지 말아야 한다!
프린터와 스캐너 기능을 모두 가진 '복합기' 인터페이스 대신, '프린터' 인터페이스와 '스캐너' 인터페이스를 따로 만들어야 한다.
// 좋은 예: 특정 클라이언트에 맞춘 인터페이스
public interface Printer {
void print();
}
public interface Scanner {
void scan();
}
// 나쁜 예: 여러 기능을 하나의 인터페이스에
public interface Machine {
void print();
void fax();
void scan();
}
고수준의 모듈은 저수준의 모듈에 직접 의존하지 않아야 한다!
대신에 둘 다 추상화(인터페이스나 추상 클래스)에 의존해야한다. 예를 들어, '데이터베이스' 클래스 대신 '데이터 저장 인터페이스'를 사용해야 한다.
// 좋은 예: 추상화에 의존
public interface Database {
void save(Object data);
}
public class MySQLDatabase implements Database {
public void save(Object data) {
// MySQL 저장 로직
}
}
public class UserService {
private Database database;
public UserService(Database database) {
this.database = database;
}
public void saveUser(User user) {
database.save(user);
}
}