Well I think the Bindable on classes is valid, but I'm talking about interfaces.

I couldn't find a definitive answer on this topic while searching the web.

Bindable is different from the other meta data tags as it explicitly changes 
the output and even the
type hierarchy of the class (Bindable on a class without explicit parent is 
changed to extend EventDispatcher for example). As you noted, every variable is 
re-written to fire events. But an interface can't have variables. 
What I could read online is that people are suggested to make both the 
interface as well as the class implementing the interface bindable, to me this 
looks like a cheap trick to trick the IDE code completion and validation to not 
complaining.

The only thing I could think of that the compiler could do in case of a 
bindable interface, would be to automatically have the interface extend 
IEventDispatcher. This way an implementing class would have to make sure it 
dispatches events, but I guess the old compiler didn't do this.

The question is ... what should Falcon do? 
1. Ignore the Bindable metadata on interfaces
2. Add a warning, but ignore the Bindable in any other way
3. Automatically extend the IEventDispatcher interface
4. something I didn't think of.

For my part I thought 3 would be best, but while writing the code for that I 
had to notice that in the compiler interfaces models don't seem to have any 
metaInfos. Going even further it seems that this part of code can't work this 
way at all, not even for classes. 

metaInfos = pkg.getMetaInfos();

seems to be scanning the package node for metadata, but the class PackageNode 
implements getMetaTags() to return null. If however ASCompilationUnit would 
check the class instead of the package, it would find the MetaTag. 

I think ASCompilationUnit.handleSyntaxTreeRequest needs a good deal of cleaning 
up:
1. Currently Bindable won't work ... not for Interfaces and not for Classes 
only for classes it doesn't throw an exception (At least Bindable classes that 
don't explicitly extend another class won't be changed to extend 
EventDispatcher ... this doesn't have any effect on the code generation later 
on)
2. If I changed the code to look in the class node for MetaInfo, then it would 
find this ... but thinking a little further ... what about files with multiple 
classes? What if the second class definition in a file had such Bindable 
annotation? As far as I can see it, this wouldn't be recognized.

I think it would be best to process each interface and class in a file, check 
if it is bindable and do the processing for EACH of these (Not only the one 
with index 0). If at least one bindable Interface was found, add the 
IEventDispatcher import, if at least one class was found that didn't extend any 
other class, add the EventDispatcher import. Thinking even further ... I think 
it would be best for classes to check if they have a base class and to make 
them extend EventDispatcher if they don't and to make them implement 
IEventDispatcher if they do have a base class.

So ... enough mails for today ... have to defragment my brain now ... probably 
with a decent amount of partying :-)

Chris


________________________________________
Von: Alex Harui <aha...@adobe.com>
Gesendet: Freitag, 31. Oktober 2014 16:14
An: dev@flex.apache.org
Betreff: Re: [FALCON] Bindable interfaces?

Yes, we need to allow [Bindable] on interfaces, even if it is an
inefficient way to write your code.

More details on why it is inefficient:

You can’t have a “var” in an interface, only functions/getter/setters.
[Bindable] was really meant to switch a var into a getter/setter pair so
that a change event gets fired and bindings update.

So if you did:

  [Bindable]
  public var foo:int;

The compiler generates something like (the 12345 is a random number to
prevent name collisions):

  private var foo_12345;
  [Bindable(“propertyChange”)]
  public function get foo():int
  {
      return foo_12345;
  }
  public function set foo(value:int):void
  {
     if (value !== foo_12345)
     {
        foo_12345 = value;
        dispatchEvent(new Event(“propertyChange”));
     }
  }

If you put [Bindable] on the class definition, then all vars are
converted.  I get how that is a convenient way to save time writing code.

I suppose folks who use [Bindable] on getter/setters just want to save
time writing code, IMO, it isn’t worth it.  The Flex SDK hopefully never
does this, btw, because it is inefficient.  The inefficient pattern looks
like:

  private var _foo:int;

  [Bindable]
  public function get foo():int
  {
      return _foo;
  }
  public function set foo(value:int):void
  {
      _foo = value;
  }

This results in the compiler generating:

  private var _foo:int;

  [Bindable]
  public function get foo_12345():int
  {
      return _foo;
  }
  public function set foo_12345(value:int):void
  {
      _foo = value;
  }

  [Bindable(“propertyChange”)]
  public function get foo():int
  {
      return foo_12345;
  }
  public function set foo(value:int):void
  {
      if (value !== foo_12345)
      {
          foo_12345 = value;
          dispatchEvent(new Event(“propertyChange”));
      }
  }

Like I said, hopefully, the SDK code never does this and we always took
the time to do this:

  private var _foo:int;

  [Bindable(“fooChanged”)]
  public function get foo():int
  {
      return _foo;
  }
  public function set foo(value:int):void
  {
      if (_foo !== value)
      {
          _foo = value;
          dispatchEvent(new Event(“fooChanged”));
      }
  }

Yes, I had to do more typing, but if you compare the two patterns, you’ll
see that, for [Bindable] on interfaces and getter/setters, that you’ve
doubled the number of function calls required to get the value, and
tripled the number of function calls required to set the value, plus added
another not-so-short string to the string table and two functions to the
class traits in the SWF all of which have to be downloaded and decoded at
startup time.



Also, at runtime, the binding logic does an additional check if the
property change event is “propertyChange” to see if the property being
changes is the one it is interested in.

Will it make a huge difference in your app’s performance?  I don’t know
for sure, but I think it can add up over time.  Why wrap functions in
functions for no good reason?  Also, see [1] for old information on the
cost of function overhead.


Happy coding,
-Alex

[1]
http://blogs.adobe.com/aharui/2007/10/actionscript_readwrite_perform_1.html

On 10/31/14, 7:05 AM, "Christofer Dutz" <christofer.d...@c-ware.de> wrote:

>Hi,
>
>
>After finishing the advanced-telemetry option I started working on the
>next problem. In this case a user annotated an Interface with "Bindable".
>Falcon dies with a NPE (ASCompilationUnit line 383). I first thought that
>it was an error to make an Interface bindable, but when looking through
>the internet, it should actually be possible to annotate an interface
>with a bindable annotation. The compiler has to do a little more checking
>though :-(
>
>
>I first thought of catching this situation and simply skipping it and
>reporting a warning, but I think this solution would not be correct as
>people are using this (I stumbled over it when trying to compile the
>flexicious code with falcon)
>
>
>Chris

Reply via email to