Design Pattern for Smalltalk – interpreter

t_Dpsc_chapter05_Interpreter_01

interpreter 패턴은 작은 규모의 language에 대한 규칙이 있고, 그 규칙으로 만들어진 구문을 해석하는 해석기를 만드는 경우에 사용되는 패턴이다.

일반적으로 잘 쓰일일은 없는 패턴인데다가 해석의 속도에 대한 효율성을 생각한다면 현실적으로 사용하기에는 권하기 힘든 패턴이기도 하다. 하지만 규칙이 복잡하지 않은 경우 (♣Configuration♣ 파일 형식이나 프로그램의 내장 script 언어 등) 라면 충분히 사용 가능하며, 그 구조상 문법규칙이 확장이 필요한 경우에도 많은 수고를 들이지 않고 필요한 만큼 해석기의 변경도 가능하다.

새로운 문법규칙을 만들려 하는경우, 제대로 된 파서를 처음부터 만든다면 문법규칙이 완성되기도 전에 파서를 수시로 수정해야 하는 상황이 될 것이다. 이 경우 Interpreter 패턴을 사용해서 테스트 단계용 파서를 만든다면, 문법규칙을 일정 수준으로 완성할 때 까지 문법과 파서를 병행해서 관리하는 개발방법을 진행할 수 있다.

Interpreter 패턴에서는 상위클래스인 추상클래스에서 메서드의 인터페이스를 정의하고 하위클래스에서 해석에 사용할 토큰을 각각 별도로 정의하고 해석을 진행한다. 토큰의 요소들은 하위클래스 내부에서 배열 (또는 딕셔너리 또는 Collection) 로 관리되기도 한다.

Interpreter 패턴의 목적은 규칙을 가진 문자열의 해석을 위한 해석기를 구성하는 구조 자체라는것을 잊지 않는다면 패턴의 무분별한 확장을 막는데에 도움이 될 것이다.

Design Pattern for Smalltalk – Command

t_Dpsc_chapter05_Command_01

Command 패턴은 어떠한 작동을 시작과 분배, 작업부로 나눔으로서 각 부분에 대한 유지보수와 느슨한 연결을 통한 재사용성을 높이는데 그 목적이 있다. 실행되어야 하는 실제 작동내용을 구현하고 있는 클래스와 작동을 시작시키는 부분을 분리함으로서 작업부는 필요한 만큼 재사용 될 수 있으며 작업부는 또한 실제 구현부를 따로 둠으로서 코드관리에 유연성을 확보한다

Command패턴에서 최상위 클래스는 명령부에 대한 인터페이스만 확보하는 추상클래스로서 하위클래스의 동작 스타일을 정의하게 된다. 일반적인 Application의 예를 들어보자. 사용자는 종종 프로그램의 mainmenu와 popup에서 동일한 menuitem을 확인할 수 있다. 물론 양쪽의 menuitem은 대부분의 경우 동일한 동작을 할 것이다. 이 때 menuitme의 코드에서는 동일한 명령클래스를 (또는 인스턴스를) 호출하는 코드를 가지고 있을 것이다. 이런식으로 실제 동작과 동작을 필요로하는 부분이 분리되어 있다면 그건 Command패턴으로 봐도 무방하다고 생각한다.

Command패턴은 그리 복잡하지 않다. mobile app을 예로 들어보자. mobile app에서는 각종 제스처가 사용된다. 하지만 어떤 체스처라고 해도 반드시 어떤 작동을 일으키기 위한 목적을 가지고 있다. 그렇다면 제스처의 검출 부분과, 제스처의 검출 시 어떤 동작을 할지를 별도의 구조로 분리해서 동작부분만 따로 클래스군으로 관리한다면 새로운 동작을 테스트하기 쉬운 제스처로 연결만 했다가 테스트가 끝난 다음 원하는 제스처로 연결을 바꿔주면 개발 및 코드의 유지보수도 쉽게 할 수 있다.

이렇게 필요한 부분을 분리하고, 역할을 할당하는 구조를 논의하고 규정하는게 Design pattern 이지만 Command패턴은 그 중에서도 단순하며 명확한 패턴이다.

Design Pattern for Smalltalk – Chain of Responsiblity

t_Dpsc_chapter05_ChainOfResponsibility_01

Chain of Responsiblity는 그대로 직역하자면 “책임 연쇄”가 된다. 하지만 이는 너무 직관적인 번역이라고 생각한다. 좀 더 고민해 보자면 “책임을 가지고 있는 연쇄” 정도가 될거고, 더 풀어보자면 “연쇄적 책임”이 되지 않을까 한다.

이 패턴은 조금은 특이하며 조금은 재귀적인 느낌을 준다. Client로 부터 요청을 받은 객체는 자신이 요청에 응답할 준비가 되어있지 않을 때 자신의 상위클래스로 수신한 요청을 전달한다. 이렇게 요청을 전달받은 상위 클래스는 요청에 대한 응답을 할 준비가 상위클래스 자신에게 되어있는지를 살펴보고 자신에게 준비가 되어있지 않다면 스스로에 대한 상위클래스로 요청을 다시 전달한다. 이렇게 요청을 계속 위로 전달해서 client의 요청에 적합한 준비가 된 클래스가 요청에 대한 행동을 진행한다. 이 방식의 단계에 대한 구조가 바로 Chain of Responsiblity 패턴이다.

Chain of Responsiblity 패턴이 성립하기 위해서는 가장 중요한 요건이 두가지가 있다. 하나는 요청을 받은 클래스의 전체 구조에서 요청에 대한 클래스(인스턴스)의 메서드는 동일한 인터페이스를 가지고 있어야 하며, 해당 요청을 처리하는 메서드 내부에서 ♣위줄♣의 객체로 요청을 전가하는 기본동작은 필요단계의 제일 위쪽에 있는 클래스에 선언되고, 그대로 아래쪽으로 상속되어야 한다는 점이다.

상위클래스에서 상속된 하위 클래스는 Client의 요청을 분석하고, 자신이 처리해야 할 필요가 있는 경우라면 메서드를 오버라이드 하면 된다. 그러면 요청의 내용에 따라 자신이 해야하는 처리가 있는 경우에 대한 동작만 새로 정의하면 된다. 이런 방식의 구현을 통해서 계층구조에서 작성되어야 하는 코드의 분량을 효율적으로 줄이고 관리의 용이성을 확보할 수 있다.