본문 바로가기

이생각 저생각

OOP 의 원칙들 (Object-Orientied Programming Principles)

OO 언어가 절차(Procedual) 언어와 다른 이유는 모듈성(Modularity)을 전면으로 내세웠느냐 아니냐의 차이라고 본다.

보통은 이 모듈의 최소 단위로 클래스(Class) 를 이야기 한다. 따라서, 클래스가 얼마만큼 잘 만들어지느냐, 그리고 그로 인해 클래스의 묶음체인 패키지(Package)혹은 컴포넌트(component)가 정제되어 있느냐가 OO 프로그램의 질(quality)을 판가름 한다.

이 퀄러티를 평가하고 유지하는 데에 있어서 기준이 되는 원칙이 몇 개 있는데, 그걸 OO 원칙(OO Principle) 이라고 부른다.

그럼, OO 원칙에는 어떤 것들이 있는지 살펴보도록 하자.


OOP 4대 기본 원칙

(Object Oriented Programming Basic Principle)

추상화(Abstraction)

추상화는 주제 영역(Subject Domain Area)내에서 시스템에 참여 시키고자 하는 대상에 대한 관심점(a point of concern)의 표현방법이다. 다만, 있는 그대로 풀어내는 것이 아니라, 모듈의 단위를 결정하기 위한 '단어'를 정하는 것이다. 추상화 단계에서 속성(attribute)과 행위(Behavior)를 분리해 내는 방식은 추상화 혼란을 일으키기 쉽기 때문에, 명백하다 생각되는 경우를 제외하고는 관계(relation)를 통해 속성과 행위를 찾아내는 방식을 선호한다.

캡슐화(Encapsulation)

추상화의 목적이 대상에 대한 관심 영역의 시야 한정(limitation of view)이라고 한다면, 캡슐화는 정보의 영역의 한정(limitation of information area)이 목적이다. 정보(Information, 혹은 Data)를 객체 안에 포함시키고, 그 정보에 대한 직접 접근은 허용하지 않는 대신, 필요에 따라 확인할 수 있는 접근점(인터페이스)을 외부에 공개하는 방식이다. 가끔, 캡슐화와 정보은닉(Information Hiding)에 대해서 혼란을 겪을 수 있는데, 캡슐화는 모듈화(modularity)의 의미가 더 강하고, 정보 은닉은 '대상에 대한 정보를 묻지(Query) 않으면 알 수 없게 만든다'는 의미를 갖는다. 따라서, 잘 된 캡슐화는 정보 은닉의 내용을 포함한다.

상속(Inheritance)

상속은 추상화와 캡슐화가 이루어진 모듈에 대한 세분화된 체계(Datailed Category)이다. 따라서, 얼마만큼 세분화(=상속)할 것인가는 설계자의 의지에 달려있다. 흔히 상세(Detail)와 복잡(Complextity)은 비례하기 때문에, 현대 프로그래밍에서는 상속은 최소한으로 한정 할 것을 권장하고 있다.

다형성(Polymorphism)

다형성은 모듈이 갖고 있는 자아 정체성(Identity)과 그 것의 표현 방식을 의미한다. 말하자면, 학생은 모두 공부를 해야 하지만, 공부하는 방식은 각자가 다 다르며, 그로 인해 각각의 학생은 구별된다. 다형성을 극대화 하기 위해 우리는 종종 추상 클래스(Abstract class)나 인터페이스(Interface, Pure Virtual Function)를 이용한다.


OO 설계 원칙들 (OO Design Principles)

OO 프로그래밍의 기본 4대 원칙 이외에도 보다 나은 OO 프로그래밍을 위해서 이야기 되는 원칙들이 있다.

그 중 가장 흔히 접하는 용어중에 SRP (Single Responsibility Principle, 단일책임원칙)이라는게 있다.

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

하나의 모듈, 그러니까 하나의 클래스 혹은 하나의 메소드는 하나의 일에 대해서만 책임을 질 수 있도록 잘 분리되어 있어야 한다는 의미로, 객체 지향의 지향점 중 하나인 높은 응집도(High Cohesion)를 말한다. 이 법칙은, 흔히 말하는 사고(logic)와 표현(Presentation)의 분리뿐 아니라, 관심도 철저하게 분리되어야 한다고 이야기 하고 있다. 따라서 SRP가 잘 되어 있는 모듈은 중복(Duplication)이 적으며, 변경이 한 곳에서만 일어날 수 있게 만들어 준다. 혹시, 데이터 모델링을 한 적이 있다면 정규화(Normalization)와 관련지어 생각할 수 있겠다. 피플웨어(Peopleware)로 잘 알려져 있는 톰 디마코가 1979년에 쓴 'Structured Analysis and Systems Specification'에서 최초로 소개 되었다.


