This thread is a little stale, apologies, but it's been a crazy
month, and
this topic deserves more consideration.
As a long time user of Tapestry (since T3) and an early adopter of
T5 (since
~T5.0.0), my experience with type coercion has been love/hate. But
mostly
hate.
When there was only TypeCoercer to think about, things were much
simpler.
There was only one possible path of type coercion for the entire
system,
and, importantly, things ... just... worked.
With the introduction of:
Translator
ValueEncoder
PrimaryKeyEncoder
We have not one, but FOUR systems of type coercion.
I know that Howard has expressed concern over separation of
concerns as
being the motivator for the additional conversion interfaces, but I
submit
that the additional interfaces, in fact, pollute separation of
concerns.
Take Translator: it's trying to act both as a type coercion system
(value
-> string and back) and as a first-pass validation system.
or:
PrimaryKeyEncoder: acting both as a simplistic batching mechanism (by
stashing the set of keys used into the form, and providing a
mechanism to
convert those keys back to values en masse) and as a type coercion
system
(value -> serializable and back)
I'm not disputing the utility of any of the functions provided by the
various systems. I'm disputing the complexity of the system. For
a novice
user, it's confusing and adds additional learning-burden that
doesn't need
to be there.
Consider, for example, trying to learn a few of the built-in
components:
textfield: translator
Context of links: /normally/ value encoder and decoder (quietly).
Except
when your handler takes a type of Object[]. And then you get back
strings,
and if you don't explicitly arrange for the ValueEncoder to do the
decoding,
tapestry tries to use TypeCoercer, which screws up. (See example
later).
DateField: I would expect translator, but, hey, no, it's not...
it's a
java.text.DateFormat.
Grid: ?? No explicit encoding mechanism provided. Presumably....
value
encoder?
Loop: PrimaryKeyEncoder (<sarcasm>since, clearly, the only thing
we're
/ever/ going to loop over is a database entity with a serializable
primary
key</sarcasm>)
AjaxFormLoop: PrimaryKeyEncoder
Select: PrimaryKeyEnco.... oh... wait... ValueEncoder. Shucks.
Just when I
thought I was starting to get this straight. Oh, right, unlike with
Loop, I
might want to use non-entities in a Select. Clear as mud.
textarea: translator
textfield: translator
Because I've been using tapestry, and T5, for a long while now, I can
understand the rationale behind each of these choices. But from the
perspective of a new user, the framework appears schizophrenic.
In fact, the framework doesn't even always "get it right". Take the
following example:
public class SomeComponent {
@Parameter
private Object[] parameters;
@Component(parameters="context=inherit:context")
private ActionLink someAction;
@Inject
private ComponentResources resources;
void onActionFromSomeAction(Object[] parameters) {
resources.triggerEvent("SomeComponentEvent",parameters,null);
}
}
This seems to be perfectly legitimate code. And is potentially a
very
powerful paradigm. However, try using "SomeComponent" with a
hibernate
entity encoded via the value encoder in the hibernate module, and the
framework explodes. The cause, after some digging, is that the
framework
encodes values into the url using a value encoder, but the decoding
will be
done by type coercer (in the above example). There is a
workaround: provide
your own event context that uses value encoder. But there
shouldn't /need/
for a workaround. Type coercion should just work, with absolutely no
thought from the user. Ironically, this was the case when all we
had was
TypeCoercer. But the additional interfaces obscure that simplicity
and
reliability.
Robert
On Sep 15, 2008, at 9/159:53 AM , Howard Lewis Ship wrote:
On Mon, Sep 15, 2008 at 4:31 AM, Kevin Menard <[EMAIL PROTECTED]>
wrote:
I'll test this is the next few days, but don't expect to see
anything
problematic.
I guess the whole RC thing snuck up on me though. I'd really
like to
see the whole type coercion system looked at again. I know we've
ping-ponged on this a few times, but the framework has evolved a
fair
bit since then and I do think it's worth another look. As Robert
pointed out in TAPESTRY-2491, we have four ways of doing type
coercion:
Translators
Very tied into form mechanics; not general purpose; used for moving
between strings and arbitrary values. User input based, with hooks
for client-side validation.
ValueEncoders
Specific to encoding a value into a string, for use inside a URL or
something similar. Really means for entity values, rather than user
input values.
PrimaryKeyEncoders
Similar to ValueEncoders, but not necessarily a String, just a
Serializable. Also meant for entity values. Includes a performance
optimization that allows many entities to be efficiently pre-loaded.
TypeCoercers
Very low-level; used in tapestry-ioc, not just tapestry-core.
Designed
to be combinable. Primarily meant for converting parameters from
actual types to desired types but often used as the basis of the
other
three.
While I can appreciate the value of each being used in a particular
context, it seems as though the framework is even inconsistent with
its usage at times. Any custom implementation of one almost
implies
an implementation of the others and more often than not a simple
adapter is used because the code is so common between them all. It
strikes me as something that's perhaps over-engineered and the
practicality of a single interface may trump the separation of
concerns benefit. I think it's one of the framework's "gotchas"
that
we could address without much hassle.
I still see the simularities as pretty shallow, and the
differences as
pretty deep.
If we do decide to keep the system as is, I guess that's fine as
well.
It's not really broken. But, I would like to see some discussion
on
it leading to some decisive path.
--
Thanks,
Kevin
On Sat, Sep 13, 2008 at 7:18 PM, Howard Lewis Ship <[EMAIL PROTECTED]
>
wrote:
I've fixed a few more bugs for 5.0.15 and updated the Maven and
src/bin distributions, as previously discussed here.
I've created and uploaded a release of Tapestry 5.0.15, ready to
be
voted upon. This is the release candidate.
The files are uploaded to:
http://people.apache.org/~hlship/tapestry-releases/
and a Maven repository:
http://people.apache.org/~hlship/tapestry-ibiblio-rsynch-repository/
Please examine these files to determine if a new preview release,
5.0.15, is ready.
I've also created a 5.0.15 tag in Subversion:
http://svn.apache.org/viewvc/tapestry/tapestry5/tags/releases/5.0.15/
On a successful vote, I'll move the files from these directories
to
the proper distribution directories.
Vote will run for three days; on success I'll move the voted
artifacts
into place and send out appropriate notifications.
I'm looking forward to having several weeks of exposure of the
release
candidate. If no critical, unpatchable errors occur, this can
be the
5.0 GA. I'm already looking forward to doing some ambitious
things in
the 5.1. release.
Howard M. Lewis Ship: +1 (binding)
--
Howard M. Lewis Ship
Creator Apache Tapestry and Apache HiveMind
---------------------------------------------------------------------
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]
--
Howard M. Lewis Ship
Creator Apache Tapestry and Apache HiveMind
---------------------------------------------------------------------
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]