Archive for the ‘OOP와 DP’ Category.

격리(Isolation)

프로그램의 규모가 커지면 커질수록 실패할 확률이 높아집니다.
수많은 서브모듈이 복잡하게 통신하면서 개발자가 미쳐 생각하지 못했던 경우의 수가 발생하여 예외나 오류가 발생하여 전체적인 시스템 다운으로 이어집니다.

이는 개발 시에도 이 문제는 그대로 들어나는데, a클래스를 수정하면 그 여파가 a클래스의 자식, a클래스를 소유한 모든 객체, 인자로 a클래스를 받는 녀석 등으로 번집니다. 또한 여기서 끝나지 않고 b클래스가 a클래스를 소유했기 때문에 다시 b클래스의 자식, b클래스를 소유한 객체 등으로 끝없이 확장되어 번집니다.

일반적으로 이러한 문제를 회귀테스트의 문제라고 합니다.

회귀테스트란 어떤 내용을 수정하면 그 여파로 모든 내용을 처음부터 다시 검토해야하는 현상을 말합니다.

이 악몽에서 벗어나려면 어떻게 해야할까요?

TDD(테스트 주도 개발)

요즘 세상사람들이 말하는 테스트주도개발방법론이란게 있습니다. 어떠한 클래스를 개발하면 그 클래스나 메쏘드에 대해서 테스트도 같이 만들어서 테스트를 걸도록 하는 방법론입니다. 이는 듣는 순간 단순해보이지만 사실은 전혀 단순하지 않습니다.

1. 어떠한 클래스를 작성해도 테스트가 작성되기 되기 때문에 회귀테스트가 생기는지 아닌지를 즉시 알 수 있습니다.
2. 따라서 회귀테스트 문제가 생기지 않는 클래스만 작성해가기 때문에 전체적으로도 회귀테스트가 생기지 않고
3. 또한 어떤 모듈을 고쳤을때 이 문제가 시스템에 회귀테스트를 일으킬지 아닐지도 즉시 알 수 있습니다.

Isolation(격리)

사실 TDD는 실천적인 내용입니다. 즉 설계 상의 기술이나 개념이 아니라 코딩시 실천하면 좋은 실천강령같은 것이죠(물론 애자일개발론으로 연결하면 설계상의 개념으로 확대됩니다. 저도 개인적으로 켄트백팬입니다)
하지만 격리라는건 개발시에 항상 고려해야하는 개념같은 것으로 중복코드방지나, 단일책임의 원칙처럼 항상 근본적으로 고려해야하는 부분입니다.
격리라는건 간단히 말해 절대로 격리시킨 부분에서는 문제가 생기지 않는다는 확신입니다. 어떻게 그렇게 될까요?

가장 기본적으로는 런타임에 결정되는 내용을 없애면 가능합니다. 즉 아래와 같은 예를 볼까요?

function test($val:*):void{}

function test($val:Number):void{}

function test($val:int):void{}

function test($val:uint):void{}

function test($val:CintOverZero):void{}

test의 내용이 양수인 정수를 기반으로 개발되었다고 했을때 격리수준은 위에서 아래수준으로 높아집니다. test의 인자를 이미 양수임을 확신시켜주는 전용클래스(CintOverZero)로 받는 마지막 샘플은 격리의 전형적인 예를 보여줍니다. 사람보단 컴파일러가 확인하게 하고 그렇게 통과된건 컴파일러는 믿는 범위내에선 문제가 안생긴다고 확신할 수 있습니다.
따라서 test함수의 내부 로직이 잘못되어도 그건 인자로 음수나, 0이나 소수가 들어와서가 아니다라고 문제의 범위를 격리할 수 있습니다.

Command Pattern – 객체 통신을 추상화하자

다른 DP와 달리 이번에는 심화학습이 아니라 Command DP가 뭔지를 이해하는 것 자체에 초점을 맞춰보겠습니다. Command DP는는 UML이나 정의에서는 그 특성을 알아차리기 힘듭니다. 또한 많은 분들이 Command DP의 부산물인 history나 undo가 본질인 줄 착각하시는 경우도 많습니다. 이 패턴은 DP중 가장 복잡하고 난해한 패턴이면서 동시에 가장 중요한 패턴입니다. 다른 패턴은 특정 Design에 관여하는데 비해 Command DP는 OOP설계 그 자체에 관여합니다. 이제 순차적으로 Command DP를 이루는 개념을 차근차근 풀어보죠.

