You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Howard Lewis Ship <hl...@gmail.com> on 2007/02/12 23:08:38 UTC

Notes on "type safe" Tapestry 5

Kent has put a lot of work into a "type safe" Tapestry 5.

I'm begining to work through the code changes.

Please bear with me ... my style is to write my questions as I go, and
leave them, even when I answer those questions further down.

The FormPersist annotation is very clever and useful.  I'm a little
troubled that a field's label and disabled flags are persisted in the
form. The label should just be available again, and the disabled flag
is something I'd like to recompute when the form is submitted.  Also,
a persistence strategy of "form" may be preferable to a new
annotation.

It's also very heavily tied to AbstractField implementation (the
collectFormPersistPropNames).  Please spell out "property".  This
means that it will be harder to create a "composite field" component
that implements the Field interface and delegates out to a number of
real fields.

I'm not happy with the hooks into Loop to support Forms via
RestorePropertiesAction.storeAction(). This seems like something that
should be done inside Form/FormSupport or make use of the Heartbeat
environmental service in order to occur as part of the Loop without
tying the two classes so closely together.  You don't see a lot of
class-calling-class in Tapestry, its usually
implementation-calls-interface.

I particularly don't like the way that BindingExprValueConduit works,
it's not very IoC ... instead, it forces every component to implement
these additional service interfaces (BindingSourceProvider).  It looks
like these things get persisted into the form as well (which would
explain the need for lookup, since IoC service proxies don't
serialize).

So now containers have to implement a configure_foo() method for each
component.  Underscores?  Since ids are unique (caselessly) then it
could be configureFoo() which would be more consistent with, say,
Tapestry IOC & etc.

Why a seperate method for each component? Since components appear to
always be instance variables now, a single method per container
component could configure all contained components.

Please avoid abbreviated names like "Expr" for "Expression".  In fact,
setValueBindingExpr() could be called setValueBinding() or even
bindValue().

Ouch.  RestorePropertiesAction is also based on reflection to read the
property values that will be stored into the form.  Much better to
gain access to a PropertyAccess service or better yet, a
PropertyConduit (which avoids reflection in favor of bytecode
generation).

OK ... I'm pulling down large scale diffs to see how everything fits
together.  I'm beginning to think that components must re-configure
themselves (invoke a configure method on their parent) as part of
their lifecycle?

It looks like @Parameter is just completely gone.   Performance issue:
caching. As fast as methods can be invoked via PropertyConduit (i.e.,
via bytecode generation), if the method called is slow, that's a
problem. I guess there's just a tiny minority of "parameters" that are
read/write and those are not read or written very often, so just FUD.

Looks like much more stuff must be serializable (related to
@FormPersist). A long term philosophy in Tapestry has been "store only
what cannot be recreated".  This approach seems more like "store
everything" (on the client)".  I can hear the .Net jokes coming :-)

Nope, looks like the configure_foo methods are invoked via REFLECTION.
Ick.  This is someting that could be done by writing code to invoke
the configure method, and doing so with a
ComponentClassTransformationWorker.  And this occurs from just before
the SetupRender state during rendering.

This basically assumes that all the properties of a component will be
stable for the duration of the component's rendering.

I guess all the properties will be reset at the end of the request.

CompoundalidatorGenerator should be named CompoundValidatorGenerator.

FormPersistWorker: the BodyBuilder utility is useful for assembling
Javassist code piecewise. Also, Javassist must have gotten more
liberal about what it accepts as a "body", it used to be that you had
to enclose multiple statements inside braces.  Maybe extendMethod() is
different from creating a new method.

InternalClassTransformationImpl: findFieldsWithAnnotation() has been
uselessly overriden (the alternate version, with the searchAncestors
parameter) is not actually used and does not doing anything with that
parameter.

So ... is parameter binding just for informal parameters now?

So ... you have to be explicit about using an Any component?

There's no longer any check for unbound parameters.  I guess that too
is up to individual components to check, probably inside @SetupRender.
 5.0.2-SNAPSHOT includes additional annotations for hooking into page
lifecycle, so @PageLoaded would also be good, I guess. I'm finding the
relationship between parameters and lifecycle a bit fuzzy.

Kind of handy having ComponentResources provide a coerce() method.

So ... for parameters where the value changes often (i.e., at least
per-render), it is necessary to
keep invoking the parent component's configure_foo() method (which has
to be public, though that could be fixed).

