서브버전으로 각종 프로젝트를 진행하다보면 여러가지의 오픈소스들을 활용해야 할 때가 있는데 그럴때 외부 저장소에 있는 오픈소스 프로젝트를 현재 작업하고 있는 저장소에 포함시키면 상당히 효율적으로 외부라이브러리를 관리할 수 있다.
다시말해 진행하려는 프로젝트 저장소를 생성하고 그 저장소에 Papervision 이라든지 Away3D 와 같은 외부 저장소의 소스를 연결할 수 있다는 의미이다. 이렇게 되면 현재 저장소에 외부 오픈소스가 귀속되어 실제 버전관리가 이루어지지 않는 맹점을 해결할 수 있다.
서브버전 디렉토리 속성중에 svn:externals 이라는 것이 있는데 이것을 이용하면 현재 저장소에 다른 저장소의 내용을 포함시킬 수가 있다.
위와 같이 외부저장소에서 가져온 라이브러리는 독립적인 버전관리가 이루어지며 한 저장소 안에서 여러개의 서로다른 저장소의 라이브러리를 가져와 연결할 수 있다.
아래 설명은 eclipse 기반의 서브버전 플러그인인 Subclipse 를 작업기준으로 한다.
우선 SVN 프로젝트를 생성하고 속성을 설정하고자 하는 폴더에서 마우스 우클릭을 하여
아래와 같이 Team –> Set Property… 메뉴를 클릭한다.
그러면 다음과 같은 svn 속성 설정창이 뜨는데 Property name 으로 svn:externals 을 선택하고 Property content (value)값을 다음과 같은 정의로 입력해준다.
Property content (value) 정의는 크게 두부분으로 구성되는데 처음부분은 외부저장소 파일이 저장될 프로젝트의 디렉토리 이름이고 두번째는 외부저장소의 URL 로 이루어진다. 그리고 외부저장소에서 원하는 리비전번호의 파일을 제한적으로 연결할 수 있는데 이는 외부저장소의 뜻하지 않은 변경사항에 현재 적용하고 있는 프로젝트와의 충돌이나 오류를 막아준다. 이는 옵션사항이니 항상 최신버전을 가져오려면 생략하면 된다. 또한 여러개의 저장소를 가져올 경우 위와 같은 형식으로 각각의 다른 라인으로 작성하면 현재 프로젝트에서 여러개의 서로다른 외부저장소를 연결하여 사용할 수 있다.
입력이 끝났으면 업데이트를 실행해보자. 그러면 외부저장소의 파일들을 프로젝트내로 가져올것이다. 그리고 변경사항에 대해 커밋을 한다.
여기서 중요한 사실은, 커밋한다고 해서 현재 프로젝트에서 업데이트 되었던 외부저장소의 파일들이 저장소에 모두 커밋되는것이 아니다. 저장소를 확인해보면 알 수 있듯이 서버상에는 svn 속성값만 변경되었을 뿐 어떠한 외부저장소의 폴더가 반영된 것을 볼 수 없을 것이다.
또한, 현재 프로젝트에서 외부저장소를 포함한 모든 작업파일에 대한 변경사항을 커밋할 때 만약 외부 저장소의 파일을 직접 변경했다고 하더라도 자동으로 외부저장소의 파일을 커밋하지 않는다는 것이다. 외부저장소의 변경을 커밋하고 싶으면 해당 외부디렉토리로 직접가서 커밋을 직접해줘야한다.
flash에서 구현되는 대부분의 사용자와의 Interaction 은 버튼을 통해 이루어 진다.
즉, 버튼을 통해 이벤트가 발생되고 그것을 통해 필요한 반응들을 처리하게 된다.
일반적으로 flash 에 버튼을 설정할때는 아래와 같이 직접 이벤트 핸들러 함수를 등록하여 사용한다.
button.onRelease=function(){ //code….}
하지만 이런 방법은 무비클립이나 버튼 자체에 코드가 종속되어 버리게 되어, 제어해야할 버튼이 많을 경우 이곳저곳에 이벤트 핸들러 함수를 작성해야하므로 체계적인 이벤트 플로우를 관리하기 위해서 좀 부족한 감이 든다.
또한 버튼은 단독으로 한개가 있는것보다는 여러개의 버튼이 컨텐츠의 네비게이션으로서 작용하는 경우가 대부분이다. 따라서, 버튼을 릴리즈 했을 경우 활성/비활성되는 부분도 고려해야하는 문제가 있다.
여기에서 소개하는 방법은 Design pattern 중에 Template method 패턴을 활용하여 버튼 로직을 구현하는 부분을 구현하고 실제적인 기능을 담당하는 부분은 추상클래스의 상속을 통해 구현하는 방법을 사용하였다.
기본적인 개념은 추상클래스 타입을 확장하여 각각의 구상클래스로서 버튼클래스를 제작한다.
그리고 추상클래스 타입을 이용해 작성된 ButtonManager class 에 버튼 클래스를 등록한다.
여기서 ButtonManager class 는 버튼 등록, 활성/비활성 체크 같은 전체적인 버튼을 관리하는 역할을 담당하게 된다.
(* 이곳에 사용된 startEvent 메소드는 기본적으로 제공하는 Dispatcher 클래스의 dispatchEvent 메소드를 재정의 한것이다. )
<AbstractSimpleButton Class> 버튼 추상 클래스로써 생성하는 모든 버튼에 공통적으로 상속되는 클래스이다.
이곳에 선언된 추상메소드를 구상클래스에서 오버라이드(override)하여 실제적인 기능을 구현한다.
import com.dstrict.UB.events.Dispatcher;
import com.dstrict.UB.events.Delegate;
class com.dstrict.UB.ui.button.AbstractSimpleButtonextends Dispatcher {privatevar _mc:MovieClip;
publicfunction setController(inMc : MovieClip) : Void{
_mc=inMc;
}publicfunction getController() : MovieClip{return _mc;
}/**---------------------------------------------------------------------------
* Constructor function
* @param inMc controller movieClip
*---------------------------------------------------------------------------*/publicfunction AbstractSimpleButton(inMc:MovieClip){
setController(inMc);
setButton();
}publicfunction setButton():Void{
getController().onRollOver=Delegate.create(this,onRollOver);
getController().onRollOut=Delegate.create(this,onRollOut);
getController().onPress=Delegate.create(this,onPress);
getController().onRelease=Delegate.create(this,onRelease);
getController().onReleaseOutside=Delegate.create(this,onReleaseOutside);
}publicfunctiononRollOver() : Void{// override in sub-class}publicfunctiononRollOut() : Void{// override in sub-class}publicfunctiononPress() : Void{// override in sub-class}publicfunctiononRelease() : Void{// override in sub-class}publicfunctiononReleaseOutside() : Void{// override in sub-class}publicfunctionenabled(mode:Boolean):Void{// override in sub-class}}
<ButtonManager Class>
추상클래스인 AbstractSimpleButton 클래스 타입을 이용하여 버튼의 등록및 이벤트 위임을 처리하고 있다.
어떠한 구상클래스(concrete class)도 사용되지 않았기 때문에 실제 구현과 완전히 분리되어 코드를 처리할 수 있다.
실제 버튼 기능을 구현하기 위한 구상 클래스. 단순히 버튼 롤오버 반응과 릴리즈시 활성체크를 구현하였다.
생성하려는 버튼의 기능에 따라 이 클래스는 다르게 구성된다. 물론 추상메소드로서 작용하는
AbstractSimpleButton 클래스의 onRollOver,onRollOut,onRelease,onReleaseOutside, enabled
는 오버라이드(override) 하여 구현하여야 한다.
Template method 패턴은 디자인 패턴 중에서도 가장 기본이 되는 패턴중에 하나다.
템플릿이란 단어에서 유추할 수 있듯이 어떤 일정한 틀을 기본으로 클래스를 구성하는 방식이다.
추상클래스(Abstract class) 에 정의되어있는 Abstract method 를 기반으로 알고리즘을 구성하는 template method 를 만들어 동작시키는 것이다. 다시말해 알고리즘의 캡슐화(encapsulation) 라고 할수 있다.
추상클래스(Abstract class) 에서는 단지 알고리즘만 기술하는 역할만 한다. 실제 구현은 서브클래스 (Concrete class) 에서 기술한다. 따라서 Template method 를 이용하면 알고리즘의 구조는 유지하면서 서브클래스에서 추상메소드를 오버라이드하여 재정의 할 수 있다.
서브클래스에서 행동을 지정할 수 있게 하면서도 코드의 재사용이 가능한 특징으로 Template method 패턴은 framework 를 제작하는데 자주 등장한다.
플래시에서는 abstract 키워드가 지원되지 않지만 개념상 큰차이없이 패턴을 사용할 수 있다.
위 sample 은 버튼을 구성하는 간단한 클래스이다.
플래시에서 Interaction 을 구현할때 거의 대부분버튼을 구현하여 접근한다. 일반적으로 버튼 액션을 구현하려면 버튼 인스턴스나 무비클립 인스턴스를 통해 버튼 이벤트를 주어서 사용하지만 그럴경우 제어해야할 버튼이 많아지면 코드길이가 늘어날 뿐더러 코드 유연성이 떨어지게 된다.
실제 버튼을 구현하려면 추상클래스를 확장하여 추상메소드를 구현하기만 하면 된다.
추상클래스의 추상메소드의 정의는 개발자가 신중히 결정해서 정해야한다. 추상메소드가 너무 많게 되면 서브클래스에서 구현해야할 코드가 많아져 불편한점이 있을 수 있다. 반대로 너무 추상메소드 자체를 큰 덩어리로 나누게되면 유연성을 떨어뜨리게 된다.
상속가능한 메소드 구현(즉, 실제본체가 있는 메소드)은 상위 클래스에 집어넣기에 딱 좋다.
하지만 추상 클래스에서는 하위 클래스에서 유용하게 써먹을 수 있는 일반적인 코드를 전혀 만들 수 없기 때문에 메소드를 구현한다는 것이 아예 말이 안 되는 경우가 종종 있다. 추상메소드를 만드는 이유는 실제 메소드 코드를 전혀 집어넣지는 않더라도 일련의 하위클래스를 위한 규약(protocol)의 일부를 정의하기 위한 것이다.
그렇다면 장점은?…….
OOP의 핵심이라 할 수 있는 다형성(polymorphism)이다.
상위클래스 유형을 메소드의 인자나 리턴유형 또는 배열유형으로 쓸 수 있게 만드는 능력이 필요하다. 그래야만 새로운 유형을 처리하기 위한 새로운 메소드를 추가하거나 기존의 메소드를 고칠 필요없이 프로그램에 새로운 하위클래스 유형을 추가할 수 있기 때문이다.
플래시에서는 추상클래스를 지원하지는 않는다.
하지만 추상클래스 보다 더 추상적인 개념인 인터페이스(interface)가 존재한다. 물론 자바에서 사용되는 인터페이스와 똑같다.
앞으로 사용될 AS3.0 에서도 추상클래스는 지원하지 않지만 인터페이스 만으로도 비슷한 역할을 구현할 수 있을 것이다.
익스트림 프로그래밍(XP, eXtream Programming)이라는 방법은 최근의 소프트웨어 개발 방법론 분야에 새로 등장했다. 많은 사람들이 “프로그래머들이 정말 원하는 방법” 이라고 하는 XP는 90년대말에 등장했으면 두명으로 구성된 조그만 회사에서 포드 자동차에 이르기까지 다양한 규모의 회사에서 쓰이고 있다.
XP의 가장 큰 장점은 막판에 스펙에 변경되는 일이 있어도 고객이 원하는 것을 고객이 원하는 기한에 맞춰서 제공할 수 있다는 점이다.
XP는 서로 조화롭게 쓸 수 있도록 계획된 일련의 규칙이 있다. 물론, 그 가운데 일부만을 채택하고 있는 프로그래머도 많이 있긴 하다.
규칙에는 다음과 같은 것들이 있다.
- 조금씩, 하지만 자주 발표한다.
- 사이클을 반복해서 돌리면서 개발한다.
- 스펙에 없는 것은 절대 집어넣지 않는다.
- 테스트 코드를 먼저 만든다.
- 야근은 하지 마라. 항상 정규일과 시간에만 작업한다.
- 기회가 생기는 족족 언제 어디서든 코드를 개선한다.
- 모든 테스트를 통과하기 전에는 어떤것도 발표하지 않는다.
- 조금씩 발표하는 것을 기반으로 하여 현실적인 작업 계획을 만든다.
- 모든일을 단순하게 처리한다.
- 두 명씩 팀을 편성하고 모든 사람이 대부분의 코드를 알 수 있도록 돌아가면서 작업한다.
구조 패턴은 복잡한 구조를 이루는 클래스들을 어떻게 하면 개발하기에도 쉽고 보기에도 좋은 형태를 만들어 줄 것인가에 대한 답을 제시해 준다. 구조 패턴을 이용해서 시스템을 구축하면 새로운 기능을 가진 복합객체를 효과적으로 작성할 수 있다.
구조패턴에는
1. Facade 패턴
2. Adapter 패턴
3. Bridge 패턴
4. Composite 패턴
5. Decorator 패턴
6. Flyweight 패턴
7. Proxy 패턴
1. Facade 패턴
일반적으로 프로젝트를 수행할 때, 하나의 목적을 위해 여러개의 오브젝트들이 유기적으로 연결되게 된다. 이때, 오브젝트들을 묶을 수 있다고 판단이되면, 별도의 오브젝트를 새롭게 만들어 사용자들에게 새롭게 만든 오브젝트의 인터페이스를 이용하여 다른 오브젝까지 모두 사용할 수 있게 만들수 있다. 이처럼 대표 인터페이스를 이용하여 다른 여러 오브젝트를 사용할 수 있게 만드는 패턴이 바로 Facade 패턴이다.
2. Adapter 패턴
어댑터 패턴은 기존에 존재하는 클래스를 직접 변경하지 않고도 원하는 형태의 인터페이스를 가지게 만드는데, 효과적으로 사용할 수 있는 패턴이다. 외부에서 돈을 주고 구입한 클래스나 다른 부서가 개발한 클래스들이 적용하고자 하는 시스템에 적합하지 않을 경우, 시스템을 변경하지 않고도 이들 클래스를 활용할 수 있는 방법을 제공한다.
3. Bridge 패턴
브리지 패턴은 어댑터 패턴과 팩토리 패턴을 합친 것 같은 패턴으로 이들의 장점을 시스템에 적용한 패턴이다. 이를 간단히 설명하면 동일한 조상을 가진 객체들은 팩토리 패턴을 이용하여, 객체의 생성을 추상화해서 객체들을 사용하는 모듈과 이들을 분리시키지만, 동일한 조상을 가지지 않았거나 동일한 인터페이스를 소유하지 않은 객체는 팩토리 패턴을 적용하기 어렵다. 브리지 패턴은 어댑터 패턴을 이용하여 같은 조상을 가지지 않은 시스템구조에 팩토리 패턴을 적용할 수 있도록 만들어 주는 패턴이다.
4. Composite 패턴
객체집단을 다루는데 유용한 컴포짓패턴은, 시스템이 집합속에 포함될 객체와 집합을 가지고 있는 객체, 이들 모두가 자기 사진과 동일한 타입(메소드와 데이터)의 객체리스트를 가지게 한다. 그래서 객체리스트에 객체를 삽입하거나 삭제하는 방법으로, 객체집단을 기존의 집단에 신속하게 벗붙이고 삭제하는 작업을 수행할 수 있게 만든다. 그리고 객체집단의 어느 특정한 부분에 명령을 전달하면 특정 부위의 객체집단 모두가 그 명령을 수행하게 만드는 구조를 가진다.
5. Decorator 패턴
데코레이터 패턴은 장식자라는 이름에서도 알 수 있듯이, 특정 객체를 원하는 모양(기능)으로 장식시켜주는 객체를 만들어 준다. 즉, 장식 시켜주는 객체들과 장식 받을 객체들을 만든 뒤, 이들을 이용하여 장식 바은 객체가 원하는 모양이되도록 만들어 주는 것이다. 이대, 기존의 객체(장식받을 객체)를 활용하고 있던 모듈은 장식이 이루어지는 것과 무관하게 작동하도록 한다.
6. Flyweight 패턴
Flyweight 패턴은 시스템 속에 유사한 클래스나 객체의 난립을 줄여주는 역할을 한다. Flyweight 패턴은 데이터를 관리하고 있다가 시스템이 원하는 데이터가 있을때 이를 객체로 만들어 준다. 객체를 만들 때는 데이터를 객체로 변경시켜주는 팩토리에 데이터를 넘겨주고, 팩토리는 이를 필요한 형태의 객체로 만들어서 반환하게 된다.
7. Proxy 패턴
프록시 패턴은 프록시가 대리인이라는 의미를 가지고 있는 것처럼, 원하는 작업을 대신해서 처리하도록 만드는 패턴이다. 시스템이 작업을 처리하는 가운데, 시스템의 처리과정을 효율적으로 만들기 위해 처리를 분산시킬 필요가 있다. 이렇게 처리과정의 일부부능ㄹ 다른 프로세서에 대행시키고자 할 때 프록시 패턴을 적용하면, 시스템의 구조를 어렵지 않게 효율적으로 변경시킬 수 있다.
이법칙은 한 객체가 제공하는 메서드에 접근하기 위해 또 다른 객체들을 통하는 것을 허용하지 않는다.
디미터 함수 법칙 – 모든 메서드는 다음에 해당하는 메서드만을 호출해야 한다.
class Demeter {private:
A *a;
Int func();public://...void example(B& b);}void Demeter :: example(B& b){
C c;
Int f= func();//----------- 자신
b.invert();//--------------메서드로 넘어온 인자
a=new A();
a->setActive();//---------자신이 생성한 객체
c.print();//---------------직접 포함하고 있는 객체}
참고 디미터 프로젝트 – 적응적 프로그래밍(Adaptive programming) 을 이용해서 소프트웨어를 유지보수하기 쉽고 진화하기도 쉽게 만드는데 초점을 두는 연구
Recent Comments