Re: Inputs and outputs

Hi,

Alex Milowski wrote:
> Could we possibly drop the '-port' from the declare* elements so that
> it reads a bit better in that we don't have the 'port port" going on:
> 
> <p:pipeline name="pipe">
>   <!-- accept a document, a schema, and a stylesheet. -->
>   <!-- validate, transform, and return the result -->
>   <p:declare-input port="document"/>
>   <p:declare-input port="schema"/>
>   <p:declare-input port="stylesheet"/>
>   <p:declare-output port="result" ref="identity.result"/>
> 
>   <p:step kind="validate">
>     <p:input port="document" ref="pipe.document"/>
>     <p:input port="schema" ref="pipe.schema"/>
>     <p:output port="result"/>
>   </p:step>
> 
>   <p:choose name="choice">
>     <p:declare-input port="testdocument" ref="validate.result"/>
>     <p:declare-input port="stylein" ref="pipe.stylesheet"/>
>     <p:declare-output port="result"/>
> 
> etc.

I think this is getting close. Comments:

1. We need to name the steps rather than using the kind attribute as the 
name in the reference (otherwise, what if you had two 'validate' steps: 
which one would 'validate.result' point to?). So <p:step> needs a name 
attribute.

2. The <p:declare-output> and <p:output> pairings are a bit confusing. 
At the pipeline level, we have the output declaration pointing to the 
output of a step:

   <p:declare-output port="result" ref="identity.result" />

and

   <p:step kind="identity" name="identity">
     <p:input port="document" ref="choice.result" />
     <p:output port="result" />
   </p:step>

At the choice level, we have the output of steps pointing to the output 
declaration:

   <p:declare-output port="result" />

and

   <p:step kind="xslt">
     <p:input port="document" ref="choice.testdocument" />
     <p:input port="stylesheet" ref="choice.stylein" />
     <p:output port="result" ref="choice.result" />
   </p:step>

With the step/port naming scheme, the <p:declare-output> on <p:choose> 
has to follow this pattern because it's too much to hope that the final 
steps in each branch have the same output port names (which would be 
necessary for the ref attribute on <p:declare-output> to point to them).

Perhaps it therefore makes sense to change the pattern at the pipeline 
level, such that the outputs that form the outputs of the pipeline 
itself point to the output declaration. I argued against this before, 
because it means there's more work involved in adding a step at the end 
of the pipeline, but I'm warming to it because of the symmetry and 
because it's quite useful to know which outputs are the end of the pipe. 
So something like (|s indicate changed lines):

<p:pipeline name="pipe">
   <!-- accept a document, a schema, and a stylesheet. -->
   <!-- validate, transform, and return the result -->
   <p:declare-input-port port="document"/>
   <p:declare-input-port port="schema"/>
   <p:declare-input-port port="stylesheet"/>
| <p:declare-output-port port="result"/>

| <p:step kind="validate" name="validate">
     <p:input port="document" ref="pipe.document"/>
     <p:input port="schema" ref="pipe.schema"/>
     <p:output port="result"/>
   </p:step>

   <p:choose name="choice">
     <p:declare-input-port port="testdocument" ref="validate.result"/>
     <p:declare-input-port port="stylein" ref="pipe.stylesheet"/>
     <p:declare-output-port port="result"/>

     <p:when test="/book">
       <p:step kind="xslt">
         <p:input port="document" ref="choice.testdocument"/>
         <p:input port="stylesheet" ref="choice.stylein"/>
         <p:output port="result" ref="choice.result"/>
       </p:step>
     </p:when>

     <p:when test="/html">
       <p:step kind="xslt">
         <p:input port="document" ref="choice.testdocument"/>
         <p:input port="stylesheet" href="html.xsl"/>
         <p:output port="result" ref="choice.result"/>
       </p:step>

       <p:step kind="bitbucket">
         <p:input port="document" ref="choice.stylein"/>
       </p:step>
     </p:when>
   </p:choose>

   <p:step kind="identity">
     <p:input port="document" ref="choice.result"/>
