'객체지향소프트웨어일주'에 해당되는 글 5건
- 2008/05/18 객체 지향 소프트웨어 일주 - 5
- 2008/05/08 객체 지향 소프트웨어 일주 - 4
- 2008/03/28 객체 지향 소프트웨어 일주 - 3
- 2008/03/15 객체 지향 소프트웨어 일주 - 2(2)
- 2008/03/11 객체 지향 소프트웨어 일주 - 1
작성자: yagur Rev : 2
Around Object Oriented Software - 5
은닉(Encapsulation, Information Hiding)
정보 은닉에 관해서는 파나스가 옳았고 저자가 틀렸다. 저자는 7장에서 파나스의 개념을 '참사로 이끄는 처방'이라고 보고 배제했다. 그 때는 파나스가 옳았고, 저자가 틀렸다. 하지만 저자는 이제 객체 지향 프로그래밍에 흔하게 구현되는 정보 은닉이 소프트웨어 설계 수준을 높이는 유일한 길이라고 확신한다.
- 프레더릭 브룩스
모듈 혹은 객체의 은닉은 소프트웨어에서 매우 유용한 개념으로 자리잡고 있다. '감추다'라는 은닉의 사전적 의미를 그대로 받아들이면 된다. 감추어서 얻는 이득은 무엇일까? 활용의 시각(응용 영역)에서 보았을때 은닉은 생산성의 향상과 변경 영향력의 감소를 가져온다. 자동차에서 이 은닉의 적절한 예를 볼수 있다.
좌측은 수동기어, 우측은 자동기어
'수동 기어'와 '자동 기어'의 차이점은 무엇일까? 자동 기어는 사용자로 하여금 주행시 기어 조작의 기능을 은닉해버렸다. 덕분에 아래와 같이 인터페이스가 작아졌다.
'수동 기어'와 '자동 기어'의 차이점은 무엇일까? 자동 기어는 사용자로 하여금 주행시 기어 조작의 기능을 은닉해버렸다. 덕분에 아래와 같이 인터페이스가 작아졌다.
좌측은 수동기어 차량의 패달, 우측은 자동기어 차량의 패달
자동차량을 몰게 되면 차량 운행의 본 목적에 좀더 집중할수 있다. 왼쪽 발을 쉬게 하고, 주행시 기어 변경을 할 필요가 없으므로 오른손으로는 다른 행동을 취할수 있다. 신경 쓸것이 적어 졌으므로 차량 응용(운전, 길찾기, 주변상황에 따른 방어운전 등) 자체에 좀더 집중할수 있게 되는것이다. 그리고 차량 운행에 필요한 학습량을 줄일수 있다. RPM과 속도에 따라 어떤 기어를 선택해야하는지, 그리고 클러치의 사용방법과 같은 것은 이제 필요 없어졌다.
기능이 은닉된 자동 기어 탑제 차량의 판매량이 수동 기어 탑제 차량의 판매량을 월등하게 압도하고 있다. 이를 보았을때 사용자는 자동 기어 차량(기능 은닉이 이루어진 제품)을 선호(생산성 향상의 이유)한다고 볼수있다.
작은 인터페이스는 은닉과 관련이 있다. 인터페이스가 작아짐으로서 사용자는 응용 대상과의 정보 소통량이 줄어들기 때문이다.
이전 글의 마무리 부분에 은닉의 방법에 따라 다른 시점에서 구성력을 다룰수 있다고 끝맺음 하고있다. 의존 대상와 연관되어있는 모듈(혹 객체)들을 은닉한다면 사용자는 모듈의 독립성을 느끼기 때문이다. 포도송이 들여오기(전글의 예)의 시각화된 그림을 빙산으로 생각해볼수 있다.
기능이 은닉된 자동 기어 탑제 차량의 판매량이 수동 기어 탑제 차량의 판매량을 월등하게 압도하고 있다. 이를 보았을때 사용자는 자동 기어 차량(기능 은닉이 이루어진 제품)을 선호(생산성 향상의 이유)한다고 볼수있다.
작은 인터페이스는 은닉과 관련이 있다. 인터페이스가 작아짐으로서 사용자는 응용 대상과의 정보 소통량이 줄어들기 때문이다.
이전 글의 마무리 부분에 은닉의 방법에 따라 다른 시점에서 구성력을 다룰수 있다고 끝맺음 하고있다. 의존 대상와 연관되어있는 모듈(혹 객체)들을 은닉한다면 사용자는 모듈의 독립성을 느끼기 때문이다. 포도송이 들여오기(전글의 예)의 시각화된 그림을 빙산으로 생각해볼수 있다.
포도송이를 빙산으로
수면위의 모듈은 사용자에게 공개된 공개 부분이고, 수면아래의 모듈들은 의존성을 맺고 있는 은닉된 모듈들이다. 하지만 사용자는 이 정보들이 은닉되어 있기 때문에 공개된 모듈의 인터페이스에 의존하면된다. 빙산의 일각만을 보면 되기때문에 작은 인터페이스의 효과를 갖게 된다.
객체를 대상으로 바라 보았을때 C++에 pimpl idiom이란 아주 간단한 예가 있다.
위의 소스에서 Engine을 멤버로 갖고 있지만 그것이 무엇인지 사용자는 몰라도 된다. Gear를 변경하면 Gear의 구현부인 소스만이 Engine 객체에 의존성을 둔다. 사용자는 헤더에서 빙산의 일각 즉 Engine이 Class이다 란것만 알면 된다. 그리고 Gear가 어떻게 Engine에 영향을 미치는지는 은닉된다.
여기서 좀더 은닉하기 위해 의존성 줄이기Depedency Break를 시도할수 있다. Gear를 Interface로 분리해 공개 영역으로 노출하고 구현은 은닉하는것이다.
사용자에게 노출되는 인터페이스
은닉되는 구현부
객체를 대상으로 바라 보았을때 C++에 pimpl idiom이란 아주 간단한 예가 있다.
class Engine;
class Gear
{
public:
void SetGear(...);
private:
Engine* m_pEngine;
};
class Gear
{
public:
void SetGear(...);
private:
Engine* m_pEngine;
};
pimpl idiom의 예
위의 소스에서 Engine을 멤버로 갖고 있지만 그것이 무엇인지 사용자는 몰라도 된다. Gear를 변경하면 Gear의 구현부인 소스만이 Engine 객체에 의존성을 둔다. 사용자는 헤더에서 빙산의 일각 즉 Engine이 Class이다 란것만 알면 된다. 그리고 Gear가 어떻게 Engine에 영향을 미치는지는 은닉된다.
여기서 좀더 은닉하기 위해 의존성 줄이기Depedency Break를 시도할수 있다. Gear를 Interface로 분리해 공개 영역으로 노출하고 구현은 은닉하는것이다.
사용자에게 노출되는 인터페이스
class GearInterface
{
public:
void SetGear(...) abstract;
};
{
public:
void SetGear(...) abstract;
};
은닉되는 구현부
class Engine;
class ConcreteGear : public GearInterface
{
public:
void SetGear(...) override;
protected:
Engine* m_pEngine;
};
class ConcreteGear : public GearInterface
{
public:
void SetGear(...) override;
protected:
Engine* m_pEngine;
};
사용자는 공개 노출되는 인터페이스만으로 접근하기 때문에 Engine을 알필요가 없다. Engine 객체는 수면아래로 은닉되는것이라 할수 있다. pimpl 관용구를 통해 구현부안에서도 의존성을 줄이고 있고, 사용자의 응용 영역에 노출되는것은 인터페이스이기때문에 구현을 또한번 은닉하게 된다.
이 은닉과정을 객체뿐 아니라 이들이 응집된 결과물인 모듈에도 같은 원리로 적용될수 있다. 무엇을 노출하고 무엇을 은닉할지는 결코 쉬운 문제가 아니란것은 아쉬운 부분이다. 하지만 일반화와 추상화를 통해 작은 인터페이스를 만들고, 구현을 은닉함으로서 해당 모듈의 교체를 쉽게 하는것은 모듈의 독립성, 구성력에 큰 도움이 되리라 믿어 의심치 않는다.
'개발 > 수필' 카테고리의 다른 글
| 테스트와 장인 - 10 (0) | 2008/09/30 |
|---|---|
| 테스트와 장인 - 9 (0) | 2008/07/12 |
| 객체 지향 소프트웨어 일주 - 5 (0) | 2008/05/18 |
| 객체 지향 소프트웨어 일주 - 4 (0) | 2008/05/08 |
| 객체 지향 소프트웨어 일주 - 3 (0) | 2008/03/28 |
| 테스트와 장인 - 8 (0) | 2008/03/19 |
Around Object Oriented Software - 4
1.모듈성(Modularity)
객체 지향적인 소프트웨어를 작성하는 커다란 이유 중 하나는 재사용성Reusability과 확장성Extendibility이다. 굳이 객체 지향 개발에 국한시키지 않아도 재사용과 확장은 소프트웨어 개발에 중요한 의미를 지니고 있다. 의도적이던 비의도적이던 어플리케이션 제작을 확장이란 관점에서 보면, 우린 수직적인 추상도를 아래와 같이 그릴수 있다.
어플리케이션 수직적 추상도
위에서 밑으로 의존성Dependency을 지니고, 아래에서 위로 확장Extending된다 할수 있다. 이들 확장 과정에 생긴 라이브러리들은 일종의 모듈이고, 목적이나 명세에 맞게 그 기능들이 응집되어있다. 그렇다면 이 응집력Cohesiveness의 기준을 무엇에 둘것인지 생각해볼수 있다. 고려해야할 것들은 굉장히 많다. 공통적 특성, 명세, 프로젝트 상황등등 수도 없이 많은 이론과 시공간적인 조건들이 존재한다. 아쉽게도 명쾌하게 이들을 구분하고 구성하는것을 쉬운것과 어려운것으로 분류 해야한다면, 어려운쪽에 속할것이다.
객체지향을 실현하는 것은 객체란 응집 대상을 디자인하는것이고, 또 이들이 응집되어 파생된 결과물을 모듈화하는것이다. 모듈성을 지니기 위해 여러가지 사항들을 고려해볼수있다.
1-1 모듈의 독립성(Modular Independability)
어떠한 바보라도 일을 더 크고, 훨씬 복잡하고, 격렬하게 만들 수 있네. 반대 방향으로 돌리기 위해선 천재의 손길과 엄청난 용기가 필요하지.
- 존 드라이든
지금 생산중인 어플리케이션은 모듈화 되지 않고, 복잡하게 얽히고 설킨 한그릇의 스파게티인가? 나중에 가서 이들의 응집성을 고려해 모듈화하려하면 어떤 상황이 올지 상상해보자. 이 상상이 즐겁다면 작업물의 생산과정이 타의 모범이 될만한것이고, 이 과정이 괴롭다면 '천재의 손길'과 '엄청난 용기'의 필요성을 느끼기 시작한것이다. Unix의 철학인 KISS(Keep it simple s....)를 항상 염두하고 모듈화한다면, '용기'와 '천재의 손길'의 필요 횟수를 줄일수 있을것이다.
일부를 수정하기 위해 작업을 할때 변경의 여파를 고려해보자. 이는 모듈화에 필요한 응집성의 기준을 정립하는데 적지 않은 도움이 된다. 이는 모듈의 독립성과 관련이 있는데, 서로 다른 두 모듈은 서로의 변경으로부터 자유로워야 한다는 것이다. 이 글의 수직추상도의 하부에 위치하는 레이어들은 주로 그런 특성을 지니고 있다. 하지만 많은 모듈은 다른 모듈에 연관성을 지니고 있으며, 이는 상위 레이어로 갈수록 더욱 그러하다.
프로그램 모듈은 언어의 연관성의 세계에서 주로 확장되기 때문에 독립성을 너무 중시하면 생산의 효율이 떨어질수도 있다. 모듈의 위치를 잘분석하고 독립성이란 특징을 잘 해석해 적용해야할것이다.
위의 그림은 연쇄 반응에 관한 그림이다. 하나에 변경을 주었을때 연쇄적으로 다른것이 영향을 주게 되는것을 그림에서 볼수 있다. 모듈의 연관성이 수직적으로 이루어졌을때, 그 레이어가 높은곳에 있을수록 하위 레벨에 여러 레이어에 의존하고 있을 가능성이 크다. 이 경우 하위 레이어(혹은 모듈)의 변경이 있을경우 상위 레벨 레이어(혹은 모듈)들은 연쇄적으로 오동작하는 반응을 보인다.
변경 연쇄 효과 영향력
이때 수평적인 관계에 있는 모듈(레이어 깊이 레벨이 같은경우)들이 연관되어 있다면 상하개념이 아닌 수평적인 위치에 있는 모듈들까지 이 연쇄 반응에 휘말리게 된다. 나비효과Butterfly Effect를 벗어나려면 수평적 위치(같은 레벨의 레이어)에 속한 모듈들은 서로간의 의존성을 끊고 서로간에 독립성을 보장해주는것이 좋다. 그렇다면 이들은 서로 변경의 영향력에서 벗어나, 변경의 연쇄 반응에서 벗어날수 있다.
최악의 연쇄반응을 잃으키는 방법들중 몇가지를 소개하자면 소프트웨어 동작 플랫폼 교체, 언어의 컴파일러 버젼을 옛날것으로 바꾸기 등이 있다. 개발자에겐 핵폭팔과 같은 연쇄반응을 잃으키지 않을까? 이 독립성 보장은 모듈의 분해력, 구성력과 관련이 있다.
1-2 모듈의 분해력(Modular Decomposability)
거대한 모듈 혹은 여러 기능이 응집된 모듈은 공통의 문제 영역을 위해 응집되어있다. 이들은 더 작은 하위 문제 영역(subproblem domain)으로 분해될수 있다.
너무 많은 분해는 의존성 복잡도를 증가시켜 관리하는데 어려움을 주지만, 적절한 분해는 재사용성을 증대시키고 변경 영향력의 확산을 줄여줄수 있다. 이때 고려해야할 사항은 모듈의 레이어상의 위치, 그리고 이들의 의존성 관계이다. 의존성은 최대한 줄여 독립성을 최대한 보장하고, 그 연결고리를 명확히 해야한다. 그래야 책임과 분배가 더욱 쉬워진다.
명확한 의존성 정의에 관한 예를 하나 들어 보자. "이 수학 라이브러리를 업데이트 하려면 인텔 컴파일러가 필요하다. 하지만 컴파일된 결과물은 비주얼 C++에서도 링크해 사용할수 있다." 라는 의존성 정의는 사용자나 개발자가 절대 알아야할 의존 정보이다. 의존성이 명확하기 때문에 사용자는 인텔컴파일러를 써서 컴파일하고, 응용프로그램 제작시엔 비주얼 스튜디오에서 링크해 개발을 진행할수있다. 이런 사소한 컴파일 지침도 의존성이 존재한다. 복잡하고 엔트리가 많은 소프트웨어 모듈은 더욱 명확한 의존성 정의가 필요할것이며, 간결하고 그 수가 적을수록 구성Compose에 효율성을 띌것이다.
분해력을 지니되, 역으로 분해된것이 어떻게 구성되어질지를 염두한다면 좋은 모듈의 구조를 이루는 첫발이 될것이다.
1-3 모듈의 구성력(Modular Composability)
모듈은 문제 영역에 따라 구분된 재사용 가능한 집합체이다. 이 모듈을 재사용해 하나의 시스템을 구성하지 못한다면 재사용성이 매우 떨어진다고 볼수있다. 그리고 이는 모듈이라 부르기에 부끄럽다.
포도송이 들여오기(응용 프로그램과 다른 영역의 모듈간의 링크)
위의 그림은 응용 프로그램에서 하나의 모듈을 링크하려했는데 포도송이 같이 다른 모듈이 줄줄히 따라오는 경우이다. 이것이 잘된 구성일까? 과도한 분해와 잘못된 의존 관계 정립은 저런 결과를 가져올수도 있다. 필요에 의해 필요한것만 의존성을 지니게 하는것은 모듈의 독립성에 따라 좌우된다 할수 있다.
기능의 중복이 생길 우려가 있다. 공통적이 기능은 다른 모듈에 의존하여 해결하면 되는데, 독립성 보장이란 이유로 기능을 중복해버리고 다른 모듈로의 의존관계를 끊어버리는 경우가 생긴다. 독립성과 연관성의 복잡함사이에 적절한 트레이드 오프는 필요하다고 보여진다.
독립성을 최대한 살린 모듈들의 구성력이 좀더 낳으며, 변경의 영향력에 좀더 안전하다. 이는 모듈 자체의 엔트리가 대부분 공개된 경우이다. 하지만 모듈의 정보의 은닉을 어떻게 할지에 따라 이 기준은 또 다른 시점에서 다뤄질수 있다.
위의 그림은 응용 프로그램에서 하나의 모듈을 링크하려했는데 포도송이 같이 다른 모듈이 줄줄히 따라오는 경우이다. 이것이 잘된 구성일까? 과도한 분해와 잘못된 의존 관계 정립은 저런 결과를 가져올수도 있다. 필요에 의해 필요한것만 의존성을 지니게 하는것은 모듈의 독립성에 따라 좌우된다 할수 있다.
독립성이 보장된 모듈들의 링크
독립성을 어느정도 지닌 모듈이라 하면 의존성을 아껴쓴 모듈을 말한다. 이들은 응용 영역에서 링크를 해도 다른것에 의존성이 생기거나, 원치 않는 기능이 딸려 올 확률이 적다. 하지만 지나치게 독립성을 강조하게 되면기능의 중복이 생길 우려가 있다. 공통적이 기능은 다른 모듈에 의존하여 해결하면 되는데, 독립성 보장이란 이유로 기능을 중복해버리고 다른 모듈로의 의존관계를 끊어버리는 경우가 생긴다. 독립성과 연관성의 복잡함사이에 적절한 트레이드 오프는 필요하다고 보여진다.
독립성을 최대한 살린 모듈들의 구성력이 좀더 낳으며, 변경의 영향력에 좀더 안전하다. 이는 모듈 자체의 엔트리가 대부분 공개된 경우이다. 하지만 모듈의 정보의 은닉을 어떻게 할지에 따라 이 기준은 또 다른 시점에서 다뤄질수 있다.
'개발 > 수필' 카테고리의 다른 글
| 테스트와 장인 - 9 (0) | 2008/07/12 |
|---|---|
| 객체 지향 소프트웨어 일주 - 5 (0) | 2008/05/18 |
| 객체 지향 소프트웨어 일주 - 4 (0) | 2008/05/08 |
| 객체 지향 소프트웨어 일주 - 3 (0) | 2008/03/28 |
| 테스트와 장인 - 8 (0) | 2008/03/19 |
| 객체 지향 소프트웨어 일주 - 2 (2) | 2008/03/15 |
작성자: yagur Rev : 1
Around Object Oriented Software - 3
다형성(Polymorphism)
Poly는 '많은(多)'이란 뜻을 가지고 있고 morph는 '형(形)'이란 뜻을 가지고 있다. polymorph는 다형으로 번역되고 있으며 polymorphism은 다형성을 뜻하고 있다. 다형성이란 무엇일까? 다수의 형을 가진 성질이라고 해석하면 되지만 다수의 형을 갖는것이 어떤 것인지는 예를 보기전엔 알기 어려운 단어이다.
미녀와 야수에서 야수는 저주에 걸린 왕자이다. '그'는 저주를 받은 인간으로 야수의 모습을 하게 되었다. 우리가 소설속 남자 주인공을 지칭하는 '왕자'란 추상적 객체는 시간에 따라 여러 가지 형을 지니게 된다. 저주 받기 전인 과거에는 인간으로서 '왕자'였고, 저주 받은 상태의 현재엔 야수의 형태를 지닌 '왕자'이다. 또 공주를 만나 시간이 흐른 미래에는, 저주가 풀리면서 다시 인간의 형태를 지닌 '왕자'가 된다.
컴퓨터 언어의 코드 플로우에도 과거와 현재, 그리고 미래를 지니고 있다. 그리고 '그'(왕자)를 코드로 재미 삼아 표현해 본다.
미녀와 야수 코드 샘플
#1에서 그(' pHe ')는 인간이다.
#2에서 그는 야수이다.
pHe 개체의 객체인 Actor는 프로그램의 흐름에 따라 다형성을 지니는 것을 알수 있다. 역활의 추상화Abstraction으로 만들어진 Actor 객체는 대부분의 역활을 지칭하는데 쓰일수 있으며, 다형성을 지니고 있다. 이것이 주는 이점중 하나는 은닉Encapsulation이다. 사용자는 실체가 무엇인지 몰라도 추상 객체를 통해 흐름을 진행시킬수 있다. 위와 같이 추상화를 통해 실현된 다형성은 상속을 기반으로 한것이다.
행위 기반 다형성(Behavior based polymorphism)
정적 타입 언어는 상속 관계를 통한 다형성을 구현하지만 다른 방식의 다형성도 존재한다. 행위만 동일하다면 관계에 상관없이 다형성을 지니게 되는 경우이다. 이 행위 기반 다형성은 동적 타입 언어와 정적 타입 언어에서 모두 나타나지만 차이점이 존재한다. 그 차이점은 언제 다형성을 지니는것인가 이다.
정적 타입 언어의 특징상 행위 기반 다형성을 컴파일 타임에 템플릿을 통해 지원한다. 동적 타입 언어는 형 변경의 제약이 없기 때문에 실행시간에 해당 다형성을 지원하고 있다. 동적 타입 언어에서 실현되는 행위 기반 다형성을 Duck-typing이라고 한다.
하지만 Duck-Typing 역시 약속된 행위를 객체가 지니고 있어야 다형성을 지닐수 있다. 상속을 배제하고 행위를 런타임중에 확인할수 있는 언어의 특징상 생긴 기능이라 볼수 있다. 이는 정적 언어와의 성능차이로 이어진다. 양쪽 타이핑 모두 일장일단을 지니고 있다.
이렇듯 여러 객체 지향 언어에서 다형성은 매우 중요한 추상화의 실제 장점으로 여겨지고 있다. 현제 객체지향 패러다임은 추상화를 매우 중요히 다루고 있다. 다형성은 모듈화와 재사용성에 큰 영향을 미치고 있으며 필수 테크닉이 되었다.
Around Object Oriented Software - 3
다형성(Polymorphism)
Poly는 '많은(多)'이란 뜻을 가지고 있고 morph는 '형(形)'이란 뜻을 가지고 있다. polymorph는 다형으로 번역되고 있으며 polymorphism은 다형성을 뜻하고 있다. 다형성이란 무엇일까? 다수의 형을 가진 성질이라고 해석하면 되지만 다수의 형을 갖는것이 어떤 것인지는 예를 보기전엔 알기 어려운 단어이다.
미녀와 야수에서 야수는 저주에 걸린 왕자이다. '그'는 저주를 받은 인간으로 야수의 모습을 하게 되었다. 우리가 소설속 남자 주인공을 지칭하는 '왕자'란 추상적 객체는 시간에 따라 여러 가지 형을 지니게 된다. 저주 받기 전인 과거에는 인간으로서 '왕자'였고, 저주 받은 상태의 현재엔 야수의 형태를 지닌 '왕자'이다. 또 공주를 만나 시간이 흐른 미래에는, 저주가 풀리면서 다시 인간의 형태를 지닌 '왕자'가 된다.
컴퓨터 언어의 코드 플로우에도 과거와 현재, 그리고 미래를 지니고 있다. 그리고 '그'(왕자)를 코드로 재미 삼아 표현해 본다.
미녀와 야수 코드 샘플
Queen* pQueen = g_pActorFactory->CreateQueen();
King* pKing = g_pActorFactory->CreateKing();
Prince* pPrince = pKing->CreateBabyWith(pQueen); // Birth of the prince
Actor* pHe = pPrince;
pHe->LiveLifeFor("SomeYears"); // #1
Wizard* pWizard = g_pActorFactory->CreateWizard();
MagicSpell* pMagicSpell = pWizard->CreateMagicSpell("MetamorphToBeast");
pHe = pMagicSpell->CastTo(pHe); // cursed
pHe->LiveLifeFor("SomeYears"); // #2
Princess* pPrincess = g_pActorFactory->CreatePrincess();
MagicEffect* pUndoEffect = pPrincess->CreateMagicEffect("Kiss");
pHe = pUndoEffect->AffectTo(pHe); // Princess kisses the prince.
pPricess->Speaks("I love you");
pHe->Speaks("Will you marry me?"); // #3
Priest* pPriest = g_pActorFactory->CreatePriest();
pPriest->AnnounceMarriage(pHe, pPrincess); // Marriage between the princess and prince.
Life* pLifeProcess = g_pLifeFactory->CreateHappilyEverAfter();
pLifeProcess->Add(pHe);
pLifeProcess->Add(pPrincess);
King* pKing = g_pActorFactory->CreateKing();
Prince* pPrince = pKing->CreateBabyWith(pQueen); // Birth of the prince
Actor* pHe = pPrince;
pHe->LiveLifeFor("SomeYears"); // #1
Wizard* pWizard = g_pActorFactory->CreateWizard();
MagicSpell* pMagicSpell = pWizard->CreateMagicSpell("MetamorphToBeast");
pHe = pMagicSpell->CastTo(pHe); // cursed
pHe->LiveLifeFor("SomeYears"); // #2
Princess* pPrincess = g_pActorFactory->CreatePrincess();
MagicEffect* pUndoEffect = pPrincess->CreateMagicEffect("Kiss");
pHe = pUndoEffect->AffectTo(pHe); // Princess kisses the prince.
pPricess->Speaks("I love you");
pHe->Speaks("Will you marry me?"); // #3
Priest* pPriest = g_pActorFactory->CreatePriest();
pPriest->AnnounceMarriage(pHe, pPrincess); // Marriage between the princess and prince.
Life* pLifeProcess = g_pLifeFactory->CreateHappilyEverAfter();
pLifeProcess->Add(pHe);
pLifeProcess->Add(pPrincess);
#1에서 그(' pHe ')는 인간이다.
#2에서 그는 야수이다.
#3에서 그는 인간이다.
pHe 개체의 객체인 Actor는 프로그램의 흐름에 따라 다형성을 지니는 것을 알수 있다. 역활의 추상화Abstraction으로 만들어진 Actor 객체는 대부분의 역활을 지칭하는데 쓰일수 있으며, 다형성을 지니고 있다. 이것이 주는 이점중 하나는 은닉Encapsulation이다. 사용자는 실체가 무엇인지 몰라도 추상 객체를 통해 흐름을 진행시킬수 있다. 위와 같이 추상화를 통해 실현된 다형성은 상속을 기반으로 한것이다.
행위 기반 다형성(Behavior based polymorphism)
정적 타입 언어는 상속 관계를 통한 다형성을 구현하지만 다른 방식의 다형성도 존재한다. 행위만 동일하다면 관계에 상관없이 다형성을 지니게 되는 경우이다. 이 행위 기반 다형성은 동적 타입 언어와 정적 타입 언어에서 모두 나타나지만 차이점이 존재한다. 그 차이점은 언제 다형성을 지니는것인가 이다.
정적 타입 언어의 특징상 행위 기반 다형성을 컴파일 타임에 템플릿을 통해 지원한다. 동적 타입 언어는 형 변경의 제약이 없기 때문에 실행시간에 해당 다형성을 지원하고 있다. 동적 타입 언어에서 실현되는 행위 기반 다형성을 Duck-typing이라고 한다.
하지만 Duck-Typing 역시 약속된 행위를 객체가 지니고 있어야 다형성을 지닐수 있다. 상속을 배제하고 행위를 런타임중에 확인할수 있는 언어의 특징상 생긴 기능이라 볼수 있다. 이는 정적 언어와의 성능차이로 이어진다. 양쪽 타이핑 모두 일장일단을 지니고 있다.
C++에서 duck typing과 상속의 차이는 C++의 정적 타입 시스템 때문에 생긴다. 그리고 우리는 C++ 프로그램이 빠르게 동작하것으로 그 비용의 일부를 지불하고 있다.
- Andrew Koenig and Barbara E. Moo(AT&T)
이렇듯 여러 객체 지향 언어에서 다형성은 매우 중요한 추상화의 실제 장점으로 여겨지고 있다. 현제 객체지향 패러다임은 추상화를 매우 중요히 다루고 있다. 다형성은 모듈화와 재사용성에 큰 영향을 미치고 있으며 필수 테크닉이 되었다.
'개발 > 수필' 카테고리의 다른 글
| 객체 지향 소프트웨어 일주 - 5 (0) | 2008/05/18 |
|---|---|
| 객체 지향 소프트웨어 일주 - 4 (0) | 2008/05/08 |
| 객체 지향 소프트웨어 일주 - 3 (0) | 2008/03/28 |
| 테스트와 장인 - 8 (0) | 2008/03/19 |
| 객체 지향 소프트웨어 일주 - 2 (2) | 2008/03/15 |
| 테스트와 장인 - 7 (0) | 2008/03/12 |
작성자: yagur Rev : 2
Around Object Oriented Software - 2
2. 추상
추상화(Abstraction)
프로그래밍을 접해본사람은 '추상'이란 단어를 아마 수백 수천번은 보고, 듣고 했을것이다. 이 추상화Abstraction란 기술은 객체 지향 프로그래밍에서 중요한 여러 기반 기술 중 하나이다.
우리가 자주 하는 추상화는 말속에 들어있다. "이것" "저것"과 같이 대상을 지칭을 하거나, "과일" "동물"과 같이 공통점에 의해 개체Instance들을 객체Class로 분류 하거나, 숫자나 기호와 같이 약속된 의미를 두기도 한다. 이들은 모두 구체화되지 않고 그 자체만으로는 '개체화Instantiation가 불가' 하다는 공통점을 가지고 있다. 예를들어 "과일"이란 객체만으로 개체를 만들기엔 구체성이 부족하다. '내가 먹을 책상위의 바나나'란 개체로 과일을 개체화하려면 '노란 껍질에 모양이 휘고, 단맛을 지닌' 바나나라는 구체적인 객체가 필요하다.
대상을 지칭하는 추상의 개념은 컴퓨터 언어속에도 존재하고 있다. C++과 Java에선 this 그리고 Python에서는 self라는 키워드로 객체 자신을 지칭할때 사용한다. 혹은 '이미 개체화된 객체'를 사용자가 레퍼런싱 함으로서 대상을 지칭하는 용도로 쓰인다.
예를 들자면 아래와 같다.
ex> 자신 지칭
ex> 상위 분류로 지칭
피카소의 추상화抽象畵를 보면 개체가 가지는 특징(윤곽)을 나타내 추상화Abstraction한다.
원본 그림을 몰랐다면 연상이 안될수도 있다. 하지만 구체적인 것(추상화 대상)을 안다면 추상화된 결과물을 보고 무릎을 탁칠수도 있는일이다. 피카소의 그림은 공통 윤곽을 잡아 기하학적 추상화를 하고있는것으로 보인다. 컴퓨터 언어의 객체 추상화도 다를것이 없다. 서브 클래스들의 공통 분모를 찾아 슈퍼 클래스로 일반화 하기도 하며, 추상 객체인 슈퍼 클래스를 미리 정의 해놓고 하위 클래스로 서브클래싱하기도 한다. 이들을 상속 관계Inheritance에 있다고 한다. 그리고 상속은 객체 지향 프로그래밍의 기반 기술중 하나이다.
추상화는 단계적으로 이루어질수도 있다. 피카소가 소를 단계적으로 추상화하는것이 인상적이다.
화살표를 누르면 추상화가 되가는 과정을 볼수있다.
피카소의 추상화는 공통점을 모아 기하학적 예술로 승화시키고 있다. 이 예술의 가치중 하나는 작품을 보고 '서로 다른 의미를 부여'하는 것으로 볼수 있다. 달리 말하면 의미적 다형성Semantic Polymorphism을 지니게 되며, 다형성이 추상화의 중대한 가치가 되는것이다.
피카소가 마지막까지 추상화한 결과물을 보고 여러가지를 연상할수 있다. 주로 네발달린 짐승으로 뿔을 가진 동물을 연상할것이다. 그리고 추상화된 성기 부분을 관찰해낸 사람은 수컷을 연상하기도 할것이다. 추상화 결과물의 의미가 다형을 갖는 가치는 컴퓨터 언어도 비슷하다.
최종 결과물로 부터 추상화 단계를 역으로 볼수록 점점 그 형태가 구체적이 되서 의미적 다형성을 점점 잃어가는것을 볼수 있다. 컴퓨터 언어의 객체도 마찬가지이다. 추상화 계층의 깊이가 깊어질수록 객체의 다형성은 커지고 덜 구체적이 된다. 피카소의 그림은 기하학적인 추상화를 이루며 구체성을 줄이지만, 컴퓨터 언어의 객체는 행위Behavior와 구조Structure를 추상화 하며 구체성을 줄이는 점이 차이점이라 할수있다. 공통점은 이들이 최소한의 공통점으로 대상을 표현하려 함으로서 유용한 다형성을 지닌다는 점이다.
컴퓨터 언어의 관점에서봤을때 추상화는 중복 제거의 의미보다 다형성의 가치가 매우 크다고 생각하며, 추상의 개념은 이에 매우 밀접한 관계에 있다. 이 객체들의 추상화 품질은 객체 지향 소프트웨어의 내부 디자인 품질을 판단하는 좋은 기준이 될수 있다.
인터페이스(Interface)
객체가 극도로 추상화 되다보면 속성이나 구조는 사라지고 행위Behavior만이 남는다. 이때 이 순수 추상 객체(Pure Abstract Class)를 인터페이스라고 부른다. 실생활에서 우린 좋은 인터페이스의 예를 가지고 살고 있다.
Around Object Oriented Software - 2
2. 추상
컴퓨터 과학은 추상화의 과학이다. - A. Aho and J. Ullman
추상화(Abstraction)
프로그래밍을 접해본사람은 '추상'이란 단어를 아마 수백 수천번은 보고, 듣고 했을것이다. 이 추상화Abstraction란 기술은 객체 지향 프로그래밍에서 중요한 여러 기반 기술 중 하나이다.
우리가 자주 하는 추상화는 말속에 들어있다. "이것" "저것"과 같이 대상을 지칭을 하거나, "과일" "동물"과 같이 공통점에 의해 개체Instance들을 객체Class로 분류 하거나, 숫자나 기호와 같이 약속된 의미를 두기도 한다. 이들은 모두 구체화되지 않고 그 자체만으로는 '개체화Instantiation가 불가' 하다는 공통점을 가지고 있다. 예를들어 "과일"이란 객체만으로 개체를 만들기엔 구체성이 부족하다. '내가 먹을 책상위의 바나나'란 개체로 과일을 개체화하려면 '노란 껍질에 모양이 휘고, 단맛을 지닌' 바나나라는 구체적인 객체가 필요하다.
대상을 지칭하는 추상의 개념은 컴퓨터 언어속에도 존재하고 있다. C++과 Java에선 this 그리고 Python에서는 self라는 키워드로 객체 자신을 지칭할때 사용한다. 혹은 '이미 개체화된 객체'를 사용자가 레퍼런싱 함으로서 대상을 지칭하는 용도로 쓰인다.
예를 들자면 아래와 같다.
ex> 자신 지칭
Human::Human(bool gender)
{
this->gender = gender;
}
{
this->gender = gender;
}
ex> 상위 분류로 지칭
Human nancy;
Animal* she = &nancy;
she->Eats(hotDog);
Animal* she = &nancy;
she->Eats(hotDog);
피카소의 추상화抽象畵를 보면 개체가 가지는 특징(윤곽)을 나타내 추상화Abstraction한다.
원본 그림을 몰랐다면 연상이 안될수도 있다. 하지만 구체적인 것(추상화 대상)을 안다면 추상화된 결과물을 보고 무릎을 탁칠수도 있는일이다. 피카소의 그림은 공통 윤곽을 잡아 기하학적 추상화를 하고있는것으로 보인다. 컴퓨터 언어의 객체 추상화도 다를것이 없다. 서브 클래스들의 공통 분모를 찾아 슈퍼 클래스로 일반화 하기도 하며, 추상 객체인 슈퍼 클래스를 미리 정의 해놓고 하위 클래스로 서브클래싱하기도 한다. 이들을 상속 관계Inheritance에 있다고 한다. 그리고 상속은 객체 지향 프로그래밍의 기반 기술중 하나이다.
추상화는 단계적으로 이루어질수도 있다. 피카소가 소를 단계적으로 추상화하는것이 인상적이다.
피카소의 추상화는 공통점을 모아 기하학적 예술로 승화시키고 있다. 이 예술의 가치중 하나는 작품을 보고 '서로 다른 의미를 부여'하는 것으로 볼수 있다. 달리 말하면 의미적 다형성Semantic Polymorphism을 지니게 되며, 다형성이 추상화의 중대한 가치가 되는것이다.
피카소가 마지막까지 추상화한 결과물을 보고 여러가지를 연상할수 있다. 주로 네발달린 짐승으로 뿔을 가진 동물을 연상할것이다. 그리고 추상화된 성기 부분을 관찰해낸 사람은 수컷을 연상하기도 할것이다. 추상화 결과물의 의미가 다형을 갖는 가치는 컴퓨터 언어도 비슷하다.
최종 결과물로 부터 추상화 단계를 역으로 볼수록 점점 그 형태가 구체적이 되서 의미적 다형성을 점점 잃어가는것을 볼수 있다. 컴퓨터 언어의 객체도 마찬가지이다. 추상화 계층의 깊이가 깊어질수록 객체의 다형성은 커지고 덜 구체적이 된다. 피카소의 그림은 기하학적인 추상화를 이루며 구체성을 줄이지만, 컴퓨터 언어의 객체는 행위Behavior와 구조Structure를 추상화 하며 구체성을 줄이는 점이 차이점이라 할수있다. 공통점은 이들이 최소한의 공통점으로 대상을 표현하려 함으로서 유용한 다형성을 지닌다는 점이다.
컴퓨터 언어의 관점에서봤을때 추상화는 중복 제거의 의미보다 다형성의 가치가 매우 크다고 생각하며, 추상의 개념은 이에 매우 밀접한 관계에 있다. 이 객체들의 추상화 품질은 객체 지향 소프트웨어의 내부 디자인 품질을 판단하는 좋은 기준이 될수 있다.
인터페이스(Interface)
객체가 극도로 추상화 되다보면 속성이나 구조는 사라지고 행위Behavior만이 남는다. 이때 이 순수 추상 객체(Pure Abstract Class)를 인터페이스라고 부른다. 실생활에서 우린 좋은 인터페이스의 예를 가지고 살고 있다.
필립스사의 통합 리모콘
통합리모콘이 그 예이다. 이 필립스 리모콘은 1100여개의 기기를 하나의 리모콘으로 접근한다. 각 기기들의 적외선 코드를 모두 가지고 있다. 우리가 보고 있는 것은 인터페이스이며, 그것의 구현은 생각하지 않아도 된다. 단지 기기를 선택하기만 하면 같은 버튼으로 동일한 기능의 행동을 할수 있다. 예를 들어 Sony TV의 채널을 바꾸는것과 Samsung TV의 채널을 바꾸는것은 단지 '채널 변경 버튼'만으로 가능해지는 것이다. 변하지 않는 모든 기기의 일반적인 레이아웃을 모은 인터페이스라고 보면 된다. 그리고 각 기기별 리모콘 적외선 코드 구현은 내부에 감추어져 있다.
하단의 세가지 리모콘은 DVD-Player, TV, Amp 기기의 리모콘들이다. 통합리모콘이 없다면 기기들의 전원을 켜기 위해서 리모콘을 세가지 다 가지고 있어야 한다. 그리고 세가지 리모콘의 전원 버튼을 전부 한번씩 눌러야 전원을 킬수있다. 하지만 이제 공통의 기능 버튼을 모은 인터페이스인 통합 리모콘(상단의 필립스 리모콘)을 가지고 있으므로 나머지 리모콘은 옆에 보관하면 된다.
인터페이스에 접근하면 모든 기기에 접근할수 있게 되었다. 즉 필립스 리모콘은 다형성을 지니고 DVD 리모콘으로 되었다가, TV 리모콘도 되고, 앰프 리모콘도 되는것이다. 예외의 경우는 공통 인터페이스가 아닌 고유의 기능을 조작하기 원할 경우, 해당 기기의 번들 리모콘으로 접근해야한다(다운 캐스팅을 생각하면 된다).
번들 리모콘으로 접근하는것을 불편하게 생각해서, 다른 통합 리모콘은 수십개의 버튼을 지니고 있는 경우도 있다. 하지만 너무 많은 버튼때문에, 대부분의 버튼이 아무기능을 하지 않는 경우가 많다. 사용자는 어떤 버튼이 제대로 동작하는지 눌러보기 전까지 알수없다. 이것은 잘못된 추상화의 부작용이다.
하단의 세가지 리모콘은 DVD-Player, TV, Amp 기기의 리모콘들이다. 통합리모콘이 없다면 기기들의 전원을 켜기 위해서 리모콘을 세가지 다 가지고 있어야 한다. 그리고 세가지 리모콘의 전원 버튼을 전부 한번씩 눌러야 전원을 킬수있다. 하지만 이제 공통의 기능 버튼을 모은 인터페이스인 통합 리모콘(상단의 필립스 리모콘)을 가지고 있으므로 나머지 리모콘은 옆에 보관하면 된다.
인터페이스에 접근하면 모든 기기에 접근할수 있게 되었다. 즉 필립스 리모콘은 다형성을 지니고 DVD 리모콘으로 되었다가, TV 리모콘도 되고, 앰프 리모콘도 되는것이다. 예외의 경우는 공통 인터페이스가 아닌 고유의 기능을 조작하기 원할 경우, 해당 기기의 번들 리모콘으로 접근해야한다(다운 캐스팅을 생각하면 된다).
번들 리모콘으로 접근하는것을 불편하게 생각해서, 다른 통합 리모콘은 수십개의 버튼을 지니고 있는 경우도 있다. 하지만 너무 많은 버튼때문에, 대부분의 버튼이 아무기능을 하지 않는 경우가 많다. 사용자는 어떤 버튼이 제대로 동작하는지 눌러보기 전까지 알수없다. 이것은 잘못된 추상화의 부작용이다.
'개발 > 수필' 카테고리의 다른 글
| 객체 지향 소프트웨어 일주 - 3 (0) | 2008/03/28 |
|---|---|
| 테스트와 장인 - 8 (0) | 2008/03/19 |
| 객체 지향 소프트웨어 일주 - 2 (2) | 2008/03/15 |
| 테스트와 장인 - 7 (0) | 2008/03/12 |
| 객체 지향 소프트웨어 일주 - 1 (0) | 2008/03/11 |
| 테스트와 장인 - 6 (2) | 2008/02/25 |
작성자: yagur Rev : 2
Around Object Oriented Software - 1
1. 객체
내 생각은 추상의 세계에서 오고 내가 하는 말은 연관성의 세계로부터 오기 때문에 나는 오류를 범하지 않고는 결코 얘기를 할 수 가 없다.
- 칼릴 지브란
근 십수년간 Object Oriented Programming의 패러다임은 바이러스와 같이 퍼져나갔다. 그리스 철학자 플라톤의 이데아론의 영향을 받은 패러다임은 사람들의 입담과 종이위의 글, 또는 소프트웨어의 코드란 실체 통해 그 철학을 전염시켜 나갔다. 그리고 지금 그것의 위치는 가장 널리 보급된 패러다임이 되었다.
현실 세계에 존재하는것은 객체Class의 개체Instance일 뿐이다. - 플라톤
재미있는 글귀이다. 객체 지향 프로그래밍을 하던 사람에게 매우 친숙한 단어들이 보인다. 객체Class 그리고 인스턴스Instance가 바로 그것들이다. 칼릴의 격언처럼 우린 생각 영역에 있는 추상의 것들을 프로그래밍의 객체Class로 정의해 코드란 것으로 개체화Instantiation시킨다. 그리고 우리는 코드로 개체화된 컴퓨터 언어 영역의 객체를 메모리의 세계에 개체화 한다.
카릴의 격언중 '말'이란 부분을 컴퓨터 언어(C++, Java등)로 해석하면 꾀 그럴사 하다. 우리가 객체 지향 프로그래밍을 하며 가장 많이 하는 것이 무엇이 있을까? 바로 연관 관계를 디자인하거나, 그것들을 프로그램으로 실체화 하는 것이다. 이 연관 관계를 구체화한것들은 OOP에 매우 친숙한 객체 관계Class Relationship들이다.
연관 관계를 위와 같은 모델링 언어로 표현하기도 한다. 상속Inheritance, 합성Composition, 집합Aggregation, 연관Assocation, 위임Delegation등의 관계는 경험자에게 친숙한 관계들일것이다. '직선과 화살표 그리고 << >>의 스테레오 타입'으로 표기한것은 '결합관계를 스테레오 타입'으로 나타내는 방언으로 봐도 무방하다.
우리가 실체화한 객체는 추상의 세계로부터 나왔다. 그리고 추상적 개념을 띄고 소프트웨어의 내부 구성원인 객체로서 우리의 창조물이 된다. 우리가 말(Computer Language)을 할때 추상적인 것들 사이의 연관 관계를 정의함으로서 우린 오류를 범할수 밖에 없다. 하지만 연관성의 오류가 소프트웨어의 동작을 멈추게 하는것은 아니며, 소프트웨어에 나쁜 냄새(Refactoring의 냄새 혹은 OOD의 나쁜 설계)를 풍기게 할뿐이다.
우린가 무엇으로 객체를 식별하는지, 그 기준을 생각해 보는것도 나쁘지 않다.
Plato and cats
우린 무엇으로 위의 그림에 보이는 개체들을 고양이라고 구분짖고 있는것일까. 우리가 보고있는것들은 나이가 다르고, 생명체가 아닐수도 있고, 신체 특징도 다르며, 추상적이거나, 심지어 그저 모형이기도 하다. 하지만 우리는 고양이라고 저들을 구분 짖는다.
우린 고양이란 개개의 개체Instance들의 특성을 종합하고, 그것들을 일반화해 '보편적인 고양이'라고 인식하고있다. 즉 이 '고양이'란 단어는 공간과 시간의 영향을 받는것이 아닌, 추상적인 개념으로서 객체Class 혹은 플라톤의 이데아現象인 것이다.
소프트웨어는 객체를 컴퓨터 언어로 표현해야 하기 때문에 좀더 구체적이 되어야 한다. 행위와 속성을 정의해야하며 그것을 구체화해야한다. 객체의 멤버들은 선언시 실체가 없는 추상적 멤버가 될수 있다. OOP에서 추상 멤버Abstract Member를 지닌 객체를 추상 객체Abstract Class라 부르며, 순수 추상 객체Pure abstract class는 인터페이스Interface라 부르기도 한다.
윗 단락에서 굉장히 많이 언급된 '추상'이란 단어가 있다. 이는 OOP를 하기 위해 상당히 중요한 개념이며 다형성Polymorphism과도 맞물려 있다.
우린 무엇으로 위의 그림에 보이는 개체들을 고양이라고 구분짖고 있는것일까. 우리가 보고있는것들은 나이가 다르고, 생명체가 아닐수도 있고, 신체 특징도 다르며, 추상적이거나, 심지어 그저 모형이기도 하다. 하지만 우리는 고양이라고 저들을 구분 짖는다.
우린 고양이란 개개의 개체Instance들의 특성을 종합하고, 그것들을 일반화해 '보편적인 고양이'라고 인식하고있다. 즉 이 '고양이'란 단어는 공간과 시간의 영향을 받는것이 아닌, 추상적인 개념으로서 객체Class 혹은 플라톤의 이데아現象인 것이다.
소프트웨어는 객체를 컴퓨터 언어로 표현해야 하기 때문에 좀더 구체적이 되어야 한다. 행위와 속성을 정의해야하며 그것을 구체화해야한다. 객체의 멤버들은 선언시 실체가 없는 추상적 멤버가 될수 있다. OOP에서 추상 멤버Abstract Member를 지닌 객체를 추상 객체Abstract Class라 부르며, 순수 추상 객체Pure abstract class는 인터페이스Interface라 부르기도 한다.
윗 단락에서 굉장히 많이 언급된 '추상'이란 단어가 있다. 이는 OOP를 하기 위해 상당히 중요한 개념이며 다형성Polymorphism과도 맞물려 있다.
'개발 > 수필' 카테고리의 다른 글
| 객체 지향 소프트웨어 일주 - 2 (2) | 2008/03/15 |
|---|---|
| 테스트와 장인 - 7 (0) | 2008/03/12 |
| 객체 지향 소프트웨어 일주 - 1 (0) | 2008/03/11 |
| 테스트와 장인 - 6 (2) | 2008/02/25 |
| 테스트와 장인 - 5 (0) | 2008/02/22 |
| 테스트와 장인 - 4 (2) | 2008/02/21 |








Recent Comment