So, what you're really saying is that people are going to prefer option A:

  <t:comp id="showProperties">
     ...
                <t:comp id="propLoop">
                                    <dt>${propertyName}</dt>
                                    <dd>${propertyValue}</dd>
                  </t:comp>
   ...
  </t:comp>

with

    public void configure_showProperties()
    {
        _showProperties.setTest(getShowPropertyList());
    }

    public void configure_propLoop()
    {
        _propLoop.setSource(getInfo().getPropertyNames());
    }

to:

<t:comp type="If" test="showPropertyList">
  ...
  <t:comp type="Loop" source="info.propertyNames" value="propertyName">
          <dt>${propertyName}</dt>
           <dd>${propertyValue}</dd>
   </t:comp>
  ...
</t:comp>

with

... nothing ...

I don't totally follow what is going on in terms of form support
(though I think it could be implemented less obtrusively using
ComponentActions and some code generation, and maybe some changes to
FormSupport) but I'm finding some aspects of it a bit worrysome
(particularily the fact that disabled is NOT re-evaluated on form
submit).


I believe your value statement is that TypeSafe Tapestry makes the
code more correct and more readable, allowing for IDE support in terms
of available parameters (they are just setter methods) and parameter
type.

I think you are correct, the code is more type safe, but does so by
being more rigid.  We've shifted more of the responsibility onto the
developer and away from the framework. This is true both for the
author of the component (more setter and getter methods) and for the
user of the component (the need for lots of configure_foo methods, the
need to be aware of which are properties and which are bindings).

I think the templates suffer. They are less readable, more in service
to the Java code and less readable (containing less useful
information) than with parameter bindings in place. In T3/T4 I found
that too many users were not providing explciit ids for components, so
T5 gives you a reward (don't have to bind value) and a better default
id when the id is omitted (the component type in lower case).  With
TypeSafe, you must give each component, no matter how trivial, an
explicit id in order to be able to configure its properties.

There's some issues with flexibility.  Component A renders component
B, which has a parameter set from a property of component A.  Inside
B's body, there's a component C that modifies the property of A.  When
does B see that change?  Not until it starts a completely fresh
render. This kind of thing happens in more complex components, such as
BeanEditFor and Grid (today) and the Ajax components coming in the
future.

There are performance issues (that could be addressed in non-prototype
code). There are other performance issues (some of the form related
stuff) that may be more difficult to address.  Sorry, FUD ... slower
than T5/trunk is not a peformance problem, just a difference.

Where do we stop?  Isn't the ${property} syntax just as questionable?
It's not type safe (less important because it will always be converted
into a string), but the same kind of refactoring changes that cause
issues (addressed by TypeSafe Tapestry) will break property names in
the templates, causing runtime exceptions.

Lastly, there's the issue of compile time safety vs. working code.
Code that compiles cleanly doesn't necessarily work. Testing is
necessary on top of clean compiles.  In the dynamic land, such as
Ruby, code can be "untyped" and still industrial strength because they
test the hell out of things.  With your own contributions, plus
Selenium, plus the clean POJO components, that is true for T5 as well
... fully, easily testable.

Further, with T5's ability to do extensive type coercions efficiently
and invisibly, many of the changes necessitated by refactoring do go
away.

Finally, and this is much more subjective than the rest (which is
already subjective), this just doesn't "feel" as much like Tapestry.
All the other changes in T5 are just T4 with the chains removed.
Souped up. Stream lined. Smarter defaults. Less code to accomplish the
same thing. TypeSafe does more to change the basic nature of Tapestry
than the new T5 code base does in an of itself.

So ... let's get a discussion cranked up!




-- 
Howard M. Lewis Ship
TWD Consulting, Inc.
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Apache HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

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


Re: Notes on "type safe" Tapestry 5

Posted by Jesse Kuhnert <jk...@gmail.com>.
I think it's been "kibosh"-ed now ...

Sometimes I wish Hani was on ~all~ (vs one)  the dev lists I subscribe
to. It certainly would keep things nice and brief.

On 2/17/07, Ryan Holmes <ry...@hyperstep.com> wrote:
>



-- 
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

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


Re: Notes on "type safe" Tapestry 5

Posted by Jesse Kuhnert <jk...@gmail.com>.
Oh really? Do pray tell, just how is it a ruby framework ?

I don't know if you've ever explored any artistic endeavor unrelated
to programming - but I look at it like that. Every day in everything
you do in any art / language / whatever you always learn new "good"
things and new "bad" things. The artist part comes in when you
successfully take your own version of good from all these points and
form your own expression being the sum of all that is good. (or crap,
depending on how good you are at your art ;) )