<구조적 분석/설계의 선구자 중 한명, Tom DeMarco>


디미터의 법칙(Demeter's Law, LoD)

최소 지식의 원칙(Principle of Least Knowledge) 이라고도 불린다. OO 프로그래밍 연구 프로젝트(Demeter Project)에서 나온 법칙으로 흔히 '친한 친구들 하고만 이야기 하여라(Only talk to your immediate friends)' 라는 이야기로 요약된다. 친구는 클래스 정도로 해석하면 되며, getA().getB().getC() 하는 식으로 '여러 객체에 물어물어 가는 식으로 정보를 찾아내는 스타일은 자제하는 것이 좋다'라는 법칙이다. 재미있는 것은 다른 법칙과 달리 디미터의 법칙은 장/단점이 생기는 법칙으로, 디미터의 법칙을 잘 따를 경우 메소드(=함수)가 많이 생기게 되면서 복잡도가 증가 할 수 있다. 하지만, 전체적으로는 잘 따르는 것이 좋은 법칙이다. 현재 디미터의 법칙이라 불리는 법칙은 디미터 프로젝트의 OO 프로그래밍 스타일 가이드 중 함수와 메소드(Law of Demeter for Functions/Methods) 부분의 가이드를 말한다.


<웁슬라88 (OOPSLA 88')에서 발표된 LoD>

참고: http://www.ccs.neu.edu/home/lieber/LoD.html


<농업과 계절의 여신, 디미터>


Open/Closed Principle (OCP, 개방 폐쇄의 원칙)

"변경에는 닫혀있고, 확장에는 열려 있다" 는 법칙으로, 디자인 패턴들의 기본 원칙이 되는 원칙이다. 다형성과 인터페이스를 통해 변하는 부분과 변하지 않는 부분을 분리해 낸다.


<전략 패턴(Strategy Pattern)의 한 예>

알려진 바에 의하면 OCP는 두 종류가 있는데, 현재 우리가 사용하는 방식은, 업계에서 엉클 밥(Uncle Bob)이라 불리고 있는 Robert C. Martin이 1996년에 말한 Polymorphic Open/Closed Principle을 지칭한다.

참조 : http://www.objectmentor.com/resources/articles/ocp.pdf


<엉클 밥 아저씨>

ps. 데이터 베이스에 관심있는 사람은 오라클 자격증 OCP(Oracle Certificated Professional)와 혼동하지 않기를.:)


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

정확히는 Liskov의 공식화된 OO원칙(Fomulated principle)이 맞는 말이다. 가장 간단한 원칙이면서도 많은 걸 내포하고 있는 원칙으로, '자식(Sub-type)은 부모(Super-type)로 치환될 수 있다' 는 원칙이다.

즉, 이런 상속 관계에서 Customer A = new Police(); 가 가능해야 한다는 이야기이다.

리스코프의 원래 공식은

"Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T."

"q(x)가 타입 T의 객체 x를 증명할 수 있는 속성이 된다고 가정한다. 이때, T의 하위 클래스 S의 객체 y 에 대해서도 q(y)는 '참'이어야 한다"


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

"상위 레벨의 모듈은 하위 레벨들에 의존해선 안되며, 모든 것들은 추상에 의존해야 한다"는 원칙.

OCP와 마찬가지로 OO 설계의 중요한 개념 중 하나가 된다. 쉽게는 인터페이스에 의한 코딩으로 해석해도 무방하다. 종종 IOC(Inversion Of Control)와 혼용해서 쓰는 경향이 있는데, IOC는 Control의 Flow에 좀 더 집중되어 있기에, DIP가 발전되어서 IOC 와 DI(Dependency Injection)의 개념이 생겨났다고 보는게 맞다. 참고로 IOC는 Call Back의 개념을 갖는 헐리우드 법칙(Hollywood Principle) - "Don't call us, we'll call you" (내가 알아서 연락할테니까, 전화하지 말고 기다려)과도 일맥 상통한다.

여유가 되면 IOC와 DI 에 대해서는 마틴 파울러(Martin Fowler)의 유명한 글인 Inversion of Control Containers and the Dependency Injection pattern을 읽어보면 많은 도움이 된다.



이 외에도 ISP (Interface Segregation Priciple, 인터페이스 분리 원칙) 등이 있지만, 중요도 측면에서 생략하고자 한다.

여기 소개된 원칙들은 개발의 기본이 되는 하나의 경향(Tendency)과 흐름(Stream)이라고 생각하고, 늘 고민하며 적용할 수 있도록 노력하자.