an ActionForward should represent a logical outcome of an Action, not a menu choice. Let me explain further.

Consider the little search box (with a "Go" button) that we like to put on pages of our applications, to allow users to do text based searching on things. Now, consider that you are authoring the Struts action that actually performs the search. The author of this code should require no knowledge of where in the application they wil be sent after the search is completed – his/her only job is to say "what happened" when the search took place.

Logically, there are three interesting outcomes we might want to describe:

  • No results at all were found – outcome "none".
  • Exactly one result was found – outcome "single".
  • More than one result was found – outcome "multiple".

I would argue that the search Action should return these three results as three separate logical outcomes. It is up to the application architect to decide to send all three outcomes to the "here's the list of responses" table page. It's also up to the application architect (perhaps later, in response to user feedback) to say "let's do this instead":

  • If there's no results, go to a page that says "sorry, no results were found,
    please try your search again."
  • If there's exactly one response, go to the details page to display the
    corresponding data.
  • If there's more than one response, go to the list page (as per the
    previous behavior).

Note that nothing in the forwards defined for the search action, or the code inside it, is affected by this decision. Indeed, the outcomes returned by an action are much more stable than the places that you (as the application architect) mght want to send the user next. The only time you have to change them is when you add new interesting outcomes that need to be accomodated in the navigation architecture of your app.

I agree with you that the names of forwards and the paths they go to can be fragile at times ... but I submit that this is primarily the result of how we are using them. Adding yet another identifier doesn't help, because now you've got two fragile identifiers for the same concept. If you think in terms of logical outcomes, though, you'll find this problem to be much less serious. Simply have each Action document the logical outcomes it returns, with meaningful nouns to describe them, and let the architect stitch together the navigation as the struts-config.xml file is composed.

(Even if it is you playing both roles – developer and archtect – you will find that this change of viewpoint really helps the long term maintainability of your application's navigation architecture.)

PS: If you ever hear me talk or write about JSF navgation, you'll hear exactly the same thing ... the strings returned by action methods should be outcomes, not destinations.

  • No labels