
SOLID
- 로버트 마틴이 2000년대 초반에 명명한 객체 지향 프로그래밍 및 설계의 다섯 가지 기본 원칙
- 에자일 소프트웨어 개발의 전반적 전략의 일부
SRP - Single Responsibility principle
- 단일 책임 원칙
- 한 클래스는 하나의 책임만 가져야 함
- 클래스의 응집도를 높이고 결합도를 낮출 수 있음
ex) SRP가 지켜지지 않은 경우
public class Animal {
public String type;
public Animal(String type) {
this.type = type;
}
public void speak() {
if (type.equals("강아지")) {
System.out.println("왈왈");
} else if (type.equals("고양이")) {
System.out.println("야옹");
}
}
}
Animal 클래스가 개와 고양이 둘 다 책임을 지고 있기 때문에 SRP가 지켜지고 있지 않음
SRP를 지키기 위해서는 강아지와 고양이 클래스를 나누어 각각 책임을 지게 해야 함
OCP - Open Closed principle
- 개방 폐쇄 원칙
- 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 함
- 기존의 코드를 변경하지 않고 기능 추가, 수정할 수 있도록 설계 가능해야 함
ex) OCP가 지켜지지 않은 경우
public class Animal {
public String type;
public Animal(String type) {
this.type = type;
}
public void speak() {
if (type.equals("강아지")) {
System.out.println("왈왈");
} else if (type.equals("고양이")) {
System.out.println("야옹");
}
}
}
위 코드에서 강이지와 고양이뿐인데 새로운 동물 추가를 원할 때???
else if (type.equals("새로운 동물")
이렇게 기능을 추가해야 할 때 기존의 코드를 계속 고쳐야함 이 때문에 OCP가 지켜지지 않음
이 부분을 위해 인터페이스를 주로 사용
ex) OCP를 적용시키면
public interface Animal {
void speak();
}
새로운 동물이 추가될 때 마다 else if 추가를 해야했지만
이제는 새로운 동물 클래스를 만들어 Animal 인터페이스를 구현하면 된다
LSP - Liskov Substitution principle
- 리스코프 치환 원칙
- 부모와 자식 클래스 정의가 논리적으로 제대로 된 상속이어야 함
- 자식 클래스로 치환을 해도 문제없이 프로그램이 작동해야 함
- 조금더 쉽게 이야기 해보면 자식 클래스는 부모 클래스가 따르던 규칙들을 자식도 따라야 함
ISP - Interface Segregation principle
- 인터페이스 분리 원칙
- 한 클래스는 쓰지 않는 기능을 가진 인터페이스는 구현하지 않는게 좋다
- 클래스의 책임을 덜어주고 기능에 의존하지 않게 함 -> 확장성에 용이
ex) ISP가 지켜지지 않은 경우
public interface Robot {
void dance();
void attack();
void defend();
}
public class Wuga_V01 implements Robot{
@Override
public void dance() {}
@Override
public void attack() {}
@Override
public void defend() {}
}
Wuga 로보트를 V02로 업그레이드!
dance를 빼고 싶은데?? 이미 Robot 인터페이스 의존되어 있어서 뺄 수가 없다
이때 분리를 하자
- 먼저 공통기능을 가진 인터페이스
- V01만 가지고 있는 기능이 있는 인터페이스
public interface WugaV01Skill {
void dance();
}
public class Wuga_V01 implements Robot, WugaV01Skill{
@Override
public void attack() {}
@Override
public void defend() {}
@Override
public void dance() {}
}
public class Wuga_V02 implements Robot{
@Override
public void attack() {}
@Override
public void defend() {}
}
클래스에 필요한 기능만 선언 가능하고 재사용성이 높아짐
용도가 명확한 인터페이스를 제공할 수 있음
DIP - Dependency Inversion principle
- 의존 역전 원칙
- 자주 변경이 되는 클래스에 대해서는 의존 X
- 의존 관계를 맺을 때, 구체적인 클래스보다 인터페이스나 추상 클래스와 맺어야 함
프로그래머가 자바에서 파이썬으로 바꿀 때 변경 되어야 함
하지만, 오른쪽 그림처럼 추상화 된 언어라는 인터페이스에 의존하면 언어에 프로그래머는 영향을 받지 않음
SOLID 요약
S (단일 책임 원칙) - 한 클래스는 하나의 책임만 가져야 함
O (개방 폐쇄 원칙) - 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 함
L (리스코프 치환 법칙) - 부모와 자식 클래스 정의가 논리적으로 제대로 된 상속이어야 함
I (인터페이스 분리 원칙) - 한 클래스는 쓰지 않는 기능을 가진 인터페이스는 구현하지 않기
D (의존 역전 원칙) - 자주 변경이 되는 클래스에 대해서는 의존 X
'dev > ✍️ computer science' 카테고리의 다른 글
[Database] Concurrent Control이란? (0) | 2023.09.19 |
---|---|
[면접뿌시기] 운영체제 질문 정리 - 01 (0) | 2023.09.14 |
HTTP 와 HTTPS 의 차이는 무엇일까? (0) | 2022.07.15 |
REST와 RESTful API란? (2) | 2022.06.04 |
OOP 란? (0) | 2022.05.31 |