Stop trying to pigeon hole everything as being either completely one
thing or another. It just is. Try embracing it a little.

Maybe start somewhere smaller like contributing some components /
documentation / etc. I'm sure Howard has plenty of things in mind he'd
like to do if you ask him.

On 2/20/07, Kent Tong <ke...@cpttm.org.mo> wrote:
<snipped>
> But anyway, please don't waste any more time on this issue as it is
> now clear that Tapestry 5 is going to be a Ruby web framework for
> Java programmers. As such I fully agree that compile time checking
> and first class IDE support are conflicting goals.
>
> --
> Kent Tong
> Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT)
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

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


Re: Notes on "type safe" Tapestry 5

Posted by Kent Tong <ke...@cpttm.org.mo>.
Ryan Holmes <ryan <at> hyperstep.com> writes:

> It seems to utterly contradict the primary goals of  
> Tapestry 5 which, as I understand them, are to bring some of the  
> advantages of *dynamic languages* to a Java web framework 

I found that out later. Is it written somewhere as the design goal
of T5? If so, I'm sorry that I've missed that. This would have saved 
us a lot of time.

> It would be a serious mistake to build two fundamentally different  
> philosophies into Tapestry 5 and expect users to perceive the  
> schizophrenic result as "flexible." They won't -- they'll only find  
> it confusing and will move on to other, more coherent frameworks.

Agree.

> I also have to note that, based on the total lack of support from  
> users or developers for the concept of "type-safe Tapestry", I'm  
> afraid Kent is the only one who doesn't see that he is pulling in a  
> different and ultimately counterproductive direction.

Interesting. You mean the following have never existed?
http://thread.gmane.org/gmane.comp.java.tapestry.user/45117/focus=45143
http://thread.gmane.org/gmane.comp.java.tapestry.user/45117/focus=45143
http://www.theserverside.com/news/thread.tss?thread_id=44119#226878
http://tapestryjava.blogspot.com/2005/07/vs-makes-me.html

In addition, I suppose you have seen people keep asking for IDE
support for Tapestry. My proposal is not only about compile time
checking, but also first class IDE support.

But anyway, please don't waste any more time on this issue as it is 
now clear that Tapestry 5 is going to be a Ruby web framework for 
Java programmers. As such I fully agree that compile time checking
and first class IDE support are conflicting goals.

--
Kent Tong
Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT)


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


Re: Notes on "type safe" Tapestry 5

Posted by Howard Lewis Ship <hl...@gmail.com>.
ZTT?  "Zero Time to Try" maybe?

On 2/17/07, Ryan Holmes <ry...@hyperstep.com> wrote:
>
> On Feb 16, 2007, at 8:32 PM, Kent Tong wrote:
>
> >
> >> So, what you're really saying is that people are going to prefer
> >> option A:
> >>
> >>   <t:comp id="showProperties">
> >>      ...
> >>                 <t:comp id="propLoop">
> >>                                     <dt>${propertyName}</dt>
> >>                                     <dd>${propertyValue}</dd>
> >>                   </t:comp>
> >>    ...
> >>   </t:comp>
> >>
> >> with
> >>
> >>     public void configure_showProperties()
> >>     {
> >>         _showProperties.setTest(getShowPropertyList());
> >>     }
> >>
> >>     public void configure_propLoop()
> >>     {
> >>         _propLoop.setSource(getInfo().getPropertyNames());
> >>     }
> >>
> >> to:
> >>
> >> <t:comp type="If" test="showPropertyList">
> >>   ...
> >>   <t:comp type="Loop" source="info.propertyNames"
> >> value="propertyName">
> >>           <dt>${propertyName}</dt>
> >>            <dd>${propertyValue}</dd>
> >>    </t:comp>
> >>   ...
> >> </t:comp>
> >>
> >> with
> >>
> >> ... nothing ...
> >
> > Yes, I believe more Java users prefer option A especially when most of
> > the Java code in option A can be generated using a code template.
> > There is really no much more typing required, while we enjoy the
> > warm and fuzzy feeling of compile-time checking and auto-completion.
>
>
> Sorry to say this, but option "A" is essentially a half-baked
> implementation of Wicket, without any of that framework's elegance or
> consistency. It seems to utterly contradict the primary goals of
> Tapestry 5 which, as I understand them, are to bring some of the
> advantages of *dynamic languages* to a Java web framework in addition
> to refining the concepts developed in earlier versions of Tapestry --
> none of which emphasized static typing.
>
> It would be a serious mistake to build two fundamentally different
> philosophies into Tapestry 5 and expect users to perceive the
> schizophrenic result as "flexible." They won't -- they'll only find
> it confusing and will move on to other, more coherent frameworks.
>
> Regarding the more fundamental issue of run-time vs. compile-time
> type checking, Howard has apparently worked miracles to mitigate one
> of the primary disadvantages of run-time checking by providing (for
> the first time, I believe) ZTT in a Java web framework. ZTT is
> precisely why developers who work with dynamic languages don't seem
> to miss compile-time checking. They write some code, run the app and
> it either works or it doesn't. With ZTT, it's so quick and easy to
> run your code that bouncing back and forth between coding and testing
> is really no big deal.
>
> I also have to note that, based on the total lack of support from
> users or developers for the concept of "type-safe Tapestry", I'm
> afraid Kent is the only one who doesn't see that he is pulling in a
> different and ultimately counterproductive direction.
>
> I apologize for being so blunt, especially since I'm not a Tapestry
> developer (besides a couple of minor patches) and only sporadically
> contribute to the user list. However, this particular issue appears
> very clear-cut to me and I think if Tapestry developers have a
> similar opinion (which I suspect they do) they should put the kibosh
> on this and move on towards a 5.0 release.
>
> -Ryan
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: dev-help@tapestry.apache.org
>
>


