SOLID - 객체 지향 설계의 5가지 원칙

Yetti·2023년 6월 1일
0
post-thumbnail
"본 내용은 스스로 공부한 내용을 정리한 것이므로 부정확한 내용이 있을 수 있습니다. 잘못된 내용을 댓글로 알려주신다면 진심으로 감사드리겠습니다."
"그리고 공식문서가 존재하는 내용이라면 공식문서 먼저 찾아보고 오시길 부탁드립니다."

SOLID를 알기 전에 반드시 알아야 할것


"프로그래밍에서 가치는 원칙보다 높은 수준의 개념이며, 원칙을 가치를 지키기 위해서 존재해야 한다." - 켄트 백

프로그래밍에서의 가치 3가지

  1. 가독성, 커뮤니케이션
    1. 읽고 이해할 수 없는 코드는 가치가 없다!!
  2. 단순성
    1. 버그가 생길 틈이 적어진다.
    2. 커뮤니케이션에 도움된다.
    3. 미래의 확장성을 위해서 복잡한 패턴은 경계해야할 대상이다.
  3. 유연성
    1. 기존의 코드를 수정하는 데에 최대한 적은 시간을 소모되어야 한다.
    2. 처음부터 유연성있는 코드를 작성하는데에는 많은 경험이 필요하다.

유연성은 언제 챙겨야 하나?

  • 처음엔 단순하게진행하다가 기획 또는 정책의 변경이 발생하면 유연성 측면을 고려해볼 수 있다.

개발자에게 가독성, 단순성, 유연성이 중요 가치인 이유

  • 위 3가지 원칙은 리팩토링 시간을 줄여주고,리팩토링 시간을 줄이면 그만큼의 시간이 생기고 시간은 곧 비용 으로 직결된다.

엔지니어는 현재의 상황에서 우선순위를 계산하고, 그에 맞는 최선의 선택을 추구해야하고 최선의 선택을 위해서는 우리만의 기준을 세워두어야 한다.

SOLID 원칙


SOLID 원칙 간단 정리 표

약어개념
SSRP단일 책임 원칙(Single Responsibility Principle) → 한 클래스는 하나의 책임만 가져야 한다.
OOCP개방 - 폐쇄 원칙(Open Closed Principle) → 소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.
LLSP리스코프 치환 원칙(Liskov Substitution Principle) → 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
IISP인터페이스 분리 원칙(Interface Segregation Principle) → 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
DDIP의존 관계 역전 원칙(Dependency Inversion Principle) → 프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다. 의존성 주입은 이 원칙을 따르는 방법 중 하나다.

1. 단일 책임 원칙(SRP)


소프트웨어 요소(타입, 모듈, 함수 등)는 응집도 있는 하나의 책임(기능)을 가져야 한다.

  • 타입을 변경해야 하는 이유는 단지 응집도여야 한다.
  • 변경을 위한 이유가 같은 것들끼리 잘 모여있어야 한다.
  • 높은 응집도를 바탕으로 코드의 수정은 한 곳에 집중되어야 한다.

응집도(Cohesion): 응집도는 모듈에 포함된 내부 요소들이 하나의 책임/ 목적을 위해 연결되어있는 연관된 정도를 뜻한다. 응집도는 높을 수록 좋다.

2. 개방 - 폐쇄 원칙(OCP)


소프트웨어 요소는 확장 가능하도록 열려있고, 변경에는 닫혀있어야 한다.

  • 기존 코드의 변경 없이도 기능을 추가할 수 있도록 설계해야 한다.
  • 기존 코드의 변경은 버그의 가능성을 높이고 테스트 코드의 변경도 필요할 수 있기 때문에 확장을 할 때는 연쇄적인 수정이 일어나지 않도록 기존의 코드를 최대한 건드리지 않아야 한다.
  • 즉, 프로토콜이 있고 그 프로토콜을 채택하는 타입들이 있다면 확장을 할 때 프로토콜 내부는 건들지않고 타입 내부에서 수정되는게 좋은 방식이다.

OCP를 잘 이행하기 위한 방법

  1. 먼저 변경(확장)될 것과 변하지 않을 것을 엄격히 구분한다.
  2. 2개 이상의 모듈이 만나는 지점에 프로토콜을 정의한다.
  3. 구현체에 의존하기보다 정의한 프로토콜에 의존하도록 코드를 작성 한다.

3. 리스코프 치환 원칙(LSP)


자식 클래스는 언제나 부모 클래스로 교체 가능해야한다.

  • 부모 클래스의 인스턴스를 사용하는 위치에 자식 클래스의 인스턴스를 대신 사용했을 때 코드가 원래 의도대로 작동해야 한다는 뜻이다.
  • 생각보다 지키지기 어려운 원칙 중 하나다.

4. 인터페이스 분리 원칙(ISP)


클라이언트 객체는 사용하지 않는 메소드에 의존하면 안된다.

  • 프로토콜이 커지면 그만큼 한번에 요구되는 구현량이 많아진다. 일부 기능만 필요함에도 불구하고 나머지 기능들은 사용할 수 없는데도 구현해주어야 한다.
  • 예를 들어보자
    스마트폰 프로토콜이 존재하고 그곳엔 스마트폰을 구현하기 위한 각종 기능들이 들어가 있고 그 중에는 생체 인식 기능도 있다. 만약 iPhone 14 클래스를 구현해야한다면 프로토콜 내부의 동작들을 모두 사용할 수 있고 ISP원칙을 지킬 수 있다. 하지만 iPhone 2 클래스를 구현하게 된다면 생체 인식 기능은 포로토콜 규칙 상 구현은 하되 빈공간으로 버려지는 기능이 될 것이고 이런 상황은 ISP원칙을 위반한 것이다.
  • 그렇기 때문에 각각의 프로토콜은 잘게 분리가 되어있고 그 중에 정말 필요한 기능만 들어있는 프로토콜을 선택해서 사용할 수 있게 해야 한다.
  • 한번 프로토콜을 분리하여 구성해놓고 나중에 무언가 수정사항이 생겨서 또 프로토콜을 분리하는 행위는 지양하자.

5. 의존성 역전 원칙(DIP)


상위 레벨 모듈은 하위 레벨 모듈에 의존하면 안된다.

  • 둘 다 추상화된 프로토콜에 의존해야 한다. 추상화는 구체화에 의존하면 안되고, 구체화는 추상화에 의존하면 안된다.
  • 이유: 구체적인 것은 쉽게 변하지만, 추상적인 것은 잘 변하지 않는다.

📚참고 문서

profile
글 잘 쓰는 iOS개발자______가 되고싶다.

0개의 댓글