Jing Zhou wrote:

----- Original Message ----- From: "Craig R. McClanahan" <[EMAIL PROTECTED]>
To: "Struts Developers List" <[EMAIL PROTECTED]>
Sent: Tuesday, October 07, 2003 2:22 PM
Subject: Re: Struts-chain Behavior Discussion





You do not need to determine Class4 was always run or not,
actually it is determined at runtime. Its definition is included
in every labeled chain by default.



It is absolutely necessary to understand the control flow if you want to
customize it.  The above would support all of the following flows
(assuming that no command returns true prematurely):
* Class1 - Class2 - Class3 - Class4
* Class1 - Class3 - Class4
* Class1 - Class2 - Class4

Now, if I want to add a new step that has to occur before Class3, but is
ONLY executed if Class3 will be executed, how do I do that? I have to
change which command gets label L1, which is bad for the same reason
that "goto" in programming languages is bad.



You could easily assign the label L1 to the new command before Class3 in the chain. A chain definition is normally very very small (5-30 lines) comparing with programs (up to 8000 or more lines). I do not see any difficulties to manipulate such a small section. Note that the thing we are dealing with is a config file, not a program (with a "go to" from line 67 to line 7598 :-)



The idea is that you do not have to define a separate chain else where
if you could re-use a labeled chain in the current chain definition.
You could also ignore  labels if any, just use the chain as is.




If you're going to (potentially) ignore the labels and branches, why
have them in the first place?



In the example, the L1 labeled chain is invoked by Class1 if it returns false. If you do not need the particular L1 labeled chain in the current chain definition, you could ignore it. But the label could serve as an entry point for other chains outside the scope to invoke the L1 labeled chain if they find it useful.



Or, to put it differently, conditional behavior should be a feature of
the Command implementation ("is the world in the correct state for me to
perform this action?").  If the current state is not correct, it should
just return false to let the chain continue.  That's why a change based
on Ted's suggestion:

(1) LookupCommand
(2) ExceptionCatcher
(3) SelectLocale
(4) SelectAction
(5) CreateActionForm
(6) PopulateActionForm
(7) ValidateActionForm (must save state in the Context)
(NEW) SelectInput [skip if validation succeeded]
(8) CreateAction [skip if validation failed]
(9) ExecuteAction [skip if validation failed]
(10) PerformForward

is actually the cleanest overall approach.  The user should not have to
even *know* what conditions the commands care about to determine whether
they are executed.  Thus, you would end up with a clean and simple chain
definition:

<chain id="request-processor">
 <command class="LookupCommand"/>
 <command class="ExceptionCatcher"/>
 <command class="SelectLocale"/>
 <command class="SelectAction"/>
 <command class="CreateActionForm"/>
 <command class="PopulateActionForm"/>
 <command class="ValidateActionForm"/>
 <command class="SelectInput"/>
 <command class="CreateAction"/>
 <command class="ExecuteAction"/>
 <command class="PerformForward"/>
</chain>

Now, if I want to insert something that always happens before
ValidateActionForm, I know exactly where it goes.  I don't have to worry
about whether ValidateActionForm is going to branch or skip, because
it's not ... SelectInput and friends decide for themselves whether they
are relevant.

OK, I've convinced myself that this is the right approach :-). So I'll
likely be changing struts-chain to this tonight, and adding the
appropriate mechanisms for ValidateActionForm to pass on the success or
failure state information.



I have not been fully convinced by this approach yet. Taking a general chain definition as follows,

<chain>
 <command class="C1"/>
 <command class="C2"/>
 <command class="C3"/>
 ...
 <command class="C19"/>
 <command class="C20"/>
</chain>

If I want to add a new command C before C19, I'll have to figure out
who set up a state before C19, even on one does it.

Not true. You don't care who set up state .. you care only if your newly inserted command is relevant or not, since it will always be executed.

Also,
I'll have to figure out where the state is located if any and see if the new
command C honor that state or not (command coupling problem).


Why should you expect any *other* command to decide whether *your* new command is relevant or not. That's *your* problem.

Furthermore, assume the command C3 set up a state, but we could
see any commands between C3 and C19 could set up a second one
or third one. Where the states are stored systematically is another
question (state storage problem).


"State is in the eyes of the beholder" :-). If you can't decide for yourself when your newly inserted command is relevant, then by definition you are at fault, because there is no way for your command component to be independently testable and reusable.

I could be convinced if I see a possible mechanism that deals with
the command coupling problem and state storage problem.


Jing, it is sounding more and more like what you want is a scripting control flow language expressed in XML. That is absolutely, totally, *not* what commons-chain is about. Feel free to invent your own package for this purpose. Feel free to popularize it all you want. You're even welcome to say "this is an extension to commons-chain that supports branches and labels". But commons-chain itself is going to stay focused on the pure CoR pattern, which has absolutely no notion of branches or labels in the fundamental APIs. Such things, therefore, do not belong in the fundamental commons-chain APIs.

I'm not going to bother to respond to any further discussion along this line -- as far as I'm concerned, the case for adding branches and labels has failed to illustrate that it has any technical merit (for commons-chain), and I'm not interested in spending any more time discussing it. What you do in your own projects (open source or not) is, of course, totally up to you.



Craig




Jing


Craig



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to