-- 
Howard M. Lewis Ship
TWD Consulting, Inc.
Independent J2EE / Open-Source Java Consultant
Creator and PMC Chair, Apache Tapestry
Creator, Apache HiveMind

Professional Tapestry training, mentoring, support
and project work.  http://howardlewisship.com

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


Re: Notes on "type safe" Tapestry 5

Posted by Ryan Holmes <ry...@hyperstep.com>.
On Feb 16, 2007, at 8:32 PM, Kent Tong wrote:

>
>> So, what you're really saying is that people are going to prefer  
>> option A:
>>
>>   <t:comp id="showProperties">
>>      ...
>>                 <t:comp id="propLoop">
>>                                     <dt>${propertyName}</dt>
>>                                     <dd>${propertyValue}</dd>
>>                   </t:comp>
>>    ...
>>   </t:comp>
>>
>> with
>>
>>     public void configure_showProperties()
>>     {
>>         _showProperties.setTest(getShowPropertyList());
>>     }
>>
>>     public void configure_propLoop()
>>     {
>>         _propLoop.setSource(getInfo().getPropertyNames());
>>     }
>>
>> to:
>>
>> <t:comp type="If" test="showPropertyList">
>>   ...
>>   <t:comp type="Loop" source="info.propertyNames"  
>> value="propertyName">
>>           <dt>${propertyName}</dt>
>>            <dd>${propertyValue}</dd>
>>    </t:comp>
>>   ...
>> </t:comp>
>>
>> with
>>
>> ... nothing ...
>
> Yes, I believe more Java users prefer option A especially when most of
> the Java code in option A can be generated using a code template.
> There is really no much more typing required, while we enjoy the
> warm and fuzzy feeling of compile-time checking and auto-completion.


Sorry to say this, but option "A" is essentially a half-baked  
implementation of Wicket, without any of that framework's elegance or  
consistency. It seems to utterly contradict the primary goals of  
Tapestry 5 which, as I understand them, are to bring some of the  
advantages of *dynamic languages* to a Java web framework in addition  
to refining the concepts developed in earlier versions of Tapestry --  
none of which emphasized static typing.

It would be a serious mistake to build two fundamentally different  
philosophies into Tapestry 5 and expect users to perceive the  
schizophrenic result as "flexible." They won't -- they'll only find  
it confusing and will move on to other, more coherent frameworks.

Regarding the more fundamental issue of run-time vs. compile-time  
type checking, Howard has apparently worked miracles to mitigate one  
of the primary disadvantages of run-time checking by providing (for  
the first time, I believe) ZTT in a Java web framework. ZTT is  
precisely why developers who work with dynamic languages don't seem  
to miss compile-time checking. They write some code, run the app and  
it either works or it doesn't. With ZTT, it's so quick and easy to  
run your code that bouncing back and forth between coding and testing  
is really no big deal.

I also have to note that, based on the total lack of support from  
users or developers for the concept of "type-safe Tapestry", I'm  
afraid Kent is the only one who doesn't see that he is pulling in a  
different and ultimately counterproductive direction.

