cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Ivelin Ivanov" <ive...@apache.org>
Subject Re: [Proposal] Implementing XMLForm with Flow
Date Sun, 08 Dec 2002 18:30:23 GMT

I have nothing new to add, but would like to balance the discussion
with a reminder:

----- Original Message -----
From: "Ovidiu Predescu" <ovidiu@apache.org>
To: <cocoon-dev@xml.apache.org>
Sent: Saturday, December 07, 2002 10:52 PM
Subject: Re: [Proposal] Implementing XMLForm with Flow


> Brilliant example Chris, I love it!!
>
> This shows exactly what can be built with continuations and
> tail-recursive functions.
>
...
> > state-machine code as in XMLForm actions.  Compare the flow version to
> > the original XMLForm action code reproduced below, and judge for
> > yourself.
> >
> > //  display form, wait for submission, and
> > //  apply validations; repeat until no violations
> > function sendView(form, view, uri) {
> >    form.clearViolations();
> >    if (uri == undefined) {
> >        uri = view + ".xml";
> >    }
> >    sendPageAndWait(uri, {id: view});
> >    form.populate(cocoon.request);
> >    if (form.violations != null) {
> >        sendView(form, view, uri);
> >    }
> > }
>
> The recursive call to sendView here is what is called a tail-recursive
> call. This type of calls are optimized by Christopher's modified engine
> to avoid eating stack space, a common technique in functional
> languages. They behave as a simple goto to the beginning of the
> function.

Tail recursion is as old as 20 years. Most functional language
implementations use it.
The example above though is equivalent to the following java(Action) code:

    if getForm().getViolations () != null )
    {
      return page( getFormView() );
    }

Clearing violations and population are provided by the abstract action
unless explicitly overriden.
Read on.

>
> > function createForm() {
> >    // create the Form object
> >    // ...
> > }
> >
> > function howToWizard() {
> >    // different form views
> >    // participating in the wizard
> >    var VIEW_START = "start";
> >    var VIEW_REGISTRATION = "registration";
> >    var VIEW_INTEREST = "interest";
> >    var VIEW_GARDENING = "organicGardening";
> >    var VIEW_COOKING = "cooking";
> >    var VIEW_SMALLHOLDING = "smallholdingManagement";
> >    var VIEW_CONFIRM = "confirm";
> >    var VIEW_END = "end";
> >
> >    var form = createForm();
> >    var jBean = form.getModel();
> >    sendView(form, VIEW_START);
> >    sendView(form, VIEW_REGISTRATION);
> >    sendView(form, VIEW_INTEREST);
> >    if (jBean.organicGardening) {
> >        sendView(form, VIEW_GARDENING);
> >    } else if (jBean.cooking) {
> >        sendView(form, VIEW_COOKING);
> >    } else if (jBean.smallholdingManagement) {
> >        sendView(form, VIEW_SMALLHOLDING);
> >    }
> >    sendView(form, VIEW_CONFIRM);
> >    sendView(form, VIEW_END);
> > }

This code assumes that you are only moving one direction,
which is not what the wizard is doing.
It is supposed to handle "Prev" as well.

Additionally it always validates the input, which is again not what the demo
is doing.
"Prev" does not trigger validation.

It is unfare to compare oranges to apples!

Please, implement the exact same functionality of the demo before further
comparison.

The action code is very verbose to make it clear what it is supposed to do
in the general case.
You realize that if it were for this specific application, I could optimize
the code to
look much shorter and use a map for looking up the next/prev page in the
workflow.

I don't think that anyone on this list needs lessons on how to shorten

     if ( formView.equals ( VIEW_REGISTRATION ) )
      {
        if ( command.equals( CMD_NEXT ) )
        {
          return page(  VIEW_INTEREST );
        }
      }

to

if (formView.equals(VIEW_REGISTRATION))
  return page(  VIEW_INTEREST );

which assumes that there is only one way navigation.

It is not much different than the js code:

    sendView(form, VIEW_REGISTRATION);
    sendView(form, VIEW_INTEREST);

but it doesn't have the overhead of preserving runtime stack.
It also doesn't have to deal with abandoned runtime stacks.
I will leave the scalability issue aside, granting to the js flow its young
age.

>
> Which shows exactly why continuations provide such a simple way of
> programming complex applications!

Until now, it has shown to me a simple way to program simple applications.


Again, I would love to see a better alternative to the traditional events
model.
However let's leave emotions aside and compare objectively.
Since there are so many people excited about it, someone has to
play devil's advocate.


Ivelin