|   <p:output port="result" ref="pipe.result"/>
   </p:step>
<p:pipeline>

3. I know we're not supposed to be talking about defaulting, but perhaps 
it should be possible for path in the ref attribute to default to 
starting at the enclosing p:pipeline/p:choose etc. So (using a / 
separator instead, for variety) you'd have:

<p:pipeline name="pipe">
   <!-- accept a document, a schema, and a stylesheet. -->
   <!-- validate, transform, and return the result -->
   <p:declare-input port="document"/>
   <p:declare-input port="schema"/>
   <p:declare-input port="stylesheet"/>
   <p:declare-output port="result"/>

   <p:step kind="validate" name="validate">
|   <p:input port="document" ref="document"/>
|   <p:input port="schema" ref="schema"/>
     <p:output port="result"/>
   </p:step>

   <p:choose name="choice">
|   <p:declare-input port="testdocument" ref="#validate/result"/>
|   <p:declare-input port="stylein" ref="stylesheet"/>
     <p:declare-output port="result"/>

     <p:when test="/book">
       <p:step kind="xslt">
|       <p:input port="document" ref="testdocument"/>
|       <p:input port="stylesheet" ref="stylein"/>
|       <p:output port="result" ref="result"/>
       </p:step>
     </p:when>

     <p:when test="/html">
       <p:step kind="xslt">
|       <p:input port="document" ref="testdocument"/>
|       <p:input port="stylesheet" href="html.xsl"/>
|       <p:output port="result" ref="result"/>
       </p:step>

       <p:step kind="bitbucket">
|       <p:input port="document" ref="stylein"/>
       </p:step>
     </p:when>
   </p:choose>

   <p:step kind="identity">
|   <p:input port="document" ref="#choice/result"/>
|   <p:output port="result" ref="result"/>
   </p:step>
<p:pipeline>

4. For what it's worth, I think non-technical users will balk at having 
to include all the extra "pipework", such as declaring all the inputs 
for the choice (so that it can standalone) and having a bitbucket for 
unused inputs so that it passes static processing. I don't think it 
scales very well when you have lots of branches that use different 
inputs, or nested choices.

I would much rather <p:choose> (and <p:for-each>) *weren't* 
self-contained, and could point to inputs from their ancestors. I don't 
think this is unreasonable, given that it's how conditionals and 
iterations work in most programming languages. So something like:

<p:pipeline name="pipe">
   <!-- accept a document, a schema, and a stylesheet. -->
   <!-- validate, transform, and return the result -->
   <p:declare-input port="document"/>
   <p:declare-input port="schema"/>
   <p:declare-input port="stylesheet"/>
   <p:declare-output port="result"/>

   <p:step kind="validate" name="validate">
     <p:input port="document" ref="document"/>
     <p:input port="schema" ref="schema"/>
     <p:output port="result"/>
   </p:step>

| <p:choose name="choice">
|   <p:declare-output port="result"/>

     <p:when test="/book">
       <p:step kind="xslt">
|       <p:input port="document" ref="#validate/result"/>
|       <p:input port="stylesheet" ref="#pipe/stylesheet"/>
         <p:output port="result" ref="result"/>
       </p:step>
     </p:when>

     <p:when test="/html">
       <p:step kind="xslt">
|       <p:input port="document" ref="#validate/result"/>
         <p:input port="stylesheet" href="html.xsl"/>
         <p:output port="result" ref="result"/>
       </p:step>
     </p:when>
   </p:choose>

   <p:step kind="identity">
     <p:input port="document" ref="#choice/result"/>
     <p:output port="result" ref="result"/>
   </p:step>
<p:pipeline>

Whether people like this or not may well depend on where they stand on 
strong-vs-weak typing.

Enough for now,

Jeni
-- 
Jeni Tennison
http://www.jenitennison.com

Received on Friday, 21 July 2006 10:13:17 UTC