I apologize for being so blunt, especially since I'm not a Tapestry  
developer (besides a couple of minor patches) and only sporadically  
contribute to the user list. However, this particular issue appears  
very clear-cut to me and I think if Tapestry developers have a  
similar opinion (which I suspect they do) they should put the kibosh  
on this and move on towards a 5.0 release.

-Ryan





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


Re: Notes on "type safe" Tapestry 5

Posted by Kent Tong <ke...@cpttm.org.mo>.
Howard Lewis Ship <hlship <at> gmail.com> writes:

> CompoundalidatorGenerator should be named CompoundValidatorGenerator.

Right!

> FormPersistWorker: the BodyBuilder utility is useful for assembling
> Javassist code piecewise. 

Thanks for the tip!

> Also, Javassist must have gotten more
> liberal about what it accepts as a "body", it used to be that you had
> to enclose multiple statements inside braces.  Maybe extendMethod() is
> different from creating a new method.

The collectFormPersistPropNames() method needs to call 
super.collectFormPersistPropNames(). Therefore, I am using extendMethod().
However, it does seem that addMethod() is a safer choice.

> InternalClassTransformationImpl: findFieldsWithAnnotation() has been
> uselessly overriden (the alternate version, with the searchAncestors
> parameter) is not actually used and does not doing anything with that
> parameter.

Right. I forgot to remove it after failed attempt.

> So ... is parameter binding just for informal parameters now?

Yes.

> So ... you have to be explicit about using an Any component?

Yes. It needs a bit more typing (and editing the Java file), but
it enforces a better separation between HTML code and Java code
and makes the configuration code (binding) subject to compile-
time checking, auto-completion and refactoring.

> There's no longer any check for unbound parameters.  I guess that too
> is up to individual components to check, probably inside  <at> SetupRender.

Yes.

>  5.0.2-SNAPSHOT includes additional annotations for hooking into page
> lifecycle, so  <at> PageLoaded would also be good, I guess. I'm finding the
> relationship between parameters and lifecycle a bit fuzzy.

The configure_xxx() method is called just before SetupRender. This allows
the component to render multiple times in a loop. Therefore, I think
PageLoaded is not a suitable moment for configuration.

> So ... for parameters where the value changes often (i.e., at least
> per-render), it is necessary to
> keep invoking the parent component's configure_foo() method (which has
> to be public, though that could be fixed).

Yes, that's what I have been saying. Configuration is a per-render
thing.
 
> So, what you're really saying is that people are going to prefer option A:
> 
>   <t:comp id="showProperties">
>      ...
>                 <t:comp id="propLoop">
>                                     <dt>${propertyName}</dt>
>                                     <dd>${propertyValue}</dd>
>                   </t:comp>
>    ...
>   </t:comp>
> 
> with
> 
>     public void configure_showProperties()
>     {
>         _showProperties.setTest(getShowPropertyList());
>     }
> 
>     public void configure_propLoop()
>     {
>         _propLoop.setSource(getInfo().getPropertyNames());
>     }
> 
> to:
> 
> <t:comp type="If" test="showPropertyList">
>   ...
>   <t:comp type="Loop" source="info.propertyNames" value="propertyName">
>           <dt>${propertyName}</dt>
>            <dd>${propertyValue}</dd>
>    </t:comp>
>   ...
> </t:comp>
> 
> with
> 
> ... nothing ...

Yes, I believe more Java users prefer option A especially when most of
the Java code in option A can be generated using a code template.
There is really no much more typing required, while we enjoy the
warm and fuzzy feeling of compile-time checking and auto-completion.

> I don't totally follow what is going on in terms of form support
> (though I think it could be implemented less obtrusively using
> ComponentActions and some code generation, and maybe some changes to
> FormSupport) but I'm finding some aspects of it a bit worrysome
> (particularily the fact that disabled is NOT re-evaluated on form
> submit).

The point about re-evaluating "disabled" is something that I haven't 
been able to understand. If we render a field and decide that "disabled"
should be true, then on submission it should remain true, right? 
Otherwise it will become inconsistent. If it must remain unchanged,
why re-evaluate it? Doing so will only give rise to inconsistence.

> I believe your value statement is that TypeSafe Tapestry makes the
> code more correct and more readable, allowing for IDE support in terms
> of available parameters (they are just setter methods) and parameter
> type.

Yes.

> I think you are correct, the code is more type safe, but does so by
> being more rigid. 

