본문 바로가기
I LEARNED/자료구조

[자료구조] 객체 지향적 설계 원칙

by veganwithbacon 2023. 1. 19.
반응형

 

이제는 너무나 익숙해진 OOP(Object-Orientied Programming, 객체지향 프로그래밍)이다.

객체지향적 설계가 Spring을 사용하며 중요한 것은 알았으니 좀더 공부해보자.

  객체지향 설계를 해야 하는 이유

객체지향의 핵심이 의존성을 줄이고 결합도를 낮추는 것이다. 이를 잘해주려면 핵심화인 캡슐화가 잘 활용되어야한다는 의미이다. 캡슐화를 잘 활용해 객체의 자율성을 높이고, 응집도를 높여 객체지향을 더 완벽하게 구현 가능하다.

 

캡슐화를 통해 의존성을 줄이고 결합도를 낮추는 것

 

객체지향 코딩을 해봤다면 객체의 자율성을 높임과 동시에 다른 객체에 대한 의존성이 높아지는 것을 경험해봤을 것이다.

위와 같이 객체의 자율성이 상승함과 동시에 결합도가 같이 높아지는 모순을 트레이드 오프라고 한다.

 

객체지향에서는 모든 것들이 능동적이고 자율적인 존재인데 이 원칙이 바로 의인화(anthropomorphism)이다.

 

의인화 뿐 아니라 객체지향 설계의 핵심 원칙 중 책임의 이동(shift of responsibility)라는 원칙이 있다.

좋은 코드는 책임을 한 객체에만 부여하지 않기에, 한 객체가 모든 책임을 지게 하지 않는다.

절차지향 프로그래밍 방식을 통해 책임을 잘 나눠주면 객체는 자신을 스스로 책임지게 된다.

 

결론적으로, 코드는 완벽하게 기능이 동작해야하고, 변경하기도 쉬워야한다.

 

이 말이 아직 이해가 안됐다면 이어서 읽으면 이해가 될 것이다.

 

  💡객체 지향 설계 원칙(SOLID 원칙)

SOLID원칙이 무엇인지 알아보자

 

1. SRP (단일 책임 원칙, Single Responsibility Principle) 

=> 모듈이 하나의 책임을 가진다는 의미보다는, 변경되는 이유가 한가지여야 한다는 의미

 

- 작성된 클래스는 하나의 기능만 가지며 클래스가 제공하나는 모든 서비스는 각각 하나의 책임(변화의 축,axis of change)만을 수행하는데 집중되어야 한다. 즉, 해당 모듈이 여러 액터에 있어 책임을 가지기보다는, 하나의 액터에만 책임을 져야한다는 의미이다. 또한 책임뿐만 아니라, 분리된 두 클래스 간의 관계 복잡도를 줄이도록 설계하는 것이 중요하다.

 

- DB 정규화와 유사하다고 볼 수 있다

 

2. OCP (개방폐쇄 원칙, Open - Closed Principle)

=> 확장에 대해 열려있으며 수정에는 닫혀있어야하는 원칙

 

- 소프트웨어의 구성요소(컴포넌트, 클래스, 모듈, 함수)는 확장은 허용하되 변경은 피해야한다

>>>  기존의 코드를 변경하지 않으면서 ,기능은 추가가능하도록 설계가 되어야한다.

 

- 요구사항의 변경이나 추가사항이 발생해도, 기존 구성요소는 수정이 일어나지 않아야 하며, 기존 구성요소를 쉽게 확장해서 재사용 가능해야 한다. 

 

OCP는 관리가능하고 재사용 가능한 코드를 만드는 기반이며,

OCP를 가능하게 하는 중요한 매커니즘이 추상화와 다형성이다.

 

즉, OCP는 객체지향의 장점을 극대화하는 중요한 원리이다.

 

3. LSP (리스코프 치환원칙, Liskov Substitution Principle)

=>자식 클래스는 언제든지 부모 클래스를 대체할 수 있는 원칙

 

>>> 기반 클래스는 파생 클래스로 대체 가능해야한다(부모 클래스의 위치에 자식 클래스를 넣어도 잘 동작해야한다.)

 

다형성을 통한 확장성을 목표로, LSP 원리도 서브 클래스가 확장에 대한 인터페이스 준수가 필수적이다.

다형성/확장성의 극대화를 위해 하위 클래스의 사용보다는 상위 클래스(인터페이스)를 사용하는 것이 좋다.

일반적으로 선언은 기반 클래스를 통해서, 생성은 세부 클래스로 대입하는 방법을 사용한다.

 

자식 클래스는 부모클래스의 책임을 무시, 재정의하지 않으며 확장만 수행하도록 한다.

위 조건을 따라 LSP를 만족한다고 할 수 있다.

 

4. ISP(인터페이스 분리 원칙, Interface Segregation Principle)

=> 주어진 저장소 내의 인터페이스 수를 제한하는 개념

 

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

- 클라이언트에서 사용하지 않는 메소드는 사용하지 않는다

 

대부분의 경우 개발자는 중앙 인터페이스 내에 여러 클래스를 구성한 다음 특정 종속성에 따라 하위 클래스를 더 분리하기 시작한다.

 

ISP 원칙은 개발자에게 종속성을 분리하는 중앙 인터페이스 내에 확장 빌드할 기능을 제공하여, 데이터가 초기 인터페이스를 벗어나지 않고 추가 기능이 있는 클래스로 라우팅된다. ISP 원칙은 SW엔지니어의 독립적인 인터페이스 내 여러 기능과 방법을 적용 및 정의하는데 도움을 준다.

 

5.DIP (의존성 역전 원칙, Dependency Inversion Principle)

=> 실사용 관계는 변화 없이, 추상을 매개로 메시지를 주고 받아 관계를 최대한 느슨하게 하는 원칙

 

의존 관계를 맺음에 있어 자주 변하거나 변화가 쉬운 것보다는 변화가 어려운것, 거의 없는 것에 의존하라는 것.

구체적인 클래스보단 인터페이스나 추상 클래스와의 관계를 맺으라는 의미.

 

확실한 필요에 의해서만 인터페이스를 생성할 것

 

DIP의 메인 키워드는 'IOC', '훅 메소드', '확장성'

 

1. IOC (Inversion Of Control, 제어의 역전)

2. 훅(HOOK) 메소드

: 슈퍼클래스에서 디폴트 기능을 정의하거나 비워두어 서브클래스에서 선택적 오버라이드 할 수 있도록 한 것

   >> 쉽게 말해 추상메소드는 오버라이딩이 강제적이나, 훅 메소드는 선택적이며 abstract도 필요없다.

3. 확장성 

 

위 세 가지 요소가 적절히 조합되어 복잡한 컴포넌트들의 관계를 단순화하고 커뮤니케이션을 효율적이게 한다.

 

 

참고 자료 : 

https://velog.io/@winz/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%84%A4%EA%B3%84%EB%9E%80-feat.-%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8 

https://limkydev.tistory.com/77 

https://devkingdom.tistory.com/95 

https://needjarvis.tistory.com/209 

https://sunlightmedia.org/ko/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84-%EC%9B%90%EC%B9%99/ 

반응형

댓글