Re: T5: which way do you prefer?
This is just an unfortunate example where the jre evolution hasn't been able to keep up with technology...Other projects using annotations suffer from the same problems. I think the only viable solution for compile time checking is getting it in the form of IDE help until the jdk catches up. For instance, I've seen but not confirmed that ognl expressions are resolved by this plugin: http://handyedit.com/handytapestry.html On 2/2/07, Onno Scheffers <[EMAIL PROTECTED]> wrote: Kent Tong wrote: > Alternatively, a type-safe setter style: > I would personally love type-safety. Currently my biggest gripe with Tapestry is the lack compile-time error-checking (and on-the-fly error-checking of my IDE) and lack of code-completion. A lot of stuff is currently (T4) configured using specific textual strings. You have to learn them by heart or keep documentation ready all the time and it is very easy to make a typo that will only show up on runtime. This decreases productivity for me. I lost count of the number of times I mixed up 'listeners:' with 'listener:' or 'beans:' with 'bean:' and other small mistakes. You won't notice them until you startup the application. That still gives me a JSP'isch feeling and basically means you have to put much more effort into testing each conditional block on the page on runtime Any IDE would give you code-completion when using setter-style code in the library. It _may_ be more typing (although I doubt it because of code-completion) but it would be easier to learn, easier to to write supporting tools for, faster to develop for (less looking through documentation for people that don't know the documentation by heart) and on top of that deliver better quality code since your IDE will help spot typos as you type and the compiler will spit out errors if you make a mistake before running. All IMHO of course :o) Regards, Onno - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
Kent Tong wrote: Alternatively, a type-safe setter style: I would personally love type-safety. Currently my biggest gripe with Tapestry is the lack compile-time error-checking (and on-the-fly error-checking of my IDE) and lack of code-completion. A lot of stuff is currently (T4) configured using specific textual strings. You have to learn them by heart or keep documentation ready all the time and it is very easy to make a typo that will only show up on runtime. This decreases productivity for me. I lost count of the number of times I mixed up 'listeners:' with 'listener:' or 'beans:' with 'bean:' and other small mistakes. You won't notice them until you startup the application. That still gives me a JSP'isch feeling and basically means you have to put much more effort into testing each conditional block on the page on runtime Any IDE would give you code-completion when using setter-style code in the library. It _may_ be more typing (although I doubt it because of code-completion) but it would be easier to learn, easier to to write supporting tools for, faster to develop for (less looking through documentation for people that don't know the documentation by heart) and on top of that deliver better quality code since your IDE will help spot typos as you type and the compiler will spit out errors if you make a mistake before running. All IMHO of course :o) Regards, Onno - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
I hate typing I am not Sam G :-) Gosh, my first day back on the list in any significant way in nearly two months, and I stumble into a reference to me. I must be famous ;-) I don't have any real comment to add to the initial question since I have no familiarity with Tap5 development, but I would like to point out that when developing a framework, assuming that a mechanism is sufficient purely because an external IDE can simplify the task is not going to lead to good design in the long run. IDEs evolve and development environment requirements vary from project to project. the only IDE I use is vi, and while I do type fast, I have no interest in typing any more than is necessary. Relying on completion in order to justify very long variable names strikes me as a bad strategy. Heck, printing the source code is argument enough against allowing super long variable and method names wherever possible, never mind that I work with a 79 character line in all my code purely for on-screen readability and xterm compatibility. My biggest gripe with Tapestry in general (I'm in Tap 4.0 except for some experiments in 4.1) is the lack of compile time error checking for much of the tapestry 'code' you wind up writing. As a project grows, the init time for the application can become significant (as can the compile time) and build/deploy/test cycle can become unbearably slow when it turns out you've got some stupid typo that wasn't caught because a file wasn't compiled (and the PermGen thing effectively prevents working with caching disabled, since things get unpredictable). So while I don't understand the nuance of the question that started this thread, if one option results in better compile time error checking, I'm all for that one. --sam - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
Yeah ... I didn't say this in my earlier post, I understand having multiple methods to allow for easier upgrades. But after suitable discussion and opportunity for users to try in the field, "one" correct method should be chosen with the other options available as a optional plugin. Realistically once you have thoousands of components written migrating to the latest "one" true way is a pain-in-the-ass, no-value-added hassle that forces established tapestry installations to stay with old versions -- so that optional plugin is only optional from a "decision to use it" perspective not a "decision to build it" perspective. Ideally, we really want people to be able to move easily from Tap3 to Tap5. And if it is not super easy many developers will never be able to convince their managers that it is worth the hassle. -Pat On 1/28/07, RonPiterman <[EMAIL PROTECTED]> wrote: Martin Strand wrote: > No, leaving the decision up to the developer is not a solution at all. > Tapestry should have one proper way to do things and if someone is not > satisfied with it they can use a 3rd party lib that provides the > functionality they need. This will also reduce confusion for newcomers. > I'd prefer o leave parameters as they are (ie > parameters={"color=color"}) but the most important thing is that there's > one "proper" way to do things. I thought to keep out of this discussion, but I couldn't help it: Yes, where its possible: one way to do things. taking the xml out is a bless, now one can define components in "only" two ways instead of 3... but I would vote for the (until now unpopular) binding: @Bindings([EMAIL PROTECTED](name="...",value="...")}) but I guess noone (except me) likes that extra typing... :( Cheers, Ron I hate typing I am not Sam G :-)
Re: T5: which way do you prefer?
Martin Strand wrote: No, leaving the decision up to the developer is not a solution at all. Tapestry should have one proper way to do things and if someone is not satisfied with it they can use a 3rd party lib that provides the functionality they need. This will also reduce confusion for newcomers. I'd prefer o leave parameters as they are (ie parameters={"color=color"}) but the most important thing is that there's one "proper" way to do things. I thought to keep out of this discussion, but I couldn't help it: Yes, where its possible: one way to do things. taking the xml out is a bless, now one can define components in "only" two ways instead of 3... but I would vote for the (until now unpopular) binding: @Bindings([EMAIL PROTECTED](name="...",value="...")}) but I guess noone (except me) likes that extra typing... :( Cheers, Ron On Sat, 27 Jan 2007 18:01:41 +0100, Hugo Palma <[EMAIL PROTECTED]> wrote: I think both are valid options. In my opinion both ways should be provided by the framework and it should be a developers decision to use the one that fits his needs/taste. Question: what would happen if the developer configured the same component both ways in the same page (by mistake or something) ? I think that this shouldn't be allowed and a runtime exception should be thrown. This would prevent some "distraction" programming errors. Kent Tong wrote: Hi, In T5, how would like to configure a component? For example, let's imagine a component type ColorText that outputs a string in a certain color. You're now using this component in a page. First, an all-binding style (same concept as in T4): @ComponentClass public class MyPage { @Component(parameters={"color=color", "text=literal:I am in red"}) private ColorText _colorText; public Color getColor() { return Color.RED; } } Alternatively, a type-safe setter style: @ComponentClass public class MyPage { @Component private ColorText _colorText; //This method will be called just before the component _colorText //is rendered. public void configureColorText() { _colorText.setColor(Color.RED); _colorText.setText("I am in red"); } } This ColorText will not update any value on form submission so all we need is to provide values to its parameters. If it was a TextField, then the two approaches will be like: The all-binding style: @ComponentClass public class MyPage { @Component(parameters={"value=name", "validator=required,minLength=10"}) private TextField _textField; private String _name; } The type-safe setter style: @ComponentClass public class MyPage { @Component private TextField _textField; private String _name; public void configureTextField() { _textField.setValueBinding("name"); //read and write _textField.setValidator(new Required(), new MinLength(10)); ... } } So far, I've collected the following PROs and CONs for each approach. The all-binding style: 1) Less typing. 2) Automatic data type conversion. For example, if a parameter is expecting an Iterable, you can pass it a binding expression that returns an array. Tapestry will automatically convert it to an Iterable. 3) Consistency across all parameters. They will use bindings no matter they only read the value or perform read and write. The type-safe setter style: 1) IDE auto-completion. The IDE will help you input the setters and the parameter values. 2) Compile time parameter name checking. If you get the name of parameter wrong, the call to the setter simply won't compile. 3) Compile time parameter value type checking. If you pass say a String to setColor(), it simpy won't compile. 4) Refactoring. If you rename a parameter, the calls to the setter will be changed automatically. 5) The Javadoc of the component class is the component doc. No need to devise a new mechanism to write component doc. 6) Easier user level innovation. For example, if one would like to write a new Validator, it's easier because it's just a Java class. With the all- binding style, one will have to come up with a initializer syntax, register it using a configuration under a validator name, while it's still limited to having a single argument. The above is just my observations. What's your take? Which one would you use if both are available in T5? - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
Hi there -- I prefer the explicit "configure*" method approach for most of the reasons mentioned by Kent in his original post, but also for these major reasons: Reduced ramp-up time for a new developer - Under the current annotation approach, new developers have to learn new syntax and tricks to do things that they already knew how to do in java. ( i.e. use setters/getters) Using the configure approach, the only extra thing they need to learn is this configure* method signature. Given a choice between a new developer learning tapestry uniqueness and learning company-specific issues and code, I chose company-specific each and every time -- that is how they are going to add value the fastest to the company's code. Works with existing tools - I know annotations, are hot and useful but as far as I can tell using the bindings with in a @Component add nothing that could not be done with *less* typing using the configure*() method. Why less typing? I use autocomplete on Eclipse! long variable names? no problem. Developers who accidently misspelled a method name? no problem. Supports refactoring. If I refactor using the existing annotation scheme I have to manually change all the bindings! Talk about a disincentive to being agile! Then everywhere the component is used I have to test to make sure that nothing got missed. double-yech. Using configure*() reduces the possible places I could screw-up. Isn't that what tools and frameworks are supposed to do? [Yes I know that I could still have problems in html files -- see below] Debugging and learning --- If a new-to-tapestry developer or an even a tapestry expert is debugging a component, a configure*() method would provide a valuable place to stick a breakpoint. In this method you would see the component fresh out of the component pool and you could step through it as the component and (its subcomponents initialize). May not be a big deal to the tap experts, but would have shortened my learning curve. Documentation -- As in one less thing for the Tapestry developers to document. While the tapestry documentation isn't horrid it isn't the best either. Documentation is always the last thing to be done (if ever). All the documentation about the special binding/validation syntax (and bug testing, and bug fixing, etc) would go away. Reduces the need for special tool support There was much hand-wringing about spindle's development being dropped, because tools are necessary. Well how about making it so that *existing* tools, supported by others outside the Tapestry community, do the trick? This lets the Tapestry community support those other tools, avoid custom solutions that depend on the good graces of a single developer, and broadens the number of people already familiar with the tools that they need to know to be productive using Tapestry. Custom tools would still be needed to help support refactoring of methods within html files but this problem is smaller than having to support refactoring within html files, binding annotations, .jwc files and .page files. Thanks for listening... -Pat Moore
Re: T5: which way do you prefer?
Howard Lewis Ship gmail.com> writes: > Thing is, that would have to be > _textField.setValidator("required,minlength=10"). > > The way the validate binding factory works, it needs to know a lot > about the component being bound as well as the container component. > That's how it obtains the field's label (for presenting error > messages), how it access's the containers catalog (to looks for > approprately keyed messages), The component should provide itself (or its ComponentResources) as an argument to the check() method of FieldValidator. As this info is supplied at the time of the call, we don't need to provide it at construction time: _textField.setValidator(new Required(), new MinLength(10)); This may allow us to pool and share validators (eg, "Required" as it isn't bound to any particular component). Again, this is static structure, dynamic behavior. > and eventually, how it will provide an > automatic default for the validators based on annotations on the > setter method. The component can determine default validators before rendering, also based on the setter method. This logic can be extracted to a single class, maybe even a mixin. > 4) Less code when writing components. You just provide the field and > access it freely. > You don't have to worry about what's a simple property and what's a > bi-directional parameter, they look the same to you. I think with a bit of annotation and byte code generation, this can be done for the type safe setter approach: class TextField { @Binding private Object value; private Validator validator; } > You don't have to > worry about field converstions. You don't have to provide getter and > setter methods (except for testing). True. Those are trade-offs for compile time checking. > Unless you provide a TypeCoercer from String to Color. Again, trade off for compile time checking. > > 4) Refactoring. If you rename a parameter, the calls to the setter will > > be changed automatically. > > Though this will break existing code, whereas implementing T4's > parameter aliases would allow existing code to work after an upgrade, > with warnings. For the code inside the same project, refactoring will work just fine. For other code, there will be compile errors, which is a good thing as it is tell us something is wrong. The case about parameter alias is not really the same thing. I may just rename a parameter during development because I found a better name. I don't want to keep the old name around. If we really want to achieve the same effect as parameter alias, we can just provide a new setter and mark the old setter as deprecated, using the standard Java mechanism. The warnings will be seen at compile time. It is also easier for Java developers to understand. > Javadoc with privates included can cover this. Perhaps some form of > JavaDoc extension that omits privates, but includes Parameter fields. Exactly what I was talking about. We need to devise new mechanisms to do what the existing mechanisms in Java are doing fine. > Component (parameters="validate=prop:myFieldSpecialValidator") > private TextField _myField; > > public FieldValidator getMyFieldSpecialValidator() > { return new FieldValidator() { ... } ; } True, but this will not work when we need multiple validators. Yes, I know about the $bean notation. This is another example of devising new mechanisms for work that can already be done. All we need is to provide a list of objects (validators) that has access to the field. -- Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT) - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
Howard Lewis Ship gmail.com> writes: > For me, the issue is that this puts an onus on the developers (us!) to > write much more code for components, while limiting their > functionality in the process (locking down some parameters as simple > read-only properties). Are you concerned that someone may change a parameter value when the component is rendering? > There's a lot of work involved in getting a parameter to work > properly, cache its value, reset at the end of the request, etc., > etc., that under the current system, is handled efficiently and > automatically with runtime bytecode generation. In the type safe setter style, the parameter values are cached in as properties. They are reset at the end of the request. The calls to the setter is compiled. What is missing? -- Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT) - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
Howard Lewis Ship gmail.com> writes: > T5 components have a very definite construction-phase (where they are > hooked up, parameters are bound, etc.) followed by a production-phase. > > The new methods you are talking about are contruction-phase only. But > what happens if they are invoked in production? The type safe setter style works in production. That is, the configuration of a component occurs in production (before it's rendered), after the component is constructed once (which does not include binding parameters to expressions to be evaluated later). > Case 1: the change is accepted and now this instance of this component > within this page instance behaves differently than any other instance, > which breaks down Principal 1: Static Structure, Dynamic Behavior. I don't think this is the case. A component instance in one page instance is exactly the same as others in other page instances. They all have their parameters (just properties) initialized to their default values. Before they're rendered, their containers need to set their properties. > Case 2: The code has to make a "locked down" check, which introduces a > new class of bugs where the check is omitted. I don't know why there needs a locked down check. Would you give an example? -- Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT) - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
hehe, great ren & stimpy reference.. 2007/1/27, Jesse Kuhnert <[EMAIL PROTECTED]>: No sir, I don't like it. On 1/27/07, Kent Tong <[EMAIL PROTECTED]> 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- /ted - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
I find the annotation approach easier to grok. It's clearer as it keeps all of the component configuration in a single (concise) place in the code. I agree with Martin that there should be a /single/ approach to binding, not multiple. I think consistency with the way that parameters are bound in the template is a good thing. As for type safety... much less of an issue for me with the T5 class reloading logic. Binding types are easily caught, and easily/quickly fixed. Robert On Jan 27, 2007, at 10:36 AM, Kent Tong wrote: Hi, In T5, how would like to configure a component? For example, let's imagine a component type ColorText that outputs a string in a certain color. You're now using this component in a page. First, an all-binding style (same concept as in T4): @ComponentClass public class MyPage { @Component(parameters={"color=color", "text=literal:I am in red"}) private ColorText _colorText; public Color getColor() { return Color.RED; } } Alternatively, a type-safe setter style: @ComponentClass public class MyPage { @Component private ColorText _colorText; //This method will be called just before the component _colorText //is rendered. public void configureColorText() { _colorText.setColor(Color.RED); _colorText.setText("I am in red"); } } This ColorText will not update any value on form submission so all we need is to provide values to its parameters. If it was a TextField, then the two approaches will be like: The all-binding style: @ComponentClass public class MyPage { @Component(parameters={"value=name", "validator=required,minLength=10"}) private TextField _textField; private String _name; } The type-safe setter style: @ComponentClass public class MyPage { @Component private TextField _textField; private String _name; public void configureTextField() { _textField.setValueBinding("name"); //read and write _textField.setValidator(new Required(), new MinLength(10)); ... } } So far, I've collected the following PROs and CONs for each approach. The all-binding style: 1) Less typing. 2) Automatic data type conversion. For example, if a parameter is expecting an Iterable, you can pass it a binding expression that returns an array. Tapestry will automatically convert it to an Iterable. 3) Consistency across all parameters. They will use bindings no matter they only read the value or perform read and write. The type-safe setter style: 1) IDE auto-completion. The IDE will help you input the setters and the parameter values. 2) Compile time parameter name checking. If you get the name of parameter wrong, the call to the setter simply won't compile. 3) Compile time parameter value type checking. If you pass say a String to setColor(), it simpy won't compile. 4) Refactoring. If you rename a parameter, the calls to the setter will be changed automatically. 5) The Javadoc of the component class is the component doc. No need to devise a new mechanism to write component doc. 6) Easier user level innovation. For example, if one would like to write a new Validator, it's easier because it's just a Java class. With the all- binding style, one will have to come up with a initializer syntax, register it using a configuration under a validator name, while it's still limited to having a single argument. The above is just my observations. What's your take? Which one would you use if both are available in T5? -- Author of a book for learning Tapestry (http://www.agileskills2.org/ EWDT) - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
No sir, I don't like it. On 1/27/07, Kent Tong <[EMAIL PROTECTED]> 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
No, leaving the decision up to the developer is not a solution at all. Tapestry should have one proper way to do things and if someone is not satisfied with it they can use a 3rd party lib that provides the functionality they need. This will also reduce confusion for newcomers. I'd prefer o leave parameters as they are (ie parameters={"color=color"}) but the most important thing is that there's one "proper" way to do things. On Sat, 27 Jan 2007 18:01:41 +0100, Hugo Palma <[EMAIL PROTECTED]> wrote: I think both are valid options. In my opinion both ways should be provided by the framework and it should be a developers decision to use the one that fits his needs/taste. Question: what would happen if the developer configured the same component both ways in the same page (by mistake or something) ? I think that this shouldn't be allowed and a runtime exception should be thrown. This would prevent some "distraction" programming errors. Kent Tong wrote: Hi, In T5, how would like to configure a component? For example, let's imagine a component type ColorText that outputs a string in a certain color. You're now using this component in a page. First, an all-binding style (same concept as in T4): @ComponentClass public class MyPage { @Component(parameters={"color=color", "text=literal:I am in red"}) private ColorText _colorText; public Color getColor() { return Color.RED; } } Alternatively, a type-safe setter style: @ComponentClass public class MyPage { @Component private ColorText _colorText; //This method will be called just before the component _colorText //is rendered. public void configureColorText() { _colorText.setColor(Color.RED); _colorText.setText("I am in red"); } } This ColorText will not update any value on form submission so all we need is to provide values to its parameters. If it was a TextField, then the two approaches will be like: The all-binding style: @ComponentClass public class MyPage { @Component(parameters={"value=name", "validator=required,minLength=10"}) private TextField _textField; private String _name; } The type-safe setter style: @ComponentClass public class MyPage { @Component private TextField _textField; private String _name; public void configureTextField() { _textField.setValueBinding("name"); //read and write _textField.setValidator(new Required(), new MinLength(10)); ... } } So far, I've collected the following PROs and CONs for each approach. The all-binding style: 1) Less typing. 2) Automatic data type conversion. For example, if a parameter is expecting an Iterable, you can pass it a binding expression that returns an array. Tapestry will automatically convert it to an Iterable. 3) Consistency across all parameters. They will use bindings no matter they only read the value or perform read and write. The type-safe setter style: 1) IDE auto-completion. The IDE will help you input the setters and the parameter values. 2) Compile time parameter name checking. If you get the name of parameter wrong, the call to the setter simply won't compile. 3) Compile time parameter value type checking. If you pass say a String to setColor(), it simpy won't compile. 4) Refactoring. If you rename a parameter, the calls to the setter will be changed automatically. 5) The Javadoc of the component class is the component doc. No need to devise a new mechanism to write component doc. 6) Easier user level innovation. For example, if one would like to write a new Validator, it's easier because it's just a Java class. With the all- binding style, one will have to come up with a initializer syntax, register it using a configuration under a validator name, while it's still limited to having a single argument. The above is just my observations. What's your take? Which one would you use if both are available in T5? - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
Another rationale for the current approach is to keep control over the lifecycle of the component. T5 components have a very definite construction-phase (where they are hooked up, parameters are bound, etc.) followed by a production-phase. The new methods you are talking about are contruction-phase only. But what happens if they are invoked in production? Case 1: the change is accepted and now this instance of this component within this page instance behaves differently than any other instance, which breaks down Principal 1: Static Structure, Dynamic Behavior. Case 2: The code has to make a "locked down" check, which introduces a new class of bugs where the check is omitted. There were bugs in T4 and earlier where construction-phase methods were invoked in production. Again, these things would work for an individual developer, but would fail once multiple users and full pooling were employed in production. Nobody wants to get insane behavior out of their running application. -- 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
On 1/27/07, Hugo Palma <[EMAIL PROTECTED]> wrote: I think both are valid options. In my opinion both ways should be provided by the framework and it should be a developers decision to use the one that fits his needs/taste. For me, the issue is that this puts an onus on the developers (us!) to write much more code for components, while limiting their functionality in the process (locking down some parameters as simple read-only properties). There's a lot of work involved in getting a parameter to work properly, cache its value, reset at the end of the request, etc., etc., that under the current system, is handled efficiently and automatically with runtime bytecode generation. There was an endless slew of bugs in the Tapestry 2 time frame with people who didn't understand the nuances of page, component and parameter lifecycle. The worst thing is when code works under a light developer load, and then fails in production. A lot of Tapestry historically has been shielding the user so that code that appears to work in development will in fact be just as valid, threadsafe, session-aware, etc. in production. -- 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: T5: which way do you prefer?
On 1/27/07, Kent Tong <[EMAIL PROTECTED]> wrote: Hi, In T5, how would like to configure a component? For example, let's imagine a component type ColorText that outputs a string in a certain color. You're now using this component in a page. First, an all-binding style (same concept as in T4): @ComponentClass public class MyPage { @Component(parameters={"color=color", "text=literal:I am in red"}) private ColorText _colorText; public Color getColor() { return Color.RED; } } Alternatively, a type-safe setter style: @ComponentClass public class MyPage { @Component private ColorText _colorText; //This method will be called just before the component _colorText //is rendered. public void configureColorText() { _colorText.setColor(Color.RED); _colorText.setText("I am in red"); } } This ColorText will not update any value on form submission so all we need is to provide values to its parameters. If it was a TextField, then the two approaches will be like: The all-binding style: @ComponentClass public class MyPage { @Component(parameters={"value=name", "validator=required,minLength=10"}) private TextField _textField; private String _name; } The type-safe setter style: @ComponentClass public class MyPage { @Component private TextField _textField; private String _name; public void configureTextField() { _textField.setValueBinding("name"); //read and write _textField.setValidator(new Required(), new MinLength(10)); ... } } Thing is, that would have to be _textField.setValidator("required,minlength=10"). The way the validate binding factory works, it needs to know a lot about the component being bound as well as the container component. That's how it obtains the field's label (for presenting error messages), how it access's the containers catalog (to looks for approprately keyed messages), and eventually, how it will provide an automatic default for the validators based on annotations on the setter method. So far, I've collected the following PROs and CONs for each approach. The all-binding style: 1) Less typing. 2) Automatic data type conversion. For example, if a parameter is expecting an Iterable, you can pass it a binding expression that returns an array. Tapestry will automatically convert it to an Iterable. 3) Consistency across all parameters. They will use bindings no matter they only read the value or perform read and write. 4) Less code when writing components. You just provide the field and access it freely. You don't have to worry about what's a simple property and what's a bi-directional parameter, they look the same to you. You don't have to worry about field converstions. You don't have to provide getter and setter methods (except for testing). The type-safe setter style: 1) IDE auto-completion. The IDE will help you input the setters and the parameter values. 2) Compile time parameter name checking. If you get the name of parameter wrong, the call to the setter simply won't compile. 3) Compile time parameter value type checking. If you pass say a String to setColor(), it simpy won't compile. Unless you provide a TypeCoercer from String to Color. 4) Refactoring. If you rename a parameter, the calls to the setter will be changed automatically. Though this will break existing code, whereas implementing T4's parameter aliases would allow existing code to work after an upgrade, with warnings. 5) The Javadoc of the component class is the component doc. No need to devise a new mechanism to write component doc. Javadoc with privates included can cover this. Perhaps some form of JavaDoc extension that omits privates, but includes @Parameter fields. 6) Easier user level innovation. For example, if one would like to write a new Validator, it's easier because it's just a Java class. With the all- binding style, one will have to come up with a initializer syntax, register it using a configuration under a validator name, while it's still limited to having a single argument. Or: @Component (parameters="validate=prop:myFieldSpecialValidator") private TextField _myField; public FieldValidator getMyFieldSpecialValidator() { return new FieldValidator() { ... } ; } The above is just my observations. What's your take? Which one would you use if both are available in T5? -- Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT) - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] -- 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 unsubscr
Re: T5: which way do you prefer?
I think both are valid options. In my opinion both ways should be provided by the framework and it should be a developers decision to use the one that fits his needs/taste. Question: what would happen if the developer configured the same component both ways in the same page (by mistake or something) ? I think that this shouldn't be allowed and a runtime exception should be thrown. This would prevent some "distraction" programming errors. Kent Tong wrote: Hi, In T5, how would like to configure a component? For example, let's imagine a component type ColorText that outputs a string in a certain color. You're now using this component in a page. First, an all-binding style (same concept as in T4): @ComponentClass public class MyPage { @Component(parameters={"color=color", "text=literal:I am in red"}) private ColorText _colorText; public Color getColor() { return Color.RED; } } Alternatively, a type-safe setter style: @ComponentClass public class MyPage { @Component private ColorText _colorText; //This method will be called just before the component _colorText //is rendered. public void configureColorText() { _colorText.setColor(Color.RED); _colorText.setText("I am in red"); } } This ColorText will not update any value on form submission so all we need is to provide values to its parameters. If it was a TextField, then the two approaches will be like: The all-binding style: @ComponentClass public class MyPage { @Component(parameters={"value=name", "validator=required,minLength=10"}) private TextField _textField; private String _name; } The type-safe setter style: @ComponentClass public class MyPage { @Component private TextField _textField; private String _name; public void configureTextField() { _textField.setValueBinding("name"); //read and write _textField.setValidator(new Required(), new MinLength(10)); ... } } So far, I've collected the following PROs and CONs for each approach. The all-binding style: 1) Less typing. 2) Automatic data type conversion. For example, if a parameter is expecting an Iterable, you can pass it a binding expression that returns an array. Tapestry will automatically convert it to an Iterable. 3) Consistency across all parameters. They will use bindings no matter they only read the value or perform read and write. The type-safe setter style: 1) IDE auto-completion. The IDE will help you input the setters and the parameter values. 2) Compile time parameter name checking. If you get the name of parameter wrong, the call to the setter simply won't compile. 3) Compile time parameter value type checking. If you pass say a String to setColor(), it simpy won't compile. 4) Refactoring. If you rename a parameter, the calls to the setter will be changed automatically. 5) The Javadoc of the component class is the component doc. No need to devise a new mechanism to write component doc. 6) Easier user level innovation. For example, if one would like to write a new Validator, it's easier because it's just a Java class. With the all- binding style, one will have to come up with a initializer syntax, register it using a configuration under a validator name, while it's still limited to having a single argument. The above is just my observations. What's your take? Which one would you use if both are available in T5? -- Author of a book for learning Tapestry (http://www.agileskills2.org/EWDT) - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]