Study/TIL(Today I Learned)

24.08.23 CS

에린_1 2024. 8. 23. 17:44
728x90

CS

SRP(단일 책임 원칙)

  • 단일 책임 원칙은 객체는 단 하나의 책임만 가져야 한다는 원칙을 말한다. 여기서 책임이라는 의미는 하나의 기능 담당으로 보면 된다. 즉, 하나의 클래스는 하나의 기능만을 담당하여 하나의 책임을 수행하는데 집중되어 있어야 한다는 의미이다.
  • 하나의 클래스에 여러 기능(책임)을 넣느냐, 따로따로 클래스를 분리하여 기능(책임)을 분산시키느냐 설계는 프로그램의 유지보수와 밀접한 관련이 있다.
  • 단일 책임 원칙 준수 유무에 따른 가장 큰 특징 기준 척도는, 기능 변경(수정)이 일어났을때의 파급 효과이다.
  • 한 객체에 책임이 많아질수록 클래스 내부에서 서로 다른 역할을 수행하는 코드끼리 강하게 결합될 가능성이 높아지게 되어 시스템이 복잡해질 수 있다. 그래서 그 객체가 하는 기능에 변경사항이 생기면 이 기능을 사용하는 부분의 코드를 모두 다시 테스트를 해야 할 수도 있다.
  • 여기서 단일 책임 원칙을 적용한다면, 각 클래스 주제마다 알맞는 책임을 가짐으로서 책임 영역이 확실해지게 된다. 그래서 어떠한 역할에 대해 변경사항이 발생했을때, 변경 영향을 받는 기능만 모아둔 클래스라면 그 책임을 지니고 있는 클래스만 수정해주면 될 일이다.
  • 이것을 다르게 말하면, 모듈이 변경되는 이유가 한가지 여야 함을 뜻한다. 여러가지 책임을 가지고 있으면 각기 다른 사유에 의해서 모듈이 변경되는 이유가 여러가지가 되기 때문이다.
  • 즉, SRP 원칙을 잘 따르면 한 책임의 변경으로부터 다른 책임의 변경으로의 연쇄작용에서 자유로울 수 있게 된다. 뿐만 아니라 책임을 적절히 분배함으로써 코드의 가독성 향상, 유지보수 용이라는 이점까지 누릴 수 있으며, 뒤에서 배울 다른 설계 원리들을 적용하는 기초가 되기도 한다.

SRP 원칙 적용 주의점

  1. 클래스명은 책임의 소재를 알 수 있게 작명
    • 클래스가 하나의 책임을 가지고 있다는 것을 나타내기 위해, 클래스명을 어떠한 기능을 담당하는지 알 수 있게 작명하는 것이 좋다.
    • 즉, 각 클래스는 하나의 개념을 나타내게 구성하는 것이다.
  2. 책임을 분리할 떄 항상 결합도, 응집도를 확인
    • SRP 원칙을 따른다고 해서 무턱대고 책임을 아무 생각 없이 분리하면 안되고, 항상 결합도와 응집도를 따져가며 구성해야 한다.
    • 응집도란 한 프로그램 요소가 얼마나 뭉쳐있는가를 나타내는 척도이고, 결합도는 프로그램 구성 요소들 사이에 얼마나 의존적인지를 나타내는 척도이다.
    • 좋은 프로그램이란 응집도를 높게, 결합도는 낮게 설계하는 것을 말한다. 따라서 여러가지 책임으로 나눌때는 각 책임간의 결합도를 최소로 하도록 코드를 구성해야 한다. 하지만 그 반대로 너무 많은 책임 분할로 인하여 책임이 여러군데로 파편화 되어있는 경우에는 산탄총 수술로 다시 응집력을 높여주는 작업이 추가로 필요하다.