Continue reading ‘Command Pattern – 객체 통신을 추상화하자’ »

Polymorphism #2 – Override의 물리구조

다형성을 이루는 요소 중 어마무지 중요한 부분은 Override 입니다. override 란 영어의 의미는 같은 사항에 대해 우선시 하는 것을 뜻합니다. 예를 들어 같은 사안에 대해 여러 법령이 다른 지시를 하는 경우 법령의 우선 순위는 헌법 → 법률 → 령 → 규칙 → 조례 → 규칙 → 고시 → 예규 순으로 정해집니다. 그래서 법원 결정을 거부하고 싶을 때, 헌법재판소에 가져가서 법률 자체가 잘못되었다라고 주장하는 것이죠. 바로 이 때 헌법이 법률을 override 했다고 할 수 있습니다.

Continue reading ‘Polymorphism #2 – Override의 물리구조’ »

Polymorphism #1 – 다형성의 물리구조

OOP 언어의 대표적인 기술인 다형성을 좀 더 깊게 3회차에 걸쳐 생각해 보겠습니다.
다형성의 원 뜻은 하나의 대표되는 모양이 여러 개의 파생적인 다른 형태를 갖는 경우를 말합니다. 광물의 결정체나 생물학, 유전학등에서 쓰이는 용어입니다. 예를 들어 같은 인간이지만 혈액형이 A,B,O로 존재한다는 뜻이죠. 이 때 인간은 혈액형이 다형적이다라고 말하게 됩니다.

OOP엔진의 상속구현 비밀

untitled-1위에서 설명한 다형성에 대한 일반적인 의미가 개발자들에겐 혼동을 일으키는 부분입니다. 개발 상에서 다형성은 전혀 위와 같은 방식으로 동작하지 않습니다. 먼저 다형성 구조를 파악하기 위해 작은 OOP엔진의 비밀을 알려드리겠습니다. 그림에서 처럼 3단계 상속구조를 갖는 Child 클래스를 new를 통해 생성하는 경우 메모리에는 Child만 heap메모리에 생성되는게 아닙니다. 사실은 상속구조 안에 있는 모든 클래스의 인스턴스가 메모리에 생성됩니다.
문제는 변수 A가 어떤 녀석을 참조하는가입니다.

Continue reading ‘Polymorphism #1 – 다형성의 물리구조’ »

Factory를 통해 new를 제거하기

OOP언어를 메모리사용 범주에서 분류하면 동적메모리할당 기술로 분류할 수 있습니다. 미리 사용할 메모리를 정해두지 않고 실행시에 메모리를 확보하여 사용하는 기술을 뜻합니다. 이에 반해 정적 메모리할당 기술은 프로그램이 실행에서 종료시까지 사용할 모든 메모리를 미리 확보한 상태로 실행되고, 실행 중에는 호출 등을 위한 스택메모리만 일부 사용하게 합니다.

OOP언어가 런타임메모리 할당을 위해 사용하는 키워드는 new 입니다.

new는 문제가 매우 많은 키워드입니다. new가 런타임메모리할당을 한다는 그 사실 자체가 문제가 많다고 봐야겠죠. 따라서 이러한 new키워드를 추상층으로 은닉하고 안정적인 방법을 통해 사용할 필요가 있습니다. DP에서는 new를 은닉하는 다양한 패턴이 존재합니다. 유명한 싱글톤 패턴을 비롯하여 빌더, 프로토타입, 플라이웨이트 등이 있습니다. 하지만 그중 가장 유명하면서도 동시에 오해가 많은 패턴은 바로 팩토리 패턴입니다.
factory란 영어 단어의 뜻은 어떤 기계나 획일적인 방법으로 대량 생산되는 공장을 뜻합니다. 그냥 공장이 아니라 내부에 저 정도의 의미를 내포하죠. 즉 팩토리패턴을 사용할 경우가 언제인가에 대해 생각해보면 똑같은 방식으로 new를 자주 해야하는 객체에 적용할 때라는 것을 이름으로부터 알 수 있습니다. 만약 그 객체가 new를 한번만 하거나 획일적인 방법으로 new를 하지 않는다면 팩토리는 사실상 무용지물입니다. 반드시 어떠한 유형으로 획일적인 new를 할 때, 팩토리 패턴의 진가가 발휘된다 하겠습니다.
Continue reading ‘Factory를 통해 new를 제거하기’ »