See below.

> -----Original Message-----
> From: Aleksandar Seovic [mailto:[EMAIL PROTECTED]] 
> Sent: Thursday, February 20, 2003 9:52 PM
> To: [EMAIL PROTECTED]
> Subject: Re: [OS-webwork] Proposal: Removing the Action Interface
> 
> 
> Hi All,
> 
> I've been following this list for a while now and I really 
> like most of the stuff I've seen. However, I don't believe 
> that removal of Action interface is a move in the right 
> direction, for several reasons.
> 
> First of all, I don't see a difference between Action and 
> Command, and I don't think there should be commands within 
> actions -- if you need a new command you create a new class 
> that implements Action interface. I can see all kinds of 

We'll have to agree to disagree. I see Commands as very powerful and
useful. Creating a new class for every entry point is not a good
solution, as you'll often have 3 or more of these for one page, so you'd
need one base class plus 3+ subclasses.

> issues arising from allowing developers to define commands 
> within actions, ranging from difficult and clumsy 
> configuration file, to inability to define different 
> interceptors for different commands, to opening door for

You assume you can't define different Interceptors for commands, whereas
I'm planning on making exactly this possible.
 
> inexperienced developers to abuse the feature which would 
> lead to bad designs and as a consequence give bad reputation 
> to Xwork/Webwork. IIRC Rickard had a post few weeks back 
> where he asked if we should get rid of CommandDriven, and I 
> believe we should.

I don't rememeber this post. Rickard, maybe you'd care to comment?

> 
> If we agree that commands within actions are a bad thing, 
> there is still an option to specify on the action level which 
> method should be called and to default to execute() if 
> nothing is specified. It would even be possible for actions 
> to inherit other actions and override only the things that 
> should be different, such as which method to call. However, I 
> still don't think this is good approach because it represents 
> a fundamental paradigm shift from Command-based framework to 
> Facade-based one. Both are valid approaches, but I think that 
> existing Command-based approach is much better fit for Xwork. 
> Main difference is that when you are using commands you 
> typically map one use case to one command (Action) class, 
> while with a facade you usually map one use case to one 
> method (which is pretty much what Gu is doing in his 
> AccountManager class).
> 
> The biggest problem I see is that use case parameters and 
> return values are handled very differently in those two 
> approaches. Command keeps parameters and return values as 
> part of its state which makes it easy for dispatcher to 
> populate them from the request using introspection and for 
> the views to read them after the execution. Facade methods, 
> on the other hand, need to be passed appropriate parameters 
> during invocation and they return a result that would have to 
> be pushed to ValueStack in order for the views to use it. 
> Obviously, Facade methods can easily be wrapped using Action 
> objects. The fact that there is an additional layer is a good 
> thing, not bad.

I'm not sure where the idea that the execute / command methods would
take parameters came from. 

> 
> For example, why allow configuration like this
> 
> <action name="AccountManager.createAccount">
>     <view exception="PermissionException">Login.jsp</view>
>     <view el="'if test="'return' >1000 "">BigAccountSummary.jsp</view>
>     <view el="'if test="'return' <=1000 
> "">SmallAccountSummary.jsp</view> </action>
> 

This was posted, but I posted, and still feel, that this is not
feasible. 

> when you can easily write your CreateAccountAction like this:
> 
> private Account account;
> private long balance;
> 
> ...
> 
> public String execute()
> {
>     AccountManager am = new AccountManager();
> 
>     try
>     {
>         balance = am.createAccount(account);
>         if (balance > 1000)
>             return BIG_SUMMARY;
>         else
>             return SMALL_SUMMARY;
>     }
>     catch (PermissionException pe)
>     {
>         return LOGIN;
>     }
> }

I agree with you here. The entry points are command methods. You set
your state before you execute them, you don't pass the state into the
method. However, where we differ is in what you do about the case where
you want to show the form for the Account before it's been filled out.
In your case, I'd need 2 Actions, one which holds the Action object but
doesn't do validation or try to execute anything, and another where it
validates and executes. In my version, I've got 2 methods:

