Return-Path: Delivered-To: apmail-pivot-user-archive@www.apache.org Received: (qmail 55298 invoked from network); 19 Nov 2010 23:07:30 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 19 Nov 2010 23:07:30 -0000 Received: (qmail 72236 invoked by uid 500); 19 Nov 2010 23:08:02 -0000 Delivered-To: apmail-pivot-user-archive@pivot.apache.org Received: (qmail 72203 invoked by uid 500); 19 Nov 2010 23:08:01 -0000 Mailing-List: contact user-help@pivot.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: user@pivot.apache.org Delivered-To: mailing list user@pivot.apache.org Received: (qmail 72195 invoked by uid 99); 19 Nov 2010 23:08:01 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 19 Nov 2010 23:08:01 +0000 X-ASF-Spam-Status: No, hits=2.2 required=10.0 tests=FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_NONE,SPF_PASS,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of bill.van.melle@gmail.com designates 74.125.83.182 as permitted sender) Received: from [74.125.83.182] (HELO mail-pv0-f182.google.com) (74.125.83.182) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 19 Nov 2010 23:07:55 +0000 Received: by pvc22 with SMTP id 22so1217674pvc.13 for ; Fri, 19 Nov 2010 15:07:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:in-reply-to :references:date:message-id:subject:from:to:content-type; bh=uD42BXxVBV2+/mS4HgNpG2Rwr1/gtZNr0YhiiF0jGlo=; b=WyS17eYFVr7EIvh+dQuBnOawBDECao0uf/+SRtlSE09k617fwOAUd2GJqLdFoYcyHF 6gp6ELTiaeLbdH9qVbp2Eri0GgQXWhOUZOe55rlt+vW0RG1eWZIZTZF8lqaBoyNt20RR 49O9GilLeKtelxabkSRXqrgjwv2MjgeavPp0k= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; b=tygtxNnttGkiT7+QhHr7K4yIpNVUPzbkH2pVAw+NopcMfGHtVcHfGQ6MY2cqGReZPv 5TreaalPUDHNh6s3c58z08tw6RspTBh/MZEB2/FC3uJv5fcZIvjjI9aa0hkAztACWQKE dPv3ilyMk5eLnnghe05FuDcN7cDnFeTw8oiYE= MIME-Version: 1.0 Received: by 10.143.1.12 with SMTP id d12mr2353945wfi.107.1290208054967; Fri, 19 Nov 2010 15:07:34 -0800 (PST) Received: by 10.142.200.9 with HTTP; Fri, 19 Nov 2010 15:07:34 -0800 (PST) In-Reply-To: <104DFBB4-FFF5-4647-9675-037DF6F91C58@mac.com> References: <104DFBB4-FFF5-4647-9675-037DF6F91C58@mac.com> Date: Fri, 19 Nov 2010 15:07:34 -0800 Message-ID: Subject: Re: Simpler event listeners? From: Bill van Melle To: user@pivot.apache.org Content-Type: multipart/alternative; boundary=001636e0a774cd7ecf04956ff827 --001636e0a774cd7ecf04956ff827 Content-Type: text/plain; charset=ISO-8859-1 > > Naming the files Foo.java and Foo.bxml implies that they are partial > classes, which isn't the case. Developers may expect "new Foo()" to produce > the same results as deserializing Foo.bxml - since it won't, this could be > confusing. Using the "Foo.java/foo.bxml" convention avoids this ambiguity. > But it's also the case that neither can be used without the other -- you can't do new() on the class and get a working component, and you can't deserialize the bxml without casting it to the class. So I think people already have to understand the structure. If anything, my strategy of adding a static create method to the class simplifies that -- nobody other than the "owner" of a bxml file ever needs to touch the serializer or even know the name of the bxml file. A practical benefit of naming them the same is that they're adjacent in Eclipse's case-sensitive explorer sort, instead of far apart. > * In lieu of a proper constructor, I add a static factory method... > > so that code which in other systems might call new ClassName() can almost > as painlessly call ClassName.create(). > > This is an interesting idea. I wonder if it might be worth adding a > parameterized static method to BXMLSerializer to do this, so you don't have > to add this to every class: > > public static T create(URL, Resources) throws IOException, > SerializationException { ... } > Doesn't do anything for me. I add the create method as a way of simplifying the interface to the class, not because I dislike casting the result of the serializer -- I don't want anyone outside the class to even care that there's a bxml file and how to deserialize it. Hmm, this now makes me wonder if it would be easy to make an Eclipse plugin that would offer a "New" option "Pivot component with bxml", which would create two files with the kind of boilerplate I spoke of. > The "this" reference in the inner class points to itself, but you can > always use .this to get access to the containing object if you > need to. However, in most cases this isn't necessary since inner classes > don't need to qualify access to outer class methods. > Good to know (about qualified this). I already knew I could call outer methods without qualification, but a common thing that a button press listener does is popup a dialog, something that requires passing the parent reference in. > - In general, I'd expect handler methods such as "loginButtonPressed" to be > private (you probably don't want to expose this logic to arbitrary callers). > We can use reflection to call a private method, but that requires that the > code be trusted (i.e. you couldn't do this in an applet unless it was > signed). This isn't necessarily a blocker - the same applies to the @BXML > annotation, which is often used to populate private members. It's just > something to consider. > Oh dear, so I can't even use @BXML on private members in an unsigned applet? Well, that kills part of my strategy if I ever want to do an unsigned applet (not important to me right at the moment, though). Yes, in general listeners ought to be private. > - As a developer, I might expect the "loginButtonPressed" method to be > defined in script within the page, rather than as a method on the root > object. In other words, there's nothing in the syntax that lets me know what > object defines the method. True, but then currently there's no way at all to call methods on the Java class, so you're not yet thinking to look there. I think having the Java class of the bxml root be a place for a listener implementation would be no harder or unexpected a place for a programmer to look than, say, inside an included .js file. > - Finally, it seems like the loginButtonPressed() method should implement > the syntax defined by the buttonPressed() method. Because .NET uses > delegates for event handlers (and XAML is compiled), this can be enforced by > the compiler. However, since BXML is not compiled (and Java does not support > delegates), we can't enforce it. This again suggests that the handler should > be script code rather than the name of a method on the root object. > Can you not use reflection to verify that the specified listener method has a signature that matches what a buttonPressListener is expecting? (I don't know -- I'm not a Java expert.) And if not, what happens? You get a Java runtime error when you call the listener method? I'd live with that -- as it is, bxml deserialization errors are often plenty cryptic :). > FWIW, I generally don't use attribute-based event handlers - I prefer the > element-based syntax: > > > > function buttonPressed(button) { > myWindow.login(); > } > > > > Yes, it's a bit more verbose, but I find it easier to read and write. It is > also much easier to implement listeners with multiple handler methods this > way. If I have to be that verbose, I'd much rather hide the verbosity in my Java class' initialize method, and try to keep the bxml file readable. --001636e0a774cd7ecf04956ff827 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable
Naming the files= Foo.java and Foo.bxml implies that they are partial classes, which isn'= ;t the case. Developers may expect "new Foo()" to produce the sam= e results as deserializing Foo.bxml - since it won't, this could be con= fusing. Using the "Foo.java/foo.bxml" convention avoids this ambi= guity.