산탄총 수술

  • 반대로 하나의 책임 담당이 여러 개의 클래스들로 분산되어 있는 경우에도, 단일 책임 원칙에 입각해 설계를 변경해야 하는 케이스도 존재한다. 예를 들어 로깅, 보안, 트랜잭션과 같은 시스템 안에 포함되는 부가 기능을 이것도 하나의 책임으로 보고 분리하라는 것이다.
  • 부가 기능이라 할 지라도 산발적으로 여러곳에 불포된 책임들을 한 곳에 모으면서 응집도를 높이는 것이다.

참조

https://inpa.tistory.com/entry/OOP-💠-아주-쉽게-이해하는-SRP-단일-책임-원칙

 

💠 완벽하게 이해하는 SRP (단일 책임 원칙)

단일 책임 원칙 - SRP (Single Responsibility Principle) 단일 책임 원칙(SRP)는 객체는 단 하나의 책임만 가져야 한다는 원칙을 말한다. 여기서 '책임' 이라는 의미는 하나의 '기능 담당'으로 보면 된다. 즉,

inpa.tistory.com

 

OCP(개방 폐쇄 원칙)

  • 개방 폐쇄의 원칙(OCP)이란 기존의 코드를 변경하지 않으면서, 기능을 추가할 수 있도록 설계가 되어야 한다는 원칙을 말한다. 보통 OCP를 확장에 대해서는 개방적(open)이고, 수정에 대해서는 폐쇄적(closed)이어야 한다는 의미로 정의한다. 여기서 확장이란 새로운 기능이 추가됨을 의미한다.
  • 따라서 해석하자면, 기능 추가 요청이 오면 클래스를 확장을 통해 손쉽게 구현하면서, 확장에 따른 클래스 수정은 최소화 하도록 프로그램을 작성해야 하는 설계 기법을 말한다고 보면 된다.
    • 확장에 열려있다.
      • 모듈의 확장성을 보장한다는 것을 의미한다.
      • 새로운 변경 사항이 발생했을 때 유연하게 코드를 추가함으로써 애플리케이션의 기능을 큰 힘을 들이지 않고 확장할 수 있다.
    • 변경에 닫혀있다.
      • 객체를 직접적으로 수정하는건 제한해야 한다는 것을 의미한다.
      • 새로운 변경 사항이 발생했을 때 객체를 직접적으로 수정해야 한다면 새로운 변경사항에 대해 유연하게 대응할 수 없는 어플리케이션이라고 말한다.
      • 이는 유지보수의 비용 증가로 이어지는 매우 안좋은 예시이다.
      • 따라서 객체를 직접 수정하지 않고도 변경사항을 적용할 수 있도록 설계해야 한다. 그래서 변경에 닫혀있다고 표현한 것이다.
  • 즉, OCP는 다형성과 확장을 가능케 하는 객체지향의 장점을 극대화하는 설계 원칙으로써, 우리는 코딩할때 강의에서 배운대로 객체를 추상화함으로써, 확장엔 열려있고 변경엔 닫혀있는 유연한 구조를 만들어 사용해오며 객체 지향 프로그래밍의 OCP 원칙의 효과를 이용한다.
  • 그래서 클래스를 추가해야 한다면 기존 코드를 크게 수정할 필요없이, 적절하게 상속 관계에 맞춰 추가만 한다면 유연하게 확장을 할 수 있었던 것이다.

OCP 원칙 적용 주의점

  • 확장에는 열려있고 변경에는 닫히게 하기 위해서는 추상화를 잘 설계할 필요성이 있는데, 추상화(추상 클래스 or 인터페이스)를 정의할 때 여러 경우의 수에 대한 고려와 예측이 필요하다.
  • 보통 우리는 추상화라는 개념에 대해 구체적이지 않은 정도의 의미로 느슨하게 알고만 있다. 하지만 그래디 부치에 의하면 추상화란 다른 모든 종류의 객체로부터 식별될 수 있는 개체의 본질적인 특징이라고 정의한다.
  • 즉, 추상 메서드 설계에서 적당한 추상화 레벨을 선택함으로써, 어떠한 행위에 대한 본질적인 정의를 서브 클래스에 전파함으로써 관계를 성립되게 하는 것이다.
  • 만일 이러한 추상화에 따른 상속 구조를 처음부터 요상하게 구성하게 되면, 다음에 배울 LSP(리스코프 치환 원칙) 과 ISP(인터페이스 분리 원칙) 위반으로 이어지게 된다.
  • 또한 OCP는 DIP(의존 역전 원칙)의 설계 기반이 되기도 한다.