>
> Best regards,
> Ovidiu
>
> > ------------------------------------------------------------
> >
> > From HowToWizardAction.java:
> >
> >      ....
> >
> >     // apply control flow rules
> >      if ( formView.equals ( VIEW_REGISTRATION ) )
> >      {
> >        if ( command.equals( CMD_NEXT ) )
> >        {
> >          return page(  VIEW_INTEREST );
> >        }            }
> >      else if ( formView.equals ( VIEW_INTEREST ) )
> >      {
> >        if ( command.equals( CMD_NEXT ) )
> >        {
> >           if ( jBean.getOrganicGardening() == true )
> >           {
> >             return page( VIEW_GARDENING );
> >           }
> >           else if ( jBean.getCooking() == true )
> >           {
> >             return page( VIEW_COOKING );
> >           }
> >           else if ( jBean.getSmallholdingManagement() == true )
> >           {
> >             return page( VIEW_SMALLHOLDING );
> >           }
> >           //else if ( getForm().get
> >          return page(  VIEW_CONFIRM );
> >        }
> >        if ( command.equals( CMD_PREV ) )
> >        {
> >           return page( VIEW_REGISTRATION );
> >        }
> >      }
> >      else if ( formView.equals ( VIEW_GARDENING ) )
> >      {
> >        if ( command.equals ( CMD_NEXT ) )
> >        {
> >           if ( jBean.getCooking() == true )
> >           {
> >             return page( VIEW_COOKING );
> >           }
> >           else if ( jBean.getSmallholdingManagement() == true )
> >           {
> >             return page( VIEW_SMALLHOLDING );
> >           }                  return page( VIEW_CONFIRM );
> >        }
> >        else if( command.equals( CMD_PREV ) )
> >        {
> >          return page( VIEW_INTEREST );
> >        }
> >      }
> >      else if ( formView.equals ( VIEW_COOKING ) )
> >      {
> >        if ( command.equals ( CMD_NEXT ) )
> >        {
> >           if ( jBean.getSmallholdingManagement() == true )
> >           {
> >             return page( VIEW_SMALLHOLDING );
> >           }                  return page( VIEW_CONFIRM );
> >        }
> >        else if ( command.equals( CMD_PREV ) )
> >        {                  if ( jBean.getOrganicGardening() == true )
> >          {
> >            return page( VIEW_GARDENING );
> >          }
> >          return page( VIEW_INTEREST );
> >        }
> >      }
> >      else if ( formView.equals ( VIEW_SMALLHOLDING ) )
> >      {
> >        if ( command.equals( CMD_NEXT ) )
> >        {
> >          return page( VIEW_CONFIRM );
> >        }
> >        else if ( command.equals( CMD_PREV ) )
> >        {
> >          if ( jBean.getCooking() == true )
> >          {
> >            return page( VIEW_COOKING );
> >          }
> >          else if ( jBean.getOrganicGardening() == true )
> >          {
> >            return page( VIEW_GARDENING );
> >          }
> >          return page( VIEW_INTEREST );
> >        }
> >      }
> >      else if ( formView.equals ( VIEW_CONFIRM ) )
> >      {
> >        if ( command.equals( CMD_NEXT ) )
> >        {
> >           return page( VIEW_END );
> >        }
> >        else if( command.equals( CMD_PREV ) )
> >        {
> >           if ( jBean.getOrganicGardening() == true )
> >           {
> >             return page( VIEW_GARDENING );
> >           }                  return page( VIEW_INTEREST );
> >        }
> >      }
> >    }
> >
> > Ivelin Ivanov wrote:
> >
> >> Sorry I wasn't clear before.
> >> I know you can call Java from the flow.
> >> The question is how to use the flow in a way which significantly
> >> reduces
> >> code
> >> while making the maintenance easier and improving the readability.
> >>
> >> Try to beat the existing XMLForm wizard demo.
> >> If you succeed, it will be great !
> >>
> >> Fingers crossed,
> >>
> >> Ivelin
> >>
> >>
> >> ----- Original Message -----
> >> From: "Ugo Cei" <u.cei@cbim.it>
> >> To: <cocoon-dev@xml.apache.org>
> >> Sent: Thursday, December 05, 2002 2:36 AM
> >> Subject: Re: [Proposal] Implementing XMLForm with Flow
> >>
> >>
> >>
> >>> Ivelin Ivanov wrote:
> >>>
> >>>> I hope you are the last hero trying to confront this monster.
> >>>>
> >>>> The discussion how to combine the two has been going on forever,
> >>>> but we
> >>>>
> >> have
> >>
> >>>> not come to an agreement.
> >>>>
> >>> I'm currently recovering the previous threads from the archive and
> >>> reading them.
> >>>
> >>>
> >>>> I would gladly offer my tactical guidance for your effort.
> >>>>
> >>> Thank you.
> >>>
> >>>
> >>>> If I was to do this with Actions, I could use well known and
> >>>>
> >> standardized
> >>
> >>>> Java APIs - JWSP or JDBC.
> >>>>
> >>> But, as Ovidiu pointed out, you can!
> >>>
> >>> var schemaFactory =
> >>>
> >>> Packages.org.apache.cocoon.components.validation.SchemaFactory.lookup
> >>>     ("http://www.ascc.net/xml/schematron");
> >>> var is = new Packages.org.xml.sax.InputSource
> >>>   ("flows/newuser-schema.xml");
> >>> var schema = schemaFactory.compileSchema(is);
> >>> var validator = schema.newValidator();
> >>> validator.setProperty("http://xml.apache.org/cocoon/validator/phase",
> >>>   "NewUser");
> >>> violations = validator.validate(userBean);
> >>>
> >>> This is just a quick hack I put together looking at the code for the
> >>> AbstractXMLFormAction and Form, but it works. I just need to define
> >>> some
> >>> symbolic constants for the namespaces and find a way to access a
> >>> SourceResolver from JavaScript to make it pretty.
> >>>
> >>> Anyway, if you prefer to write complex business logic in Java (and
> >>> I'd
> >>> agree wholeheartedly with that), you can encapsulate it in a Java
> >>> method
> >>> that returns a boolean or an index to drive the flow that will be
> >>> implemented by an if/then/else or a switch in JavaScript.
> >>>
> >>> What do we gain by this? We remove flow logic from the sitemap in the
> >>> form of actions and put it in the flowscript, where it belongs
> >>> (IMHO).
> >>>
> >>> Ugo
> >>>
> >>> --
> >>> Ugo Cei - http://www.beblogging.com/blog/
> >>>
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
> >>> For additional commands, email: cocoon-dev-help@xml.apache.org
> >>>
> >>>
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
> >> For additional commands, email: cocoon-dev-help@xml.apache.org
> >>
> >>
> >>
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
> > For additional commands, email: cocoon-dev-help@xml.apache.org
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
> For additional commands, email: cocoon-dev-help@xml.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Mime
View raw message