본문 바로가기

CS/Computer Science

01/10 SOLID

객체 지향 설계 과정

  1. 요구사항(제공해야 할 기능)을 찾고 세분화 한다. 그리고 그 기능을 알맞은 객체로 할당한다.
  2. 기능을 구현하는 데에 필요한 데이터를 객체에 추가한다.
  3. 해당 데이터를 이용하는 기능을 구현한다.(기능은 최대한 캡슐화)
  4. 객체 간에 어떻게 메소드 호출을 주고받을 지 결정한다.

객체지향 설계원칙

SRP (Single Responsibility) 단일 책임 원칙

  • 클래스는 단 한개의 책임을 가져야 함
  • 클래스를 변경하는 이유는 단 하나여야함
  • 이를 지키지 않으면, 한 책임의 변경에 의해 다른 책임과 관련된 코드에 영향을 미칠 수 있음
  • -> 이렇게 되면 유지보수가 매우 비효율적

예를 들어 어떤 클래스 내에 A라는 메소드가 있고, 이 A메소드는 A 메소드의 결과를 기반으로 B 메소드를 호출하며, B 메소드는 B 메소드의 결과를 기반으로 C 메소드를 호출하다록 구현이 되어있다고 해보자. 이 때 만약 A 메소드의 동작이 일부 수정된다고 할 때, B 와 C 메소드를 전부 바꿔야 할 상황이 발생할 수 있다. 유지보수가 매우 비효율적인 것이다. 따라서 이들을 모두 분리할 필요가 있다.

OCP(Open-Closed)개방 - 폐쇄 원칙

  • 확장에는 열려있어야 하고, 변경에는 닫혀 있어야 함
  • 즉, 기존의 코드를 변경하지 않고 기능을 수정하거나 추가할 수 있도록 설계해야 함
  • 이를 지키지 않으면 instanceof 와 같은 연사자를 사용하거나, 다운 캐스팅 발생

어떤 모듈의 기능을 하나 수정할 때, 그 모듈을 이용하는 다른 모듈들 역시 줄줄이 고쳐야 한다면 유지보수가 복잡할 것이다. 따라서 개방 폐쇄 원칙을 잘 적용하여 기존 코드를 변경하지 않아도 기능을 새롭게 만들거나 변경할 수 있도록 해야 한다.

 

그렇지 않으면 객체지향 프로그밍의 가장 큰 장점인 유연성, 재사용성, 유지보수성 등을 모두 잃어버리는 셈이고, OOP를 사용하는 의미가 사라지게 된다.

 

 

-> OCP 는 **추상화 (인터페이스) 와 상속 (다형성)** 등을 통해 구현해낼 수 있다. 자주 **변화하는 부분을 추상화함**으로써 **기존 코드를 수정하지 않고도 기능을 확장할 수 있도록 함**으로써 **유연함**을 높이는 것이 **핵심**이다.

LSP(Liskov Substitutaion) 리스코프 치환 원칙

  • 하위 타입 객체는 상위 타입 객체에서 가능한 행위를 수행할 수 있어야 함
  • -> 즉, 상위 타입 객체를 하위 타입 객체로 치환해도 정상적으로 동작해야 함
  • 상속관계에서는 곡 일반화 관계(IS-A)가 성립해야 한다느느 의미(일관성 있는 관계인지)
  • 상속관계가 아닌 클래스들을 상속관계로 설정하면, 이 원칙이 위배됨

-> 결국은, **리스코프 치환 원칙을 지키지 않으면 개방 폐쇄 원칙을 위반**하게 되는 것이다. 기능 확장을 위해 기존의 코드를 **여러 번 수정**해야 할 것이다. 따라서 상속 관계를 잘 정의하여 **LSP 원칙이 위배되지 않도록 설계**해야 한다.

ISP(Interface Segregration) 인터페이스 분리 원칙

  • 클라이언트는 자신이 사용하는 메소드에만 의존해야 한다는 원칙
  • 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 않아야 함   ->   하나의 통상적인 인터페이스보다는 차라리 여러 개의 세부적인(구체적인) 인터페이스가 나음
  • 인터페이스는 해당 인터페이스를 사용하는 클라이언트를 기준으로 잘게 분리 되어야 함

-> 각 **클라이언트가 필요로 하는 인터페이스들을 분리함**으로써, 클라이언트가 **사용하지 않는 인터페이스에 변경이 발생하더라도 영향을 받지 않도록** 만들어야 하는 것이 **핵심**이다.

DIP (Dependency Inversion) 의존 역전 원칙

  • 의존 관계를 맺을 때, 변하기 쉬운것(구체적인 것) 보다는 변하기 어려운 것(추상적인 것)에 의존해야  -> 구체화된 클래스에 의존하기 보다는 추상 클래스나 인터페이스에 의존해야 한다는 뜻
  • 즉, 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안됨
  • 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 함
  • 저수준 모듈이 변겨되어도 고수준 모듈은 변경이 필요없는 형태가 이상적

마무리

**SRP 와 ISP 는 객체가 커지는 것을 막아준다**. 객체가 단일 책임을 갖도록 하고 클라이언트마다 특화된 인터페이스를 구현하게 함으로써 **한 기능의 변경이 다른 곳까지 미치는 영향을 최소화**하고, 이는 **기능 추가 및 변경에 용이**하도록 만들어 준다.

**LSP 와 DIP 는 OCP 를 서포트**한다. OCP 는 자주 변화되는 부분을 추상화하고 다형성을 이용함으로써 기능 확장에는 용이하되 기존 코드의 변화에는 보수적이도록 만들어 준다. 여기서 **'변화되는 부분을 추상화'할 수 있도록 도와주는 원칙이 DIP 이고, 다형성 구현을 도와주는 원칙이 LSP** 인 것이다.

 

 

*** 출처 ***

 

https://velog.io/@haero_kim/SOLID-%EC%9B%90%EC%B9%99-%EC%96%B4%EB%A0%B5%EC%A7%80-%EC%95%8A%EB%8B%A4

 

 

SOLID 원칙, 어렵지 않다!

객체지향 프로그래밍 설계 원칙에 대해 알아보기

velog.io

 

'CS > Computer Science' 카테고리의 다른 글

01/13 깃과 깃허브  (0) 2023.01.13
01/12 트랜잭션의 ACID 성질  (0) 2023.01.12
01/09 디자인 패턴이란?  (0) 2023.01.11
01/06 컴파일러  (0) 2023.01.06
01/05 GPU  (0) 2023.01.05