TheSpecUIframework:Chapter 03
- 요소(elements)의 재사용 및 구성
요소(elements)의 재사용 및 구성
Spec 의 핵심 설계 목표는 구축중인 사용자 인터페이스의 위젯을 이용해서 사용자 인터페이스를 원활하게 재사용 할 수있게 하는 것입니다. 그렇게 해야 사용자 인터페이스를 만들 때 생산성이 크게 향상되기 때문입니다.
재사용에 대한 이 관점은 이전 장에서 실제로 확인할 수 있었습니다. 또한 기본 위젯을 완전한 사용자 인터페이스처럼 사용할 수 있음을 보았습니다. 이 섹션에서는 위젯의 재사용 및 구성에 중점을 두며, 기본적으로 제약은 없다는 것을 보여줍니다. UI 를 구현할 때 유일한 요구 사항은 재사용 될 때 사용자 인터페이스를 매개 변수화하는 방법을 고려해야 하는 것이며, 그 점에서 반드시 따라야 할 구체적인 규칙은 하나뿐입니다.
이 장에서는 이미 정의된 요소를 다시 사용하여 새 UI 를 작성하는 방법을 학습합니다.
First requirements
To show how Spec enables the composition and reuse of user interfaces, in this chapter we build the user interface shown in Figure 3-1 as a composition of four parts: Spec 에서 사용자 인터페이스의 구성과 재사용을 가능하게하는 방법을 보여주기 위해, 이 장에서는 그림 3-1 과 같은 사용자 인터페이스를 네 부분으로 구성합니다:
- The "WidgetClassList": AbstractWidgetModel 의 하위 클래스를 표시하기위한 ListModel 을 포함하는 위젯.
- The "ProtocolMethodList": ListModel 과 프로토콜의 메서드를 표시하기 위해 LabelModel 로 구성된 위젯.
- The "ProtocolViewer": 하나의 WidgetClassList 와 두 개의 ProtocolMethodList 의 조합으로, AbstractWidgetModel 의 모든 하위 클래스의 프로토콜 api 및 api-event 의 메서드를 검색.
- The "ProtocolBrowser" : ProtocolViewer 를 재사용하며, 레이아웃을 변경하고 TextModel 을 추가하여 메소드의 소스 코드를 참조.
위젯으로 재사용 할 기본 UI 생성하기
이제부터 만들게될 첫 번째 사용자 정의 UI 에는 AbstractWidgetModel 의 모든 하위 클래스 목록이 표시되어야 합니다. 이 UI는 나중에보다 완벽한 UI 를 위한 위젯으로 재사용됩니다. 코드는 다음과 같습니다.(접근자에 대한 코드는 포함되어 있지 않습니다):
First we create a subclass of ComposableModel with one instance variable list which will hold an instance of ListModel.
먼저 ListModel 의 인스턴스를 가지게될 하나의 인스턴스 변수 목록으로 사용하기 위해 ComposableModel 의 하위 클래스를 만듭니다.
ComposableModel subclass: #WidgetClassList
instanceVariableNames: 'list'
classVariableNames: ''
package: 'Spec-BuildUIWithSpec
initializeWidgets 메서드에서 목록을 생성하며, 필요한 클래스를 알파벳 순으로 채웁니다. 또한 창 제목을 추가합니다.
WidgetClassList >> initializeWidgets
list := self newList.
list items: (AbstractWidgetModel allSubclasses
sorted: [:a :b | a name < b name ]).
self focusOrder add: list.
WidgetClassList >> title
^'Widgets'
레이아웃에는 목록만 포함됩니다:
WidgetClassList class >> defaultSpec
^ SpecLayout composed
add: #list;
yourself
결과 UI 는 그림 3-2 에서 확인할 수 있습니다.
Since this UI will later be used together with other widgets to provide a more complete user interface, some actions will need to occur when a list item is clicked. However, we cannot know beforehand what all these possible actions will be everywhere that it will be reused. The best solution therefore is to place this responsibility on the reuser of the widget. Every time this UI is reused as a widget, it will be configured by the reuser. To allow this, we add a configuration method name "whenSelectedItemChanged:", in the "api" protocol:
이 UI 는 나중에 다른 위젯과 함께 사용되어 보다 완벽한 사용자 인터페이스를 제공하게 되기 때문에, 목록 항목을 클릭 할 때 일부 동작(action)이 발생되어야 합니다. 하지만 가능성 있는 모든 행동이 재사용 될 수 있는 모든 곳에서 어떻게 필요하게 될지 미리 알 수는 없습니다. 그러므로 가장 좋은 해결책은 이 책임[1]을 위젯을 재사용 하게될 사람에게 맡기는 것입니다. 이 UI 는 위젯으로 재사용 될 때마다 재사용 하게될 사용자가 구성하도록 합니다.
재사용에 대한 행동의 구성을 허용하기 위해 api 프로토콜에서 구성 메서드를 whenSelectedItemChanged: 라는 이름으로 추가합니다.
WidgetClassList >> whenSelectedItemChanged: aBlock
list whenSelectedItemChanged: aBlock
이제 이 위젯을 재사용하는 사람은, 선택한 항목이 변경 될 때마다 실행되어야할 블록을 매개 변수화 할 수 있습니다.
Spec 위젯을 재사용할 때의 유일한 규칙은 UI 의 모든 일반(public)적인 설정 메서드는 api 프로토콜에 포함되어야 한다는 것입니다. 이 규칙은 위젯의 재사용자가 파라미터화 하는 방법을 더 쉽게 발견할 수 있도록 하기위한 것입니다. 이 장의 끝 부분에 있는 3.6 절에서 일반 설정 api 주제에 대해 설명합니다. |
두 개의 기본 위젯을 재사용 가능한 UI 로 결합
이렇게 만들어진 UI 는 주어진 프로토콜의 모든 메서드 목록을 보여줄 것이며, list 와 label 이라는 두 개의 위젯을 결합합니다. 재사용을 고려하면 앞의 UI 와 차이는 없습니다. 왜냐하면 위젯으로서 UI 를 재사용 할 때 그 UI 에 포함 된 위젯의 개수(및 위치 포함)에 대한 영향을 받지 않기 때문입니다. 크고 복잡한 UI 는 간단한 위젯과 동일한 방식으로 재사용됩니다.
ComposableModel subclass: #ProtocolMethodList
instanceVariableNames: 'label methods'
classVariableNames: ''
package: 'Spec-BuildUIWithSpec'
The ==initializeWidgets== method for this UI is quite straightforward. We specify the default label text as 'protocol', which will be changed when the widget is reused. We also give this UI a title.
The initializeWidgets method for this UI is quite straightforward. We specify the default label text as 'protocol', which will be changed when the widget is reused. We also give this UI a title.
이 UI의 initializeWidgets 메소드는 매우 간단합니다. 기본 lable 의 텍스트를 'protocol' 로 지정합니다. 이 프로토콜은 위젯이 다시 사용될 때 변경됩니다. 또한 이 UI 에 제목을 지정합니다.
ProtocolMethodList >> initializeWidgets
methods := self newList.
methods displayBlock: [ :m | m selector ].
label := self newLabel.
label label: 'Protocol'.
self focusOrder add: methods.
ProtocolMethodList >> title
^ 'Protocol widget'
레이아웃 코드는 고정 높이 lable 이 맨 위에 있으며, 남아있는 모든 공간을 목록이 차지하게 되는 열을 만듭니다. (레이아웃에 대한 자세한 내용은 3-3 장을 참조하십시오.)
ProtocolMethodList class >> defaultSpec
^ SpecColumnLayout composed
add: #label height: self toolbarHeight;
add: #methods;
yourself
이 UI 는 ProtocolMethodList new openWithSpec 를 평가(evaluating)해서 확인할 수 있습니다. 그림 3-3 에서와 같이 목록은 비어 있습니다. 항목을 별도로 설정하지 않았으므로 이것은 정상입니다.
예를 들어 메소드 목록을 채우고 프로토콜의 이름을 지정하는 등의 경우에는 프로토콜 메소드 목록을 구성해야 합니다. 이러한 작업들을 허용하기 위해 "api" 프로토콜에 여러가지 설정 메서드를 추가합니다.
ProtocolMethodList >> items: aCollection
methods items: aCollection
ProtocolMethodList >> label: aText
label label: aText
ProtocolMethodList >> resetSelection
methods resetSelection
ProtocolMethodList >> whenSelectedItemChanged: aBlock
methods whenSelectedItemChanged: aBlock
메서드를 추가하는것 외에는 아무 것도 하지 않아도 됩니다. 메서드와 label 모두 접근자를 통해 접근 할 수 있기 때문에, 이 위젯의 재사용자는 간단하게 가져온 다음 직접 설정하면 됩니다. 이 두 가지 대안은 3.6 절에서 논의하게될 설계 결정을 반영하고 있습니다. |
3 개의 위젯과 상호 작용을 관리하기
구축하게될 세 번째 사용자 인터페이스는, 두 개의 이전 사용자 인터페이스를 구성 요소 사용하게 됩니다. 두 종류의 위젯은 api 프로토콜의 메소드를 호출하여 구성되는데, 사용자 정의 UI 구성과 시스템 위젯 구성간에 차이가 없다는것을 알게 될 것입니다.
이 UI 는 WidgetClassList 와 두 개의 ProtocolMethodList 로 구성될 것이며, WidgetClassList 에서 model 클래스가 선택되면 프로토콜 api 및 api-events 의 메서드는 각각 두 개의 ProtocolMethodList 위젯에 표시될 것입니다.
ComposableModel subclass: #ProtocolViewer
instanceVariableNames: 'models api events'
classVariableNames: ''
package: 'Spec-BuildUIWithSpec'
Notes
- ↑ 행동을 정의해야할 책임