Home SOLID 설계원칙
Post
Cancel

SOLID 설계원칙

SOLID 원칙이란?

OOP 설계시, SOLID 원칙을 지켜서 개발한다면 변경이 용이하고, 유지보수와 확장이 쉬운 SW를 개발하는데 도움이 된다고한다.

SRP : 코드 변경 시, 파급 효과가 적으면 SRP를 잘 따른것
OCP : 다형성을 극대화
LIP : 명시한 기능대로 구현하자
ISP : 여러기능 인터페이스보단 여러개의 인터페이스로 분리하는 것이 낫다.
DIP : 추상화에 의존해야지 구현 클래스에 의존하면 안된다.

Single Responsibility Principle (SRP)

단일책임원칙이란? 뜻은 하나의 모듈은 하나의 책임을 가져야한다는 뜻인데 실상 책임이라는 표현은 모호한 기준이다.
그래서 로버트 마틴의 말인 어떤 클래스를 변경해야하는 이유는 오직 하나뿐이어야한다를 생각해보면 문제는 쉬워진다.

하나의 남자가 있다고 가정해보자. 그 남자는 누구에게는 상사일수도, 부인일수도, 아들일수도있다.
상사일떄는 지시하다()라는 메소드여야하고 아내일떄는 사랑하다(), 아들일떄는 효도하기() 등 메소드 형태로 가정했을떄,
이 남자는 남자라는 테이블안에 너무나 많은 책임을 가지고 있다는 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Man{
    final static Boolean boss;
    final static Boolean husband;
    final static Boolean son;
    Boolean role;

    void 지시하다(){
        if(this.role.equals.(boss))
        else if(this.role.equals.(son))
        else
    }

}

이런식으로 남자를 하나의 클래스로 묶어 상사일떄 아들일떄 남편일떄를 모두 구현하는것은 SRP 위반이다.
딱봐도 여기서 확장을하거나 유지보수할 때 대공사가 일어날 것이 분명하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class Man{
    abstract void role();
}

class boss extends Man{
    void role();
}

class husband extends Man{
    void role();
}

class son extends Man{
    void role();
}

추상화를 통해 각자 자신의 특징에 맞게 메소드를 구현하여 하나의 책임만 지는 것을 SRP라고 한다.

Open Closed Principle (OCP)

개방 폐쇄 원칙이란? SW 엔티티(class,method,function etc)는 확장에 열려 있어야 하나, 변경에 대해서는 닫혀있어야한다.
말이 굉장히 난해하지만, 기존 코드를 유지한채 확장을 쉽게 할 수 있어야한다는 뜻이다.

OCP의 대표적인 예는 JDBC이다.
JDBC는 JAVA와 DB간의 데이터를 주고 받을수 있도록 하는 인터페이스이다.
사용자가 MySQL을 MarinaDB든 PostgreSQL든 커낵션만 바꾸면 사용할 수 있는 구조가 OCP를 잘 지킨 케이스이다.
OOP의 핵심은 OCP를 지키는데 있다.

Liskov Substitution Principle (LSP)

리스코프 치환 원칙이란? 서브타입은 언제나 자신의 기반 타입으로 교체할 수 있어야한다.
즉 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 하는 것을 의미한다. 쉽게 말해 명시한 기능대로 구현해야한다는 것이다. 하위 클래스는 상위 클래스의 한 종류여야한다.
즉 사자,기린 클래스가 있다면 상위클래스가 포유류이면 잘 지킨거고, 포유류가 고양이과이면 틀린 것이다.

Interface Segregation Principle (ISP)

인터페이스 분리 원칙이란?
여러 기능이 하나로 있는 인터페이스보다 여러가지 인터페이스로 분리하는것이 낫다는 것이다.
어찌보면 SRP와 같은 맥락으로 보면 된다. 상사일떄는 남자에게 상사역할을 부모님일떄는 아들 역할을 주는것처럼, 각 역할에 맞게 인터페이스를 분리하는 것이다.

  • 상위 클래스가 많을 수록 하위 클래스에게 많은 기능을 확장시켜주고 형변환, 코드 중복을 줄여준다.
  • 인터페이스 내에 메소드는 최소한 일수록 좋다.

Dependency Inversion Principle (DIP)

의존 역전의 원칙이란? 자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어 변하기 쉬운 것의 변화에 영향받지 않게 하는 것이다.

고차원 모듈은 저차원 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다. 추상화된 것은 구체적인 것에 의존하면 안 된다. 구체적인 것이 추상화된 것에 의존해야 한다. 자주 변경되는 구체(Concrete) 클래스에 의존하지 마라 - 로버트 C.마틴 -

이 말을 쉽게 얘기해보면 복서가 권투장갑에 의존하면 권투시합이 끝날때마다 선수가 장갑보다 더 변경사항이 자주일어나는 상황이 발생된다. 이를 방지하기 위해 구현체는 추상화에 의존하게 함으로써 서로 간의 영향을 안받는 것을 얘기한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Boxer implements Glove{
    @Override
    public void RedGlove() {
    }
    @Override
    public void GreenGlove() {
    }
    @Override
    public void BlueGlove() {
    }
}

interface Glove{
    void RedGlove();
    void GreenGlove();
    void BlueGlove();
}

결론

SRP, ISP는 한 기능의 변경이 다른 클래스에게 미치는 영향을 최소화 하고, 기능 추가와 변경에 용이하도록 해주고 (객체의 몸집을 줄여준다)

LSP, DIP는 OCP의 원칙을 지키도록 도와준다. 즉 OCP의 변화되는 부분을 추상화하도록 하는 개념이 DIP이고 다형성 구현하게 도움을 주는 원칙이 LSP이다.

This post is licensed under CC BY 4.0 by the author.