참조

https://inpa.tistory.com/entry/OOP-💠-아주-쉽게-이해하는-OCP-개방-폐쇄-원칙

 

💠 완벽하게 이해하는 OCP (개방 폐쇄 원칙)

개방 폐쇄 원칙 - OCP (Open Closed Principle) 개방 폐쇄의 원칙(OCP)이란 기존의 코드를 변경하지 않으면서, 기능을 추가할 수 있도록 설계가 되어야 한다는 원칙을 말한다. 보통 OCP를 확장에 대해서는

inpa.tistory.com

 

LSP(리스코프 치환 원칙)

  • 리스코프 치환 원칙은 1988년 바바라 리스코프가 올바른 상속 관계의 특징을 정의하기 위해 발표한 것으로, 서브 타입은 언제나 기반 타입으로 교체할 수 있어야 한다는 것을 뜻한다.
  • 교체할 수 있다는 말은, 자식 클래스는 최소한 자신의 부모 클래스에서 가능한 행위는 수행이 보장되어야 한다는 의미이다. 즉, 부모 클래스의 인스턴스를 사용하는 위치에 자식 클래스의 인스턴스를 대신 사용했을 때 코드가 원래 의도대로 작동해야 한다는 의미이다.
  • 이것을 부모 클래스와 자식 클래스 사이의 행위가 일관성이 있다고 말한다.

LSP 원칙 적용 주의점

  • 결국 리스코프 치환 원칙이란, 다형성의 특징을 이용하기 위해 상위 클래스 타입으로 객체를 선언하여 하위 클래스의 인스턴스를 받으면, 업캐스팅된 상태에서 부모의 메서드를 사용해도 동작이 의도대로만 흘러가도록 구성하면 되는 것이다. 그리고 LSP 원칙의 핵심은 상속 (Inheritance)이다.
  • 그런데 주의할 점은, 객체 지향 프로그래밍에서 상속은 기반 클래스와 서브 클래스 사이에 IS-A 관계가 있을 경우로만 제한되어야 한다. 그 외의 경우에는 합성(Composition)을 이용하도록 권고되어 있다.
  • 따라서 다형성을 이용하고 싶다면 extends 대신 인터페이스로 implements 하여 인터페이스 타입으로 사용하기를 권하며, 상위 클래스의 기능을 이용하거나 재사용을 하고 싶다면 상속(Inheritance) 보단 합성(Composition)으로 구성하기를 권장한다.

참조

https://inpa.tistory.com/entry/OOP-💠-아주-쉽게-이해하는-LSP-리스코프-치환-원칙

 

💠 완벽하게 이해하는 LSP (리스코프 치환 원칙)

리스코프 치환 원칙 - LSP (Liskov Substitution Principle) 리스코프 치환 원칙은 1988년 바바라 리스코프(Barbara Liskov)가 올바른 상속 관계의 특징을 정의하기 위해 발표한 것으로, 서브 타입은 언제나 기반

inpa.tistory.com

 

728x90

'Study > TIL(Today I Learned)' 카테고리의 다른 글

24.08.27 CS, C++  (0) 2024.08.27
24.08.26 CS, C++  (0) 2024.08.26
24.08.22 CS, C++  (0) 2024.08.22
24.08.21 CS  (0) 2024.08.21
24.08.20 CS, 디자인 패턴  (0) 2024.08.20