[Seaside] Re: Task Escape
Zulq Alam
me at zulq.net
Thu Jan 10 14:48:20 UTC 2008
I have created a superclass for all my tasks, CancelAwareTask to work in
conjunction with a Notification subclass CancelNotification. In response
to a notification, the task will reset its state and then answer (if
possible).
CancelAwareTask>>#go
" Subclasses should implement #run instead. "
[self run]
on: CancelNotification
do: [self handleCancel]
CancelAwareTask>>#cancel
CancelNotification signal
CancelAwareTask>>#handleCancel
self reset.
self answer
CancelAwareTask>>#reset
" Reset any state. "
self subclassResponsibility
CancelAwareTask>>#run
" Implement instead of #go. "
self subclassResponsibility
A run method might then be:
MyCancelAwareTask>>#run
self stepOne
self stepTwo
...
self stepN
MyCancelAwareTask>>#stepN
(self call: MyComponent new) ifFalse: [self cancel]
MyCancelAwareTask>>#reset
iVarOne := nil.
iVarTwo := nil.
...
iVarN := nil
This seems to work and I like it because I don't have to change very
much to make it work. I suspect it's not very efficient though. Would be
interested in your comments.
Thanks,
Zulq.
Zulq Alam wrote:
> I have a task with N steps:
>
> MyTask>>#go
> self stepOne.
> self stepTwo.
> ...
> self stepN.
>
> Each step calls one or more components. Each component offer a Cancel
> link / button. If clicked, the component answers false. If a component
> answers false, the task should stop. I currently do this by checking the
> answer value and then answering if the value is false.
>
> MyTask>>#stepN
> (self call: MyComponent new)
> ifFalse: [self answer: false]
>
> This seems to work OK but only if the task has been called. If it is the
> root component, then the answer is a no-op.
>
> I don't intend for such tasks to be used as root components and
> practically this isn't a problem but it doesn't feel right. The task
> should work no matter how it is being used.
>
> I suppose I could check after each step (yuk):
>
> MyTask>>#go
> ((self stepOne
> ifTrue: [self stepTwo])
> ifTrue: [self stepThree])
> ...
> ifTrue: [self stepN]
>
> Or, I could check at the beginning of each step (*slightly* less yuk):
>
> MyTask>>#stepN
> shouldRun ifFalse: [^ self].
> ...
>
> Or:
>
> MyTask>>#stepN
> self stepNMinusOne ifFalse: [^ self]
> ...
>
> Or I could use a signal:
>
> MyTask>>#stepN
> (self call: MyComponent new) ifFalse: [MyCancellation signal]
>
> MyTask>>#go
> [self stepOne.
> self stepTwo.
> ...
> self stepThree]
> on: MyCancellation
> do: [self answer: false]
>
> To me the signal looks the best, but feels like an abuse of the
> exception handling framework.
>
> What have others done? It's very possible I still don't know how to use
> tasks properly, so please feel free to correct me!
>
> Thanks,
> Zulq.
More information about the seaside
mailing list