[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