doShowForm() which just returns SUCCESS
doCreateAccount() which has validation applied and does what your
execute() method does.

> 
> I think this is exactly the logic that belongs to Action 
> classes and pushing it into the config file might be pushing 
> it just a little bit too far :) I don't think we should write 
> an XML interpreter and/or use expression evaluation to figure 
> out which view to go to. That logic is much better done in 
> Java than in XML, even if we disregard the fact that simple 
> map lookup to get the view is much, much faster than whatever 
> we would have to do to make the above configuration work.

That configuration was not something that I was planning to put into
Xwork configuration.

> 
> Previous example also shows that action class fields (and 
> their appropriate
> getters/setters) are very much related to the command itself: 
> execute() method uses them either as use case parameters or 
> as return values. How would we handle adding additional 
> method (command) to this action, for example 
> transferAccount() from Gu's AccountManager? Should we reuse 
> account field as one of the parameters to transfer or 
> introduce two new fields, sourceAccount and 
> destinationAccount? I think neither option is good, first one 
> because it uses inappropriate field which makes action more 
> difficult to use for the person creating a view, and second 
> one because it means that our instance fields are a union of 
> all the fields needed by all commands, which is terrible 
> design in my book and also makes action difficult to use even 
> if it is well documented which fields to use for each 
> command. I think the most appropriate thing to do in this 
> case is to create TransferAccountAction that wraps the call 
> to AccountManager.transferAccount().

I agree. If you're putting two completely different use cases into one
Action with commands, then you're designing it incorrectly.

> 
> In one of the messages Jason also mentioned that getting rid 
> of Action interface "allows you to have one Action with 
> multiple entry points without having to do a big if-else 
> block to do this yourself", and I'll have to disagree. 
> Commands are ideal way to avoid big if else statements -- 
> command dispatcher should be making a decision which action 
> to call, not the code within the action itself.
> 

Exactly, that's why the commands under an Action will be mapped to
aliases.


> I guess the typical example for multiple commands might be 
> the case where you need to read some persistant data, display 
> form that allows user to edit it, and then when the user 
> submits the form update your database.
> 
> I agree that it might be convinient to be able to have both 
> read and update methods in the same class, but is this really 
> necessary? After all, those two commands are different, very 

Is it necessary? No, I suppose not. Is it MUCH more convenient? Yes,
IMHO.

> likely need different interceptors (no validation or 
> transaction interceptors for read only command, for example) 
> and are likely to have different security requirements 
> (everyone can read, but only certain people can update data). 

This is spurious. This is not reading, this is loading for edit. If you
can get to this Action, you're opening the persistent data for editing.
If you're using this for viewing, then you're doing too much with your
Action.

> I think it is wise to separate those commands into different 
> classes and do one of the three things to avoid duplicating 
> code: 1) encapsulate all the shared data into a bean and have 
> that bean returned by the getModel() method Rickard was 
> proposing earlier; 2) extract all shared fields and their 
> getters/setters into abstract superclass that has execute() 
> marked as abstract; or 3) both of the previous two :)
> 

It's a good idea to keep your business logic out of your Actions, to
make it reusable. But it's also a good idea to not explode the number of
classes you create.

> Another thing to keep in  mind is that using reflection to 
> call arbitrary methods instead of calling execute() through 
> interface will have a performance penalty, no matter how 
> small that penalty is. Not the major reason why I don't like 
> proposed idea, but a reason that shouldn't be ignored nevertheless.
> 
> My belief is that a great framework should be:
> 
> 1. Simple and easy to use, even for beginners
> 
> Everyone should be able to grasp the concepts used and to 
> start using framework within hours. This is an area where 
> Webwork 1.x shines and some other popular frameworks 
> miserably fail. I'm not sure that getting rid of Action 
> interface would actually make things simpler. I think it 
> would actually make configuration more complex, for all the 
> wrong reasons.
> 

