----- Original Message ----- From: "Craig R. McClanahan" <[EMAIL PROTECTED]>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.
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 :-)
If you're going to (potentially) ignore the labels and branches, whyThe 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.
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.
Also,Why should you expect any *other* command to decide whether *your* new command is relevant or not. That's *your* problem.
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).
Furthermore, assume the command C3 set up a state, but we could"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.
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).
I could be convinced if I see a possible mechanism that deals withJing, 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.
the command coupling problem and state storage problem.
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
Craig
Jing
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]