OOP 5대 원칙

3 분 소요

OOP

객체지향 프로그래밍(OOP)이란 ?

OOP(Object-Oriented Programming)이란 객체 지향적인 프로그래밍이다.
컴퓨터 프로그램을 “객체(Object)”들의 모임이다. 각 “객체(Object)” 들은 서로 메시지를 주고 받을 수 있으며 데이터를 처리할 수 있다.

객체지향 5대원칙이란 ?

SRP(단일 책임 원칙), OCP(개방-폐쇄 원칙), LSP(리스코프 치환 원칙), DIP(의존 역전 원칙), ISP(인터페이스 분리 원칙)을 말하며,
앞자를 따서 SOILD 원칙이라고 부른다. 프로그래머가 시간이 지나도 유지 보수와 확장이 쉬운 소프트웨어를 만드는데 이 원칙들을 적용할 수 있다.



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

어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다. 클래스나 함수 등은 단 하나의 책임(기능)만을 가져야 한다는 원칙이다.

설계를 잘한 프로그램은 새로운 요구사항과 프로그램 변경에 영향을 받는 부분이 적다.

  • 위반 의심 포인트: 하나의 클래스가 둘 이상의 주제영역에 의해 영향을 받아 클래스를 변경해야 할 때

  • 원칙 적용 조치:

    • A. 주제영역을 다루는 클래스를 따로 만들어 주제영역을 분리하고, 변경해야 하는 클래스와 새로 만들어진 클래스를 연관짓는다.
    • B. 강결합을 약결합으로 변경한다. (로직을 담은 클래스가 인터페이스를 직접 구현하도록 하지 않고, 인터페이스와 클래스를 구현하는/상속받는 클래스를 새로 만든다.)



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

소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장을 지향하고, 변경을 지양해야 한다. 기존의 코드를 변경하지 않고(Closed) 기능을 수정하거나 추가할 수 있도록(Open) 설계해야 한다.

OCP에 만족하는 설계를 할 때 변경되는 것이 무엇인지에 초점을 맞춘다. 자주 변경되는 내용은 수정하기 쉽게 설계 하고, 변경되지 않아야 하는 것은 수정되는 내용에 영향을 받지 않게 해야한다.
이를 위해 자주 사용되는 문법이 인터페이스(Interface)이다.

*전략 패턴(Strategy Pattern)

전략 패턴(Strategy Pattern)과 연관을 지을 수 있다.
Strategy Pattern _Java예시

객체들이 할 수 있는 행위 각각에 대해 전략 클래스를 생성하고, 유사한 행위들을 캡슐화 하는 인터페이스를 정의하여, 객체의 행위를 동적으로 바꾸고 싶은 경우 직접 행위를 수정하지 않고 전략을 바꿔주기만 함으로써 행위를 유연하게 확장하는 방법을 말한다.

간단히 말해서 객체가 할 수 있는 행위들 각각을 전략으로 만들어 놓고, 동적으로 행위의 수정이 필요한 경우 전략을 바꾸는 것만으로 행위의 수정이 가능하도록 만든 패턴이다.

  • 위반 의심 포인트: 주제영역(환경)에 변경이 있을 때, 그 주제영역에 연관된 엔티티(클래스, 모듈, 함수 등)까지 변경해야 하는 경우(보통 주제영역과 엔티티 사이에 강결합이 맺어져 있을 때)

  • 원칙 적용 조치: 주제영역과 약결합을 맺는다. (주제영역의 인터페이스를 만들고 엔티티는 인터페이스를 통해 주제영역에 접근하도록 한다. 주제영역의 변경 영향도를 인터페이스의 구현체에 한정한다.)



3. 리스코프 교체 원칙(Liskov Substitution Principle, LCP)

서브타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다. 자식 클래스는 부모 클래스에서 가능한 행위를 수행할 수 있어야 한다.

부모 클래스와 자식 클래스 사이의 행위에는 일관성이 있어야 한다는 원칙이며, 이는 객체 지향 프로그래밍에서 부모 클래스의 인스턴스 대신 자식 클래스의 인스터스를 사용해도 문제가 없어야 한다는 것을 의미한다.
상속 관계에서는 일반화 관계(IS-A)가 성립해야 한다. 일반화 관계에 있다는 것은 일관성이 있다는 것이다. 따라서 리스코프 치환 원칙은 일반화 관계에 대해 묻는 것이라 할 수 있다.

  • 위반 의심 포인트: 어떤 인터페이스를 사용하는데, 구현체에 따라 로직을 구분하기 위해 instanceof 나 다운캐스트(downcast) 를 필요로 할 때.

  • 원칙 적용 조치: instanceof, downcast가 필요한 구현체를 다른 인터페이스의 것으로 분리한다. 이 위반이 발생함은 애초에 추상화가 잘못 되었음을 의미한다.



4. 의존 관계 역전 원칙(Dependency Inversion Principle, DIP)

고차원 모듈은 저차원 모듈에 의존하면 안 된다. 이 두 모듈 모두 다른 추상화된 것에 의존해야 한다. 의존 관계를 맺을 때, 변화하기 쉬운것 보단 변화하기 어려운 것에 의존해야 한다는 원칙이다.

여기서 말하는 변화하기 쉬운것이란 구체적인 것을 말하고, 변화하기 어려운 것이란 추상적인 것을 말한다. 객체지향적인 관점에서 보자면 변화하기 쉬운것이란 구체화 된 클래스를 의미하고, 변화하기 어려운 것은 추상클래스나 인터페이스를 의미한다. 따라서 DIP를 만족한다는 것은 의존관계를 맺을 때, 구체적인 클래스보다 인터페이스나 추상 클래스와 관계를 맺는다는 것을 의미한다.

DIP를 만족하면 ‘의존성 주입’ 이라는 기술로 변화에 유연한 설계를 할 수 있다.

  • 위반 의심 포인트: 강결합이 발견될 때.

  • 원칙 적용 조치: 추상화를 통해 인터페이스나 추상클래스를 만들어 강결합을 약결합으로 변경한다. 컨크리트 클래스에 의존하지 않는다.



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

한 클래스는 자신이 사용하지 않는 인터페이스를 구현하지 말아야 한다. 하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다.

자신이 사용하지 않는 기능(인터페이스)에는 영향을 받지 말아야 한다는 의미이다.

  • 위반 의심 포인트: 객체A 에서 객체B 를 사용하는 경우, 객체B 가 객체A 에게 필요없는 메서드를 제공할 때

  • 원칙 적용 조치: 객체A 에게 필요한 메서드만을 가진 인터페이스를 새로 만들어 객체B 의 메서드를 여기로 이동시킨다. 객체B 는 이 인터페이스를 구현하도록 하며, 당연히 객체A 는 이 새로운 인터페이스를 통해 객체B 를 사용한다.




참조 사이트

  • https://velog.io/@cyranocoding/
  • https://parkcheolu.tistory.com/123
  • https://dev-momo.tistory.com/entry/SOLID-%EC%9B%90%EC%B9%99
  • https://victorydntmd.tistory.com/292

댓글남기기