[인프런] 김영한님 스프링 입문 정리 [2.5] SOLID원칙
스프링 입문 강의를 들으면서 SOLID가 무엇인지 궁금해져 검색을 해보았다.
SOLID (객체 지향 설계)
컴퓨터 프로그래밍에서 SOLID란 객체 지향 프로그래밍 및 설계의 다섯가지 기본 원칙을 앞 글자만 따서 나열한 것이다.
단일 책임 원칙 (Single Responsibility Principle)
- 모든 클래스는 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화해야 함을 일컫는다
지금으로썬 이 이야기를 이해하자면
추론
예를들어 2개의 클래스가 있다.
서로 강한 결합도를 가진 클래스라 하나를 변경하면 다른 클래스도 변경해야 해서
프로그램 확장이 어렵다 라는 뜻 같다.
또한 옛날 나의 코딩 방식처럼 public static void main 문에 모든 것을 다 구현한다면
이것은 모든 책임을 하나의 클래스에 담은 것이므로 유지보수가 매우 불편할 것이다.
결론
그렇기 때문에 클래스간의 결합도는 낮고 각 클래스마다의 응집도는 높여서
유지보수를 더욱 용이하게 개발을 하라는 원칙 같다.
개방-폐쇄 원칙 (Open/Closed Principle)
- 확장에 대해서는 열려있어야 하고 수정, 변경에 대해서는 닫혀 있어야 한다는 걸 일컫는다.
..네? 이게 뭔소린
지금으로썬 이 이야기를 이해하자면
객체 지향 프로그래밍의 좋은 점은 하나의 부품을 조립해서 완성품을 만드는 것이라고 생각한다.
예를 들자면 인터페이스 같은 것을 뜻하는 것 같다.
추론
어떠한 작동을 위한 인터페이스를 만들었다면
그리고 또 어플리케이션의 운영 체제, 혹은 DB, 혹은 기타 사항이 변경됬을 경우
해당 인터페이스 구현 클래스를 새로 만들어 변경된 사항을 넣고 실행시키기 만해도 작동이 될 것이다.
만약 기존으로 돌아가고 싶다면 인터페이스 구현 클래스를 갈아끼기만 하면 될 것이다.
결론
다형성에 관련한 이야기 같다.
리스코프 치환 원칙 (Liskov Substituion Principle)
- 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
지금으로썬 이 이야기를 이해하자면
추론
자바에 Stack<E>이라는 자료구조는 Vector<E>라는 자료구조의 자식 클래스이다.
기존에 Vector<E>로 짜둔 프로그램이 있다.
이 Vector<E> 인스턴스 대신 Stack<E>의 인스턴스를 서로 맞 바꿀 수 있어야 된다는 이야기 같다.
결론
상속에 관련된 이야기 같다.
인터페이스 분리 원칙 (Interface Segregation Principle)
- 클라이언트가 자신이 이용하지 않는 메서드에 의존하지 않아야 한다는 원칙이다.
지금으로썬 이 이야기를 이해하자면
추론
유선충전 인터페이스 - vodi charge();
무선충전 인터페이스 - void wirelssCharge()
통화, 메세지 인터페이스 - void message(), void call()
이런 메서드를 구현하길 바라는 인터페이스 들이 있다고 가정하고
나는 스마트폰을 만들기로 하였다.
스마트폰은 해당 기능이 다 필요하므로 해당 기능에 맞는 인터페이스들을 골라 추상 클래스로 만들면 된다.
2G폰 같은 경우는 무선 충전이 안되니 무선충전을 제외한 인터페이스만 구현하면 된다.
검색결과
인터페이스 분리 원칙은 객체가 반드시 필요한 기능만을 가지도록 제한하는 원칙이다.
불필요한 기능의 상속 / 구현을 최대한 방지함으로써 객체의 불필요한 책임을 제거한다.
의존관계 역전 원칙(Dependency Inversion Principle)
- 프로그래머는 " 추상화에 의존해야지, 구체화에 의존하면 안된다. "
..말이 너무 어려워서 찾아보았다.
의존성 역전 원칙이란 객체는 구현된 객체보다 인터페이스와 같은 객체의 형태나 추상적 개념에 의존
즉, 가급적 객체의 상속은 인터페이스를 통해 이루어져야 한다는 의미로 해석할 수 있다.
원칙을 준수하지 못한 케이스
import java.util.Random;
public class OneHandSword {
private final String NAME;
private final int DAMAGE;
public OneHandSword(String name, int damage) {
NAME = name;
DAMAGE = damage;
}
public int attack() {
return DAMAGE + new Random().nextInt(10) - 5;
}
@Override
public String toString() {
return NAME;
}
}
public class Character {
private final String NAME;
private int health;
private OneHandSword weapon;
public Character(String name, int health, OneHandSword weapon) {
NAME = name;
this.health = health;
this.weapon = weapon;
}
public int attack() {
return weapon.attack();
}
public void damaged(int amount) {
health -= amount;
}
public void chageWeapon(OneHandSword weapon) {
this.weapon = weapon;
}
/**
* 캐릭터 정보 출력 함수
*/
public void getInfo() {
System.out.println("이름: " + NAME);
System.out.println("체력: " + health);
System.out.println("무기: " + weapon);
}
}
무기 클래스와 캐릭터 클래스를 만들었지만 해당 내용을 보면 캐릭터는 한손검밖에 쓰지 못한다.
RPG류의 무기만 해도 스태프, 단검, 창 등등이 있는데 이것을 다 오버라이딩하려면 시간이 오래..걸릴것이다.
그래서 Attackable이라는 인터페이스를 만들고 해당 인터페이스를 무기에 구현한다.
원칙을 잘 준수한 케이스
public interface Attackable {
int attack();
String toString();
}
public class Character {
private final String NAME;
private int health;
private Attackable weapon;
public Character(String name, int health, Attackable weapon) {
NAME = name;
this.health = health;
this.weapon = weapon;
}
public int attack() {
return weapon.attack();
}
public void damaged(int amount) {
health -= amount;
}
public void chageWeapon(Attackable weapon) {
this.weapon = weapon;
}
public void getInfo() {
System.out.println("이름: " + NAME);
System.out.println("체력: " + health);
System.out.println("무기: " + weapon);
}
}
이제 무기마다 Attackable을 구현한다면
캐릭터는 Attackable을 구현한 무기 클래스를 아무거나 쥘 수 있다.
이는 다형성을 활용한 것 같다.
객체지향은 이런것이 었구나 이제서야 조금 깨닫는 것 같다
그래서 그렇게 인터페이스가 많았구나 느낀다.
계속 자기계발에 힘쓰자.
출처
https://blog.itcode.dev/posts/2021/08/16/interface-segregation-principle
위키백과
Author And Source
이 문제에 관하여([인프런] 김영한님 스프링 입문 정리 [2.5] SOLID원칙), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yskim9718/인프런-김영한님-스프링-입문-정리-2.5-SOLID원칙저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)