I don't think it's more rigid. But that depends on what you mean by
rigid. Something that has gone in type safe Tapestry is that automatic
conversion of data to a required type. To do that now you must be
explicit about it. I think this is a case about explicit vs auto-magic.
I don't know how many Java programmers would prefer option A:

List list = ...;
if (list) {
  ...
}

to option B:

List list = ...;
if (!list.isEmpty()) {
  ...
}

Obviously the designers of Java didn't think so. In contrast, those of 
PHP did. As our users are Java programmers, I tend to believe that they
prefer the Java way, not the PHP way.

> We've shifted more of the responsibility onto the
> developer and away from the framework. 

I think this is not the case.

> This is true both for the
> author of the component (more setter and getter methods) 

One can just choose "Source | Generate getters and setters". This is
hardly a burden. With the native property support in Java 7, this
won't even be required.

> and for the
> user of the component (the need for lots of configure_foo methods, the
> need to be aware of which are properties and which are bindings).

The configure_foo() methods are just replacements for the bindings.
There is hardly any difference in terms of effort required.

The component user is now clearly told which are properties and which
are bindings. In the past, they are not told about it but they must
still know about it (eg, to make sure the "value" binding points to
the right place on rewind)

> I think the templates suffer. They are less readable, more in service
> to the Java code and less readable (containing less useful
> information) than with parameter bindings in place.

I agree that putting the logic into templates makes the templates 
easier to read, however, this is a maintenance nightmare: Do we
want JSP/ASP files that contain lots of Java code? Isn't that a
reason why people moved to MVC in Java and code-behind in .NET?

> In T3/T4 I found
> that too many users were not providing explciit ids for components, so
> T5 gives you a reward (don't have to bind value) and a better default
> id when the id is omitted (the component type in lower case).  With
> TypeSafe, you must give each component, no matter how trivial, an
> explicit id in order to be able to configure its properties.

True. This is traded for the protection when we later rename the
property (refactor). The code will continue to work.

> There's some issues with flexibility.  Component A renders component
> B, which has a parameter set from a property of component A.  Inside
> B's body, there's a component C that modifies the property of A.  When
> does B see that change?  Not until it starts a completely fresh
> render. This kind of thing happens in more complex components, such as
> BeanEditFor and Grid (today) and the Ajax components coming in the
> future.

Then the parameter value should be a value source object, not the 
value itself. As this is made explicit, the component user will know
that he can change it during rendering.

> There are performance issues (that could be addressed in non-prototype
> code). There are other performance issues (some of the form related
> stuff) that may be more difficult to address.  Sorry, FUD ... slower
> than T5/trunk is not a peformance problem, just a difference.

Right.

> Where do we stop?  Isn't the ${property} syntax just as questionable?
> It's not type safe (less important because it will always be converted
> into a string), but the same kind of refactoring changes that cause
> issues (addressed by TypeSafe Tapestry) will break property names in
> the templates, causing runtime exceptions.

I think making it ${id} may help. The Java code can be generated using
a simple code template.

If the property name is changed, it will still work.

If the id is changed in either the template or the Java file but not the 
other side, then there will be a warning when the page is loaded (not as 
good as compile time checking but slightly better than runtime exception).

> Lastly, there's the issue of compile time safety vs. working code.
> Code that compiles cleanly doesn't necessarily work. Testing is
> necessary on top of clean compiles.  In the dynamic land, such as
> Ruby, code can be "untyped" and still industrial strength because they
> test the hell out of things.  With your own contributions, plus
> Selenium, plus the clean POJO components, that is true for T5 as well
> ... fully, easily testable.

I agree that compile time checking doesn't mean the code is working.
In fact, I consider testing very critical in software development 
(otherwise I wouldn't have worked on the PageTester). However, I 
believe compile time checking is an important element in order to
efficiently produce working code. We all know that detects should
be detected and fixed as early as possible (the later it is fixed, 
the more costly it gets, up to 100 times); Compile-time checking
exactly gives us that kind of early detection.

I agree that there are many people who prefer dynamic typed languages
(PHP, Ruby) to static typed languages (Java, C#). Just that I think
the targeted users of Tapestry use Java, they should prefer compile-
time checking.

> Further, with T5's ability to do extensive type coercions efficiently
> and invisibly, many of the changes necessitated by refactoring do go
> away.

I think the single most common reason for refactoring is the desire to 
rename. Personally I seldom rename the type of fields.

> Finally, and this is much more subjective than the rest (which is
> already subjective), this just doesn't "feel" as much like Tapestry.
> All the other changes in T5 are just T4 with the chains removed.
> Souped up. Stream lined. Smarter defaults. Less code to accomplish the
> same thing. TypeSafe does more to change the basic nature of Tapestry
> than the new T5 code base does in an of itself.

As you noted, it may or may not seen as nature-changing:

1) In terms of effort, it took only a weekend to implement the type 
safe feature. Everything still works. So, it is not a significant 
change in this regard.

2) In your mind, I am sure it is a huge change. Personally I find it
is still Tapestry, just better. Everything else is there (component,
class transformation and reloading, life cycle, pooling, IoC). The 
only thing changed is how to set the properties of a component.