Well, you should read this list more if you think WW 1.x is so easy to
grasp :-). WW 1.x has lots of little inconsistencies. Check out the
Property tag, for a good example.

I personally think that Xwork and WW 2.0 are shaping up to be much more
consistent and straightforward. I may be biased, though :-) I think that
explicitly declaring which methods will be executed will make things
MORE clear.

> 2. Flexible, but not too flexible
> 
> Usually simplicity leads to flexibility, but by allowing 
> developers to call arbitrary methods on any object we might 
> be making rules little bit too relaxed. All is good while 
> good and experienced developers that know what they are doing 
> are using features like this to their advantage, and I 
> believe that most of the people the are following this list 
> and shaping great framework belong to that group.
> 
> Unfortunately, many developers that will hopefully be using 
> Webwork (if it is to become the world's best and most popular 
> web app framework) are neither good nor experienced and might 
> easily misuse features like this. It is because of them that 
> I believe that Xwork should be flexible within boundaries and 
> enforce some rules that will encourage even inexperienced 
> developers to apply best practices and good design patterns. 
> Keep in mind that inappropriate use can easily lead to very 
> bad and inflexible designs, applications that don't scale, 
> etc. I can easily see situation where someone is creating all 
> the commands in one huge Java class, making teamwork 
> impossible. Or someone splitting command methods into 
> multiple action classes based solely on the fact that they 
> need to have different interceptors applied. Why give 
> developers an opportunity to mess things up?

I thought breaking command methods into multiple action classes was what
you wanted? For me what's important is flexibility with sensible
defaults and good documentation. @see Hibernate.

> 
> 3. Focused on the specific problem
> 
> Xwork does an excellent job of executing commands that 
> implement Action interface, providing results to various view 
> technologies, and redirecting user to the appropriate view. 
> Let's not lose this focus by trying to make it execute 
> "anything, anywhere".
> 

I'm just trying to make CommandDriven, which is a very powerful and
useful pattern, a core part of Xwork / Webwork 2.0. Making it possible
to run any method is a nice side-effect that I thought would be nice.

> 
> Finally, why fix something that's not broken? Actions as they 
> stand today are really powerful and I don't see any reason 
> whatsoever that would make me think that executing a method 
> is better than executing a class. CommandDriven on the other 
> hand reminds me of an infamous "goto" statement -- something 
> that very rarely makes sense to use and should be avoided 
> like a plague in all other cases.
> 

You obviously have not used CommandDriven. It makes many things much
easier. Before CommandDriven we were doing things like putting hidden
form fields in our forms so our Actions could know whether the form had
been submitted or if we were just drawing the form the first time. 

> Even if you have all your services and their facades already 
> built, it not only makes sense to have a layer of Xwork 
> actions in front of them, it is probably the best thing to 
> do. Actions are the place to decide what view user should be 
> redirected to based on the result of service execution. You 
> might want to expose your services to many different systems, 
> either directly or through a web services layer. They should 
> be responsible for doing certain task and returning 
> appropriate result, but the burden of deciding which view to 
> display should not fall on them -- that's what the Actions 
> are for, at least in my humble opinion.

Ok, no disagreement here.

> 
> Wow, this is really long, especially for my first post on the 
> list. I promise to be shorter in the future :)
> 
> Regards,
> 
>     Aleks
> 

Well, I hope my replies don't scare you off from posting again. I think
there was some confusion about what I'm suggesting as opposed to what
some others were posting. Actions are still command objects as far as
I'm concerned, but I don't agree that there can only be one entry point.
CommandDriven is a very powerful and useful pattern for Actions.

Jason


-------------------------------------------------------
This SF.net email is sponsored by: SlickEdit Inc. Develop an edge.
The most comprehensive and flexible code editor you can use.
Code faster. C/C++, C#, Java, HTML, XML, many more. FREE 30-Day Trial.
www.slickedit.com/sourceforge
_______________________________________________
Opensymphony-webwork mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/opensymphony-webwork

Reply via email to