SOLID 원칙

newVelog·2024년 5월 3일
0

CS

목록 보기
27/31

객체지향 프로그래밍 설계시 좋은 객체지향 설계를 위한 SOLID 라고 불리는 5가지 원칙이 있다. 
SOLID의 용어의 개념 이론들은 모두 자바의 클래스 객체 지향의 특징이었던 추상화, 상속, 다형성, 캡슐화 등의 개념들을 재정립한 것으로 보면 된다.
SOLID 원칙은 소프트웨어를 설계함에 있어 이해하기 쉽고, 유연하며, 유지보수 및 확장이 편하다는 장점이 있다.

SRP

단일 책임 원칙 - Single Responsibility Principle

하나의 클래스는 하나의 책임(기능)을 갖는다.
모든 클래스는 각각 하나의 책임만 가져야 하며, 수정할 이유는 단 한 가지여야 한다.
즉, 클래스는 그 책임을 완전히 캡슐화해야 함을 말한다.

예를들어 결제 기능의 클래스가 있다면 이 클래스는 오직 결제 기능만을 책임지고, 만약 이 클래스를 수정해야 한다면 결제에 관련된 문제여야만 한다.

OCP

개방 폐쇄 원칙 - Open/Closed Principle

확장에는 열려있고 변경에는 닫혀 있어야 한다.
소프트웨어의 구성요소(컴포넌트, 클래스, 모듈, 함수)는 확장에는 열려 있어야 하지만 변경에는 폐쇄적이어야 함을 의미한다.
즉, 기존의 코드를 변경하지 않으면서, 기능을 추가할 수 있도록 설계가 되는 원칙을 말한다.

예를들어 캐릭터 하나를 생성한다고 할 때 각 캐릭터마다 움직임이 다를 경우 움직임 패턴 구현을 하위 클래스에 맡긴다면 캐릭터 클래스의 수정은 필요없고(Closed),
움직임 패턴만 재정의 하면 된다.(Open)

개방-폐쇄 원칙을 적용하기 위한 중요 메커니즘은 추상화다형성이다.

LSP

리스코프 치환 원칙 - Liskov's Substitution Principle

서브 타입은 언제나 자신의 기반 타입으로 변경할 수 있어야 한다.

상위 타입은 항상 하위 타입으로 대체될 수 있어야 함을 의미한다.
즉, 부모 클래스가 들어갈 자리에 자식 클래스를 넣어도 역할을 하는데 문제가 없어야 한다는 의미이다.

예를들어 자바에서는 Collection 인터페이스를 생각할 수 있다.
Collection 타입의 객체에서 자료형을 LinkedList에서 전혀 다른 자료형 HashSet으로 바꿔도 add() 메서드를 실행하는데 있어 원래 의도대로 작동되기 때문이다.
한마디로 다형성 이용을 위해 부모 타입으로 메서드를 실행해도 의도대로 실행되도록 구성을 해줘야 하는 원칙이라 이해하면 된다.

public void myData() {
	// Collection 인터페이스 타입으로 변수 선언
    Collection data = new LinkedList();
    data = new HashSet(); // 중간에 전혀 다른 자료형 클래스를 할당해도 호환됨
    
    modify(data); // 메소드 실행
}

public void modify(Collection data){
    list.add(1); // 인터페이스 구현 구조가 잘 잡혀있기 때문에 add 메소드 동작이 각기 자료형에 맞게 보장됨
    // ...
}

리스코프 치환 원칙은 다형성 원리를 이용하기 위한 원칙 개념으로 보면 된다.

ISP

인터페이스 분리 원칙 - Interface Segregation Principle

하나의 일반적인 인터페이스보다 여러 개의 구체적인 인터페이스가 낫다.

인터페이스 분리 원칙은 각 역할에 맞게 인터페이스를 분리하는 것이다.
인터페이스 내에 메소드는 최소한 일수록 좋다. 즉, 최소한의 기능만 제공하면서 하나의 역할에 집중하라는 뜻이다.

SRP 원칙이 클래스의 단일 책임을 강조한다면, ISP는 인터페이스의 단일 책임을 강조하는 것으로 보면 된다.
즉, SRP 원칙의 목표는 클래스 분리를 통하여 이루어진다면, ISP 원칙은 인터페이스 분리를 통해 설계하는 원칙.

DIP

의존성 역전 원칙 - Dependency Inversion Principle

구체적인 것이 추상화된 것에 의존해야 한다. 자주 변경되는 구체 클래스에 의존하지마라.

의존 관계를 맺을 때 변화하기 쉬운 것 또는 자주 변화하는 것보다는 변화하기 어려운 것, 거의 변화가 없는 것에 의존하라는 것이다.
즉, 구체적인 클래스보다 상위 클래스, 인터페이스, 추상 클래스와 같이 변하지 않을 가능성이 높은 클래스와 관계를 맺으라는 것이다.


만약 요리사라는 객체가 치즈 피자 레시피라는 구체적인 클래스에 의존하게 된다면 레시피가 변경될 때마다 요리사 객체에서도 변경을 해줘야 한다.
이는 DIP를 위반한 것으로 유연성을 떨어트린다.


요리사 객체를 피자 레시피라는 인터페이스에 의존하도록 하고, 피자 레시피 인터페이스를 구현하는 여러 레시피 클래스들을 만들면 DIP를 지킬 수 있다. 이렇게 하면 피자 레시피가 변경되더라도 요리사 객체의 변경을 필요하지 않아 유연성과 확장성이 높아지게 된다.

DIP 원칙을 따르는 가장 인기 있는 방법은 의존성 주입(DI; Dependency Injection)을 활용하는 것이다.

출처 : https://dev-coco.tistory.com/142
https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84%EC%9D%98-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%B9%99-SOLID
https://code-lab1.tistory.com/121

0개의 댓글