3) From a recent post by a Tapestry committer on the server side, he 
thought an advantage of Tapestry was its support for compile-time checking. 
There are also people explicitly asking for compile-time checking on the 
mailing list. So, for people like them, this is not something that will 
destroy Tapestry, but make it better.

However, I think whether it is nature-changing is really unimportant.
The success of Tapestry is our goal. How to make it a success? It does
NOT depend on whether I like it or not. It solely depends on whether
our targeted users like it or not. It is unimportant that I find type 
safe Tapestry better. It is important that we find out if our targeted
users find it better or not. That's all what I have been asking for.

It is an experiment. We should not trick people into believing that it is
here to stay. However, if all the reasons for accepting or rejecting it 
is debatable (some people like it but some people don't), then not 
giving them an opportunity to even take a look at is IMHO not in the 
best interest of the project.

--
Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT)


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


Re: Notes on "type safe" Tapestry 5

Posted by Kent Tong <ke...@cpttm.org.mo>.
Howard Lewis Ship <hlship <at> gmail.com> writes:

> The FormPersist annotation is very clever and useful.  I'm a little
> troubled that a field's label and disabled flags are persisted in the
> form. The label should just be available again, and the disabled flag
> is something I'd like to recompute when the form is submitted.  

Thanks for looking at the code.

The label may have been set in a loop (eg, name1, name2). The container
certainly could make it available on form submission, but the component
should be told what to do when it is kicked off (rendering) and then
automatically do its work, without bothering the container again.

I don't understand why the disabled flag should be recomputed.

> Also, a persistence strategy of "form" may be preferable to a new
> annotation.

As I documented in the FormPersist file,  I think it doesn't fit in as 
a persistent field strategy because such persistent fields are restored 
at the moment the page is attached, which doesn't work for form 
submissions and doesn't work if the component is in a loop.

> It's also very heavily tied to AbstractField implementation (the
> collectFormPersistPropNames).  

Why do you say that? The logic is in RestorePropertiesAction. As long
as the component implements FormPersistPropertySource to provide the
collectFormPersistPropNames() method, then it will work. For example,
The BeanEditForm and the Loop components also implement
FormPersistPropertySource and have @FormPersist properties.

> Please spell out "property".

OK.

> This means that it will be harder to create a "composite field" component
> that implements the Field interface and delegates out to a number of
> real fields.

Such a component can implement FormPersistPropertySource and then let 
RestorePropertiesAction do the work.
 
> I'm not happy with the hooks into Loop to support Forms via
> RestorePropertiesAction.storeAction(). This seems like something that
> should be done inside Form/FormSupport or make use of the Heartbeat
> environmental service in order to occur as part of the Loop without
> tying the two classes so closely together.  You don't see a lot of
> class-calling-class in Tapestry, its usually
> implementation-calls-interface.

OK.

> I particularly don't like the way that BindingExprValueConduit works,
> it's not very IoC ... instead, it forces every component to implement
> these additional service interfaces (BindingSourceProvider).  It looks
> like these things get persisted into the form as well (which would
> explain the need for lookup, since IoC service proxies don't
> serialize).

Right. A solution may be to make the infrastructure available through
each enhanced component class. It takes a few more byte codes, but if
it is not called, it won't slow down anything.

> So now containers have to implement a configure_foo() method for each
> component.  Underscores?  Since ids are unique (caselessly) then it
> could be configureFoo() which would be more consistent with, say,
> Tapestry IOC & etc.

Yes, I want configureFoo() a lot, but in order to write a code template
in Eclipse, the best I get is:

@Component
private ${type} _${id};

public void configure${id}()
{
	_${id}.set${name}();
}

Then the method will become configurefoo(). 

> Why a seperate method for each component? Since components appear to
> always be instance variables now, a single method per container
> component could configure all contained components.

Not really. A component could be rendered multiple times in a loop.