But it's also the case that neither ca= n be used without the other -- you can't do new() on the class and get = a working component, and you can't deserialize the bxml without casting= it to the class. =A0So I think people already have to understand the struc= ture. =A0If anything, my strategy of adding a static create method to the c= lass simplifies that -- nobody other than the "owner" of a bxml f= ile ever needs to touch the serializer or even know the name of the bxml fi= le.

A practical benefit of naming them the same is that the= y're adjacent in Eclipse's case-sensitive explorer sort, instead of= far apart.


> * In lieu of a proper constructor, I add a static factory method... > so that code which in other systems might call new ClassName() can alm= ost as painlessly call ClassName.create().

This is an interesting idea. I wonder if it might be worth adding a p= arameterized static method to BXMLSerializer to do this, so you don't h= ave to add this to every class:

public static <T> T create(URL, Resources) throws IOException, Serial= izationException { ... }

Doesn't do= anything for me. =A0I add the create method as a way of simplifying the in= terface to the class, not because I dislike casting the result of the seria= lizer -- I don't want anyone outside the class to even care that there&= #39;s a bxml file and how to deserialize it.

Hmm, this now makes me wonder if it would be easy to ma= ke an Eclipse plugin that would offer a "New" option "Pivot = component with bxml", which would create two files with the kind of bo= ilerplate I spoke of.

=A0
The "this= " reference in the inner class points to itself, but you can always us= e <OuterClass>.this to get access to the containing object if you nee= d to. However, in most cases this isn't necessary since inner classes d= on't need to qualify access to outer class methods.

Good to know (about qualified this). =A0I = already knew I could call outer methods without qualification, but a common= thing that a button press listener does is popup a dialog, something that = requires passing the parent reference in.
=A0
=A0
- In general, I'd expect handler methods such as "loginButtonPress= ed" to be private (you probably don't want to expose this logic to= arbitrary callers). We can use reflection to call a private method, but th= at requires that the code be trusted (i.e. you couldn't do this in an a= pplet unless it was signed). This isn't necessarily a blocker - the sam= e applies to the @BXML annotation, which is often used to populate private = members. It's just something to consider.

Oh dear, so I can't even use @BXML on = private members in an unsigned applet? =A0Well, that kills part of my strat= egy if I ever want to do an unsigned applet (not important to me right at t= he moment, though). =A0Yes, in general listeners ought to be private.

=A0
- As a developer, I might expect the "loginButtonPressed" method = to be defined in script within the page, rather than as a method on the roo= t object. In other words, there's nothing in the syntax that lets me kn= ow what object defines the method.

True, but then currently there's no way at all to c= all methods on the Java class, so you're not yet thinking to look there= . =A0I think having the Java class of the bxml root be a place for a listen= er implementation would be no harder or unexpected a place for a programmer= to look than, say, inside an included .js file.

=A0
- Finally, it seems like the loginButtonPressed() method should implement t= he syntax defined by the buttonPressed() method. Because .NET uses delegate= s for event handlers (and XAML is compiled), this can be enforced by the co= mpiler. However, since BXML is not compiled (and Java does not support dele= gates), we can't enforce it. This again suggests that the handler shoul= d be script code rather than the name of a method on the root object.

Can you not use reflection to verify that = the specified listener method has a signature that matches what a=A0buttonPressListener is expecting? =A0= (I don't know -- I'm not a Java expert.) =A0And if not, what happen= s? =A0You get a Java runtime error when you call the listener method? I'= ;d live with that -- as it is, bxml deserialization errors are often plenty= cryptic :).

=A0
FWIW, I generally don't use attribute-based event handlers - I prefer t= he element-based syntax:

<PushButton buttonData=3D"Login">
=A0 =A0<buttonPressListeners>
=A0 =A0function buttonPressed(button) {
=A0 =A0 =A0 =A0myWindow.login();
=A0 =A0}
=A0 =A0</buttonPressListeners>
</PushButton>

Yes, it's a bit more verbose, but I find it easier to read and write. I= t is also much easier to implement listeners with multiple handler methods = this way.

If I have to be that verbose, I&#= 39;d much rather hide the verbosity in my Java class' initialize method= , and try to keep the bxml file readable.
=A0
--001636e0a774cd7ecf04956ff827--