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
복사했습니다!