> Please avoid abbreviated names like "Expr" for "Expression".  In fact,
> setValueBindingExpr() could be called setValueBinding() or even
> bindValue().

OK.

> Ouch.  RestorePropertiesAction is also based on reflection to read the
> property values that will be stored into the form.  Much better to
> gain access to a PropertyAccess service or better yet, a
> PropertyConduit (which avoids reflection in favor of bytecode
> generation).

OK.

> OK ... I'm pulling down large scale diffs to see how everything fits
> together.  I'm beginning to think that components must re-configure
> themselves (invoke a configure method on their parent) as part of
> their lifecycle?

Yes.

> It looks like  <at> Parameter is just completely gone.   Performance issue:
> caching. As fast as methods can be invoked via PropertyConduit (i.e.,
> via bytecode generation), if the method called is slow, that's a
> problem. I guess there's just a tiny minority of "parameters" that are
> read/write and those are not read or written very often, so just FUD.

Right.

> Looks like much more stuff must be serializable (related to
>  <at> FormPersist). A long term philosophy in Tapestry has been "store only
> what cannot be recreated".  This approach seems more like "store
> everything" (on the client)".  I can hear the .Net jokes coming 

True. Storing only what cannot be recreated has the advantage of 
better performance. Storing what can be stored has the following 
advantages:
1) You just kick off the component and then it will do the job
without you worrying about helping it later (of course, if the 
component needs to write values back to you, you have to make sure 
there is a proper place to write). It means it takes more work to 
write the component, but it is easier to use the component.

2) This very much reduces the possibility of having a different 
parameter value on form submission from rendering. For example, it's
quite hard to debug if the SelectModel has changed because it depends
on some other value.

> Nope, looks like the configure_foo methods are invoked via REFLECTION.
> Ick.  This is someting that could be done by writing code to invoke
> the configure method, and doing so with a
> ComponentClassTransformationWorker.  And this occurs from just before
> the SetupRender state during rendering.

I tried exactly that (ComponentClassTransformationWorker) without 
success. It has something to do classloaders. The code generated
uses a type cast which fails at runtime.

> This basically assumes that all the properties of a component will be
> stable for the duration of the component's rendering.

Yes.

> I guess all the properties will be reset at the end of the request.

Yes.

It's quite late. I'll reply to the other points later...

--
Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT)


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


Re: Notes on "type safe" Tapestry 5

Posted by Jesse Kuhnert <jk...@gmail.com>.
That was definitely a thorough review. ;)

This actually recently came up on the TestNG users list where people
were grumbling about the type safety sort of concerns. (well,  only
one person actually ) The general feeling I got was that "it's
unfortunate the annotation spec is incomplete in this regard, oh
well...it's still better than what we were doing before annotations" .

I am not worried about the type safety concerns for the following reasons:

-) IMHO this is clearly a case of the jdk just not being caught up
with what is now almost the entire "major" development community.

-) The general argument (and even name of the branch) suggested that
this was to help people using IDE tools. If that's all they need
there's nothing stopping anyone. It certainly didn't stop Alexei from
providing asset/ognl/property/message catalog/etc autocompletions for
Tapestry users within the IDEA IDE.
(http://handyedit.com/completions.html )

If we really do care about these IDE issues enough to expand this much
effort into it then fine, but let's put it in the IDE.

-) Dynamic (-ish in the case of Java) language support is here to
stay. It's convenient/ expressive / logical. The people who care about
IDE support only represent one portion of the user base. The rest of
us actually like the dynamic typing.

-) As Howard has already solved the toughest nut of all - dynamic
reloading of class changes - most of these concerns sort of evaporate
into the wind..People using pure dynamic languages have enjoyed this
simple sounding ability for years. It hasn't really seemed to hamper
them overly much, why are we different?

I'm not "completely" against this kind of static typing support, just
when it goes into T5 directly and in my view "tarnishes" all of the
forward progress it has made. (perhaps even worse than T4). I'm not
necessarily right, but I don't see why this can't go into an IDE
plugin if people really feel strongly enough about it. That's what
plugins are for right? =p

On 2/12/07, Howard Lewis Ship <hl...@gmail.com> wrote:
> Kent has put a lot of work into a "type safe" Tapestry 5.
>
> I'm begining to work through the code changes.
> <snipped>

-- 
Jesse Kuhnert
Tapestry/Dojo team member/developer

Open source based consulting work centered around
dojo/tapestry/tacos/hivemind. http://blog.opencomponentry.com

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