Proposal for changes

48 views
Skip to first unread message

Joa Ebert

unread,
Nov 22, 2010, 12:58:44 PM11/22/10
to as3-signals
Hey everybody,

I recently forked Robert's code and started to play around with it and
as of today we achieved a nice performance boost for signal dispatch,
with or without modification. Most functions are 2x to 3x faster
(depending on Signal/DeluxeSignal).

I also started to play with the general design of the library. As an
issue request on GitHub and the applied changes we can now introduce a
signal binding object. This object would give you the ability to
pause, resume or cancel signal dispatch to a specific listener.

Here is a little API proposal and how you could work with bindings:

var signal: ISignal = ...;
var binding: ISignalBinding = signal.add(listener1);

// listener 1 is called
signal.dispatch()

binding.pause()

// listener 1 is not called, all other bindings to the signal would be
still active
signal.dispatch()

binding.resume()

// listener 1 is called
signal.dispatch()

// swap the listener for this binding
binding.swap(listener2)

// listener 2 is called
signal.dispatch()

// remove this binding
binding.remove()

// listener 2 is not called, listener 1 is not called, binding has
been removed
signal.dispatch()

I think this is a valuable addition to the signals library since it
eases temporary changes to listeners/bindings. It is also great in
terms of performance since pausing a signal does not have the overhead
of removing a listener and then adding it back to the signal. In the
end, it is also more concise since you can directly express what you
want to do ("pause and resume" vs. "remove and then add again later").

A second change I would like to introduce is just some cleanup. The
signals project comes now with a lof of interfaces and as an average
user you will therefore rely on the concrete implementation. E.g. I
want to be able to "dispatch" and "remove" from a simple signal. What
do I have to choose? ISignal, ISignalOwner, IDispatcher, ...? To keep
things more simple I would like to get rid of most of the interfaces.
That means, with my proposed change there will be only ISignal,
IPrioritySignal, INativeSignal -- dispatch and removeAll will be part
of ISignal.

Why this change? Well if you want to use a plain simple signal, it is
quite intuitive to use the ISignal interface, and you immediately know
what to do. Same for IPS and INS. How does this affect the discussion?
I guess the power of the signals library is that it is very easy to
use and lightweight. Therefore it would make sense to allow other
people that want to have this support, to implement their own objects.

E.g. you can write an interface, like IDispatcher, and create a class
like "class DispatcherDecorator extends Signal implements IDispatcher"
and return an IDispatcher where appropriate.

Last but not least I think it would be also quite nice to have another
ISignal implementation that behaves like Signal but is dead simple and
does no verification at all. That way, you as a user of the signals
library can use the Signal clas in debug mode (to get nice error
messages) and switch to the FastSignal for production code.

Please tell me what you think.


Best,

Joa

joel...@gmail.com

unread,
Nov 22, 2010, 3:19:55 PM11/22/10
to as3-s...@googlegroups.com
On Mon, Nov 22, 2010 at 11:58 AM, Joa Ebert <joae...@googlemail.com> wrote:

Last but not least I think it would be also quite nice to have another
ISignal implementation that behaves like Signal but is dead simple and
does no verification at all. That way, you as a user of the signals
library can use the Signal clas in debug mode (to get nice error
messages) and switch to the FastSignal for production code.

Please tell me what you think.

I think this implementation would be something that would make an excellent external add-on to Signals. My problem with including it in the care library is that people would assume that it would be the GOTO Signal. Who doesn't want a faster Signal? Right? Which leads to the need to explain often what it is, why to use it, and what those odd errors in a users app mean.

I tend to err on the side of modularity where possible though, and perhaps I am being too conservative. Signals are already faster than Events from the benchmarks I've seen. Needing something much faster is definitely an edge case.

-j

Joa Ebert

unread,
Nov 22, 2010, 4:25:05 PM11/22/10
to as3-signals
You are absolutely right Joel. I think it is a total edge case. From
my performance tests the signals should be sufficient for any large
scale application. And they were fast enough before as well.

Another note on the interface suggestion:

public class Dispatcher {
private var _signal: ISignal;
public function Dispatcher(signal: ISignal) {
_signal = signal;
}

public function dispatch(...rest): void {
_signal.dispatch.apply(null, rest)
}
}

The right way to do it in my opinion. An interface is not abused a an
access modifier and you get real encapsulation.

On Nov 22, 9:19 pm, "joelho...@gmail.com" <joelho...@gmail.com> wrote:

brian heylin

unread,
Nov 22, 2010, 5:24:48 PM11/22/10
to as3-s...@googlegroups.com
Nice work on the speed increases and of course, being the guy who opened the issue, I agree with adding SignalBinding :) Unsurprisingly, I already have uses for it. This is my highest priority as it allows the signals lib to easily become part of more complicated async systems.

Reducing the interfaces is also fine as long as there is a common base interface for all Signals im happy. Extending the library becomes a pain without the common interface.

The specialized interface with speed in mind is low priority for me but I do not see a huge problem with it other than more code to maintain. The external add on option sounds good to me.
--
Brian

BigP

unread,
Nov 22, 2010, 5:32:27 PM11/22/10
to as3-signals
Hi, actually new to as3-signals here, but loving what I read about it
so far.

If there's a concern whether FastSignal should be included in the core
of as3-signals, could there be two SWCs provided?

something like as3-signals.swc - and - as3-signals-dbg.swc?

So in a sense, what I'm suggesting, keep this "Fast" signal's
classname as Signal, but compile it in a production-ready SWC (or make
seperate prod and debug source folders available).

If they both do essentially the same thing, but one library simply
doesn't type-check and speeds up signals performance, I would think:
leave it up to the developers to choose which library to use (when
they've all tested and validated their work).

Anyways, hope my first post here isn't too irrelevant!
Great to see so much collaboration on this library :)

Robert Penner

unread,
Nov 22, 2010, 9:58:35 PM11/22/10
to as3-s...@googlegroups.com
I'm quite open to Joa's proposals at this point, partly because I love to delete code. I just wanted to make sure we have a chance to discuss before APIs are removed. 

IDispatcher: 

I made and unit tested it, but I've never used it.

ISignal getting dispatch() and removeAll(), removing "owner" interfaces: 

The current design was based on rationales that we agreed on, chiefly, making it difficult for listeners to affect other listeners. The question is whether the increased complexity of more interfaces is worth the payoff. If I'm honest, I think it's a nice concept but not really a big concern in the real world. AS3 EventDispatcher.dispatchEvent() is public, but I doubt many bugs result that would be prevented by restricting access to that method.  

"FastSignal":

I think it should have its own name, but something besides "Fast". Remember, Signal is already plenty fast for the vast majority of applications.

Other ideas: 

SimpleSignal
BareSignal
UntypedSignal
GenericSignal
Zzzzzignal (pronounced with Doppler shift)

Robert

Robert Penner

unread,
Nov 22, 2010, 10:04:47 PM11/22/10
to as3-s...@googlegroups.com
>>
// swap the listener for this binding
binding.swap(listener2)
<<

https://github.com/joa/as3-signals/blob/master/src/org/osflash/signals/SignalBinding.as#L182

How about turning swap() into:

function set listener(value:Function):void

Then:

binding.listener = listener2;

Robert

Robert Penner

unread,
Nov 22, 2010, 10:09:32 PM11/22/10
to as3-s...@googlegroups.com
Also, we can move the validation for the listener's number of
arguments into the SignalBinding listeners setter. Currently it's
duplicated:

https://github.com/joa/as3-signals/blob/master/src/org/osflash/signals/SignalBinding.as#L187

https://github.com/joa/as3-signals/blob/master/src/org/osflash/signals/Signal.as#L168

Robert

Jeremy Ruppel

unread,
Nov 22, 2010, 11:27:26 PM11/22/10
to as3-signals
I'm all for the pause/unpause functionality, I think Joa's spot on.
This is far more intuitive than removing/re-adding a listener. I'm
also all for removing the IDispatcher interface. Never used it, can't
see where I would need to restrict access to only the dispatch
capabilities of a signal. But on a related note, re: moving dispatch
and removeAll into ISignal:

"That means, with my proposed change there will be only ISignal,
IPrioritySignal, INativeSignal -- dispatch and removeAll will be part
of ISignal."

"AS3 EventDispatcher.dispatchEvent() is public, but I doubt many
bugs result that would be prevented by restricting access to that
method."

I couldn't disagree more. The beauty of the ISignal interface is that
you can truly provide a public interface, complete with events, that
is very hard to tamper with. I have seen the public
IEventDispatcher.dispatchEvent abused far too many times, I'd really
love it to be removed from IEventDispatcher similarly. For the
aforementioned average use case, where the user will want to add,
dispatch, and removeAll from the same signal, I'm of the mind that
they should be ignoring the interface entirely as they are really
after the full functionality of the Signal implementation. I have
found restricting access to the dispatch method invaluable, I'd hate
to see it exposed.

Joel Hooks

unread,
Nov 23, 2010, 12:46:15 AM11/23/10
to as3-s...@googlegroups.com
On Nov 22, 2010, at 11:25 PM, Jeremy Ruppel <jeremy...@gmail.com> wrote:

> I have seen the public
> IEventDispatcher.dispatchEvent abused far too many times, I'd really
> love it to be removed from IEventDispatcher similarly. For the
> aforementioned average use case, where the user will want to add,
> dispatch, and removeAll from the same signal, I'm of the mind that
> they should be ignoring the interface entirely as they are really
> after the full functionality of the Signal implementation. I have
> found restricting access to the dispatch method invaluable, I'd hate
> to see it exposed.

How is the lack of a dispatch invaluable?

I've found it to be a pain when I was writing APIs with Signals
support. I certainly didn't want to use a specific Signal
implementation. I've privately yearned for an interface that
represented this basic expected functionality.

Jeremy Ruppel

unread,
Nov 23, 2010, 1:13:17 AM11/23/10
to as3-signals
Hm, I understand where you'd want to depend on an interface with
dispatch as a member internally, but if you're writing a public API,
what is the benefit of exposing dispatch to the end-user?

In my mind, the best of both worlds would be to have an interface with
dispatch as a member that you could use internally so as not to depend
on a specific signal implementation, but a more restrictive interface
could be used when making that signal public.

On Nov 22, 9:46 pm, Joel Hooks <joelho...@gmail.com> wrote:

Joel Hooks

unread,
Nov 23, 2010, 1:18:32 AM11/23/10
to as3-s...@googlegroups.com
I'm exposing dispatch, just using it internally (via casting right
now). Frankly I was flustered when I found out ISignal didn't have the
expected dispatch method. I don't see any distinct advantage to
complicating things with multiple interfaces.

IEventDispatcher that doesn't have the means to dispatch an event
seems even weirder ;)

Jeremy Ruppel

unread,
Nov 23, 2010, 1:19:44 AM11/23/10
to as3-signals
Perhaps this means there is a use for IDispatcher after all ;). Could
IDispatcher (or maybe we'd come up with a better name for it) _extend_
ISignal? Inwardly, use the IDispatcher API to avoid depending on a
concrete Signal implementation, and outwardly offer the signal as
ISignal to prevent unwanted access to dispatch or removeAll?

On Nov 22, 9:46 pm, Joel Hooks <joelho...@gmail.com> wrote:

Robert Penner

unread,
Nov 23, 2010, 1:20:32 AM11/23/10
to as3-s...@googlegroups.com
>>
an interface with dispatch as a member that you could use internally so as not to depend
on a specific signal implementation, but a more restrictive interface
could be used when making that signal public.
<<

You've described the current ISignalOwner and ISignal, respectively. ISignalOwner was just added this month.

Robert

Robert Penner

unread,
Nov 23, 2010, 1:29:39 AM11/23/10
to as3-s...@googlegroups.com
Joa has been telling me that it's a misuse of interfaces to restrict access in this manner. I'm not sure whether I agree yet but I definitely value his perspective.

A different angle is this question: What does it mean to be a signal? Is dispatching and removing all listeners expected behaviour of signal implementations? I think it is.

Joa's also challenging us to keep the core library focussed and simple. 

Robert

Joel Hooks

unread,
Nov 23, 2010, 1:37:22 AM11/23/10
to as3-s...@googlegroups.com
I think any misuse would be in providing an interface that prevented expected actions. In the case of a Signal, I expect it to be the basic reference implementation of a ISignal. Dispatching and removing listeners is part of that basic functionality. 

Stray

unread,
Nov 23, 2010, 3:31:14 AM11/23/10
to as3-signals
+1 for simplifying the interfaces.

Yesterday I went through my project and changed the Signal references
to ISignal - because that seemed correct.

Then all my unit tests stopped running, because my mediator-view
integration tests rely on manually dispatching from
view.someSignal ... and ISignal doesn't include dispatch. Am I doing
it wrong? It feels like a good way to test. (I separately test that
the view dispatches correctly).

So then I changed all those typings to ISignalOwner - which felt icky,
but was necessary to allow the tests to work.

And then I hit a bunch of compatibility issues because some older code
in my project (which unfortunately is already compiled on the user's
machines) is expecting a different interface signature combination ...
(fair enough, we're still in 0.x releases)

...so I ended up rewinding most of them to Signal again.

Perhaps a better programmer would have anticipated it, but I'm
definitely the slowest compiler, so *don't make me think* too much!

I know Robert and I discussed interfaces when going from 0.7 to 0.8
and neither of us were fans of IDispatcher then.. but I now have a
real concrete experience of how the interface is over-fragmented!

On Nov 23, 6:37 am, Joel Hooks <joelho...@gmail.com> wrote:
> I think any misuse would be in providing an interface that prevented
> expected actions. In the case of a Signal, I expect it to be the basic
> reference implementation of a ISignal. Dispatching and removing listeners is
> part of that basic functionality.
>
> On Nov 23, 2010, at 12:30 AM, Robert Penner <i...@robertpenner.com> wrote:
>
> Joa has been telling me that it's a misuse of interfaces to restrict access
> in this manner. I'm not sure whether I agree yet but I definitely value his
> perspective.
>
> A different angle is this question: What does it mean to be a signal? Is
> dispatching and removing all listeners expected behaviour of signal
> implementations? I think it is.
>
> Joa's also challenging us to keep the core library focussed and simple.
>
> Robert
>
> On Mon, Nov 22, 2010 at 10:20 PM, Robert Penner <i...@robertpenner.com>wrote:
>
>
>
>
>
> > an interface with dispatch as a member that you could use internally so as
> > not to depend
> > on a specific signal implementation, but a more restrictive interface
> > could be used when making that signal public.
> > <<
>
> > You've described the current ISignalOwner and ISignal, respectively.
> > ISignalOwner was just added this month.
>
> > Robert
>

Stray

unread,
Nov 23, 2010, 3:32:35 AM11/23/10
to as3-signals
Oh - and also +1 for bindings. I currently have a SignalMediator class
that keeps signal references for this mediator to do cleanup
onRemove() - that would be much simplified.

On Nov 23, 6:37 am, Joel Hooks <joelho...@gmail.com> wrote:
> I think any misuse would be in providing an interface that prevented
> expected actions. In the case of a Signal, I expect it to be the basic
> reference implementation of a ISignal. Dispatching and removing listeners is
> part of that basic functionality.
>
> On Nov 23, 2010, at 12:30 AM, Robert Penner <i...@robertpenner.com> wrote:
>
> Joa has been telling me that it's a misuse of interfaces to restrict access
> in this manner. I'm not sure whether I agree yet but I definitely value his
> perspective.
>
> A different angle is this question: What does it mean to be a signal? Is
> dispatching and removing all listeners expected behaviour of signal
> implementations? I think it is.
>
> Joa's also challenging us to keep the core library focussed and simple.
>
> Robert
>
> On Mon, Nov 22, 2010 at 10:20 PM, Robert Penner <i...@robertpenner.com>wrote:
>
>
>
>
>
> > an interface with dispatch as a member that you could use internally so as
> > not to depend
> > on a specific signal implementation, but a more restrictive interface
> > could be used when making that signal public.
> > <<
>
> > You've described the current ISignalOwner and ISignal, respectively.
> > ISignalOwner was just added this month.
>
> > Robert
>

Joa Ebert

unread,
Nov 23, 2010, 4:58:00 AM11/23/10
to as3-signals
Thank you all for the feedback so far.

I also want to clarify that the signals project is not using any kind
of pool. It would make development more complicated and I think it is
really fast enough. However I will also have another look at
DeluxeSignal#add and see if we can get better results.

Another change, or possible change, would be to allow you to work with
bindings directly. That means you could use addBinding(binding:
ISignalBinding). This allows you to develop your own implementation of
ISignalBinding. In Stray's case you could create an ISignalBinding
that contains a signal itself, which fires when the ISignalBinding is
removed.

Richard Lord

unread,
Nov 23, 2010, 10:05:21 AM11/23/10
to as3-signals
Thank you, Joa. It's nice to get a performance boost.

I like the proposal for bindings. It's a nice idea, and Robert's
suggestion to use a listener property on the binding works for me. My
only tiny complaint would be that I don't like pause/resume for the
method names. Yes, a tiny complaint, but would disable/enable or mute/
unmute be better?

Like Jeremy, I like the two interfaces, ISignal and ISignalOwner. They
provide a neat way to hide the dispatch method from objects outside
the signal's owner. The other way to do this would be to namespace the
dispatch method, but having to include the namespace in every signal
owner would become tiresome. Hence, the two interfaces are nice (I
don't think the IDispatcher is required - the dispatch method should
be specified in ISignalOwner).

Joa Ebert

unread,
Nov 23, 2010, 10:44:53 AM11/23/10
to as3-signals
Richard,

what do you think about a proposed solution which you can stil use in
your own code like the Dispatcher class?

BigP

unread,
Nov 23, 2010, 10:57:33 AM11/23/10
to as3-signals
That's one of my tiny complaints too. I personally like your suggested
names, although a step further:
- enabled (as a Boolean getter / setter)
- listening (as a Boolean getter / setter)
- open() / close();
- muted (as a Boolean getter / setter)

Not sure it would differ too much performance-wise, but switches like
that seems to be more convenient as a Boolean getter / setter, at
least IMO.

What do you guys think?

edzis

unread,
Nov 23, 2010, 5:13:22 AM11/23/10
to as3-signals
- as bindings will not break existing code, i welcome that addition
- to me ISignal should be the common point interface for both Signal
and DeluxeSignal. I know now that it is ISignalOwner.as, but ISignal
is the intuitive guess when you start using signals
- a fast signal makes sense for production. Not not to promote
uninformed usage I suggest the name DumbSignal.
- if this discussion last longer than a week I suggest allready
integrating the speed optimizations without api changes just to get
this out to developers.

On Nov 23, 9:32 am, Stray <dailystray...@googlemail.com> wrote:

Tyler Wright

unread,
Nov 23, 2010, 11:55:22 AM11/23/10
to as3-s...@googlegroups.com
I have seen the public
IEventDispatcher.dispatchEvent abused far too many times, I'd really
love it to be removed from IEventDispatcher similarly.

I'm a frequent abuser of the IEventDispatcher.dispatchEvent method. I find that it's really quite useful in specific use-cases, such as testing or "replaying" system behaviors. And when it's not useful it goes quietly unused.

+1 on simplifying (unifying) interfaces for signals.

Tyler

Tyler Wright

unread,
Nov 23, 2010, 12:30:52 PM11/23/10
to as3-s...@googlegroups.com
The bindings have a similar feel to the Event object dispatched with every EventDispatcher event, though not near as frequent as it's only on add(). It gets created, sometimes retained but frequently discarded, causing some work for the garbage collection. Pausing functionality is infrequent enough for me that adding/removing the listener to achieve the same results makes the most sense and keeps Signals simple.

Joa - you mention object pooling, but since you don't know whether or not bindings are retained or discarded it's impossible to pool these type of objects - is that right?

thoughts?
Tyler

brian heylin

unread,
Nov 23, 2010, 4:47:00 PM11/23/10
to as3-s...@googlegroups.com
@Joa: What is the reasoning for not allowing access to the signal in the SignalBinding?
--
Brian

Michael Avila

unread,
Nov 23, 2010, 4:59:56 PM11/23/10
to as3-s...@googlegroups.com
AFAIK we aren't going to get a performance benefit using a pool. I agree that it will make the implementation more complex and will do so without providing any benefit.
--
-
http://proas.org/michael

Richard Lord

unread,
Nov 23, 2010, 5:43:23 PM11/23/10
to as3-signals
Tyler - The SignalBinding is used internally, so it's required anyway
and isn't discarded if not used by the user code. This is one of the
elegant features of Joa's solution and sways me to like the bindings
even though I, like you, have no pressing need for them - they don't
add significantly to the complexity, but they do add to the features
in a way that some users want.

Richard Lord

unread,
Nov 23, 2010, 5:48:51 PM11/23/10
to as3-signals
Joa,

If we have just one ISignal interface with the same API as the current
ISignalOwner interface, it's not the IDispatcher interface that I will
miss, it's the current ISignal interface. This is the "public" (i.e.
outside the signal's owner) interface for the Signal. It is how most
classes (those outside the signal owner) see and access the SIgnal and
as such, to most code it is the Signal.

I guess the idea is that developers creating libraries with signals
will need to know about the ISignalOwner interface, while developers
using those libraries will only need to know about the ISignal
interface. My feeling is that the former can handle the additional
complexity on their side while the latter will appreciate the
simplicity of the minimal ISignal interface.

Yes a class can be created to hide the signal behind a different
interface, with just add, addOnce, remove & numListeners, but to my
mind that would be far worse than the two interfaces. I'd be using it
on every signal I create. An interface is more elegant, simpler and
provides better performance.

But above all, why is it necessary that a Signal must have a
dispatch() method. Surely the important bit is add, addOnce, remove,
numListeners, valueClasses. The rest is only of interest to the class
that owns the signal and could be different for different
implementations (as is the case with Robert's NativeSignal).

Joa Ebert

unread,
Nov 23, 2010, 5:49:53 PM11/23/10
to as3-signals
That is right Tyler. I did add pools to signals, but removed them
since it is very hard to know when to retain them. It is possible but
makes client code a little bit more complex, or error prone. We have a
framework for this at Audiotool but it would be total overkill. In the
end, you do not add/remove Signals the whole time and it is clearly
not the bottleneck.

However a SignalBinding is always created and stored internally. So it
would be garbage collected only when you remove it from the signal
(and keep no reference to it).

But then again, if we add support to use ISignalBinding directly, you
can provide your implementation that is pooled and comes with extra
logic.

Richard Lord

unread,
Nov 23, 2010, 5:51:49 PM11/23/10
to as3-signals
P.S. For the fast signal with no verification, I like the name
"LeanSignal".

Stray

unread,
Nov 23, 2010, 6:07:41 PM11/23/10
to as3-s...@googlegroups.com
Just interested Richard - how do you test that your mediators respond to view signals appropriately?

If I make my getters return ISignal then I can only do genuine gui testing, because my test can't dispatch() on the view's behalf.

I have scratched my head but I can't find a neat way around it.

Mario Vieira

unread,
Nov 23, 2010, 5:56:06 PM11/23/10
to as3-signals
If I may drop an another idea. Not that I want to promote anything
(even because I'm FDT supported), isn't FlashSignals a name? Flash as
in quick.
Just an idea anyway, an obvious one :)
Mario Vieira

On Nov 23, 3:58 am, Robert Penner <i...@robertpenner.com> wrote:
> I'm quite open to Joa's proposals at this point, partly because I love to
> delete code. I just wanted to make sure we have a chance to discuss before
> APIs are removed.
>
> IDispatcher:
>
> I made and unit tested it, but I've never used it.
>
> ISignal getting dispatch() and removeAll(), removing "owner" interfaces:
>
> The current design was based on rationales that we agreed on, chiefly,
> making it difficult for listeners to affect other listeners. The question is
> whether the increased complexity of more interfaces is worth the payoff. If
> I'm honest, I think it's a nice concept but not really a big concern in the
> real world. AS3 EventDispatcher.dispatchEvent() is public, but I doubt many
> bugs result that would be prevented by restricting access to that method.
>
> "FastSignal":
>
> I think it should have its own name, but something besides "Fast". Remember,
> Signal is already plenty fast for the vast majority of applications.
>
> Other ideas:
>
> SimpleSignal
> BareSignal
> UntypedSignal
> GenericSignal
> Zzzzzignal (pronounced with Doppler shift)
>
> RobertOn Mon, Nov 22, 2010 at 2:32 PM, BigP <chamberlai...@gmail.com> wrote:
> > Hi, actually new to as3-signals here, but loving what I read about it
> > so far.
>
> > If there's a concern whether FastSignal should be included in the core
> > of as3-signals, could there be two SWCs provided?
>
> > something like as3-signals.swc - and - as3-signals-dbg.swc?
>
> > So in a sense, what I'm suggesting, keep this "Fast" signal's
> > classname as Signal, but compile it in a production-ready SWC (or make
> > seperate prod and debug source folders available).
>
> > If they both do essentially the same thing, but one library simply
> > doesn't type-check and speeds up signals performance, I would think:
> > leave it up to the developers to choose which library to use (when
> > they've all tested and validated their work).
>
> > Anyways, hope my first post here isn't too irrelevant!
> > Great to see so much collaboration on this library :)
>
> > On Nov 22, 5:25 pm, Joa Ebert <joaeb...@googlemail.com> wrote:
> > > You are absolutely right Joel. I think it is a total edge case. From
> > > my performance tests the signals should be sufficient for any large
> > > scale application. And they were fast enough before as well.
>
> > > Another note on the interface suggestion:
>
> > > public class Dispatcher {
> > >   private var _signal: ISignal;
> > >   public function Dispatcher(signal: ISignal) {
> > >     _signal = signal;
> > >   }
>
> > >   public function dispatch(...rest): void {
> > >     _signal.dispatch.apply(null, rest)
> > >   }
>
> > > }
>
> > > The right way to do it in my opinion. An interface is not abused a an
> > > access modifier and you get real encapsulation.
>
> > > On Nov 22, 9:19 pm, "joelho...@gmail.com" <joelho...@gmail.com> wrote:
>
> > > > On Mon, Nov 22, 2010 at 11:58 AM, Joa Ebert <joaeb...@googlemail.com>
> > wrote:
>
> > > > > Last but not least I think it would be also quite nice to have
> > another
> > > > > ISignal implementation that behaves like Signal but is dead simple
> > and
> > > > > does no verification at all. That way, you as a user of the signals
> > > > > library can use the Signal clas in debug mode (to get nice error
> > > > > messages) and switch to the FastSignal for production code.
>
> > > > > Please tell me what you think.
>
> > > > I think this implementation would be something that would make an
> > excellent
> > > > external add-on to Signals. My problem with including it in the care
> > library
> > > > is that people would assume that it would be the GOTO Signal. Who
> > doesn't
> > > > want a faster Signal? Right? Which leads to the need to explain often
> > what
> > > > it is, why to use it, and what those odd errors in a users app mean.
>
> > > > I tend to err on the side of modularity where possible though, and
> > perhaps I
> > > > am being too conservative. Signals are already faster than Events from
> > the
> > > > benchmarks I've seen. Needing something much faster is definitely an
> > edge
> > > > case.
>
> > > > -j

Richard Lord

unread,
Nov 24, 2010, 2:48:06 AM11/24/10
to as3-signals
Hi Stray

For a unit test, I would mock the view and expose the Signal object in
the mock so I can dispatch the signal; often the easiest way to do
this is extend the view and add a getter to expose the protected
Signal.

For an integration test, I would trigger the action on the View object
that causes the signal to be dispatched; sometimes that might require
a tool like FlexMonkey but often its as simple as dispatching a click
event from a button, which can be done in code.

Stray

unread,
Nov 24, 2010, 4:38:45 AM11/24/10
to as3-s...@googlegroups.com
Thanks Richard,

Classic - I use 'support mocks' all the time for models and VOs - and in the VO situation it's also to allow me to change properties on an immutable VO for ease of testing... but it never occurred to me to take that approach with views/signals.

I can see how a support wrapper with methods like dispatchSomeSignal(valuesThatMatchTheSignalValues...) would work, and is declarative.

I use Roboteyes rather than FlexMonkey (as I don't use flex) and I do dig down into the display list to fire events for integration tests - but you can end up having to do a whole bunch of set up on the view as well, if it passes values from its form fields for example.


However... doesn't the library situation make it harder? Especially if the utility creator has made the signals private rather than protected and so you can't extend the class to get access?

I don't run into any problems with testing via the eventDispatcher - where we can dispatchEvent() - and I haven't found any problems with my Signals test approach being the same.

In my experience, incorrect use of private vs protected is more common than abusing the ability to dispatch from outside - but perhaps that's not our problem to fix?

Richard Lord

unread,
Nov 24, 2010, 6:34:41 AM11/24/10
to as3-signals
Hi Stray

"In my experience, incorrect use of private vs protected is more
common than abusing the ability to dispatch from outside". Probably,
yes. But as you suggest, I don't think we can fix misuse of private/
protected here.

Nikos Katsikanis

unread,
Nov 24, 2010, 8:03:12 AM11/24/10
to as3-s...@googlegroups.com
This is one awesome discussion going on here :)

Joa Ebert

unread,
Nov 28, 2010, 4:49:57 PM11/28/10
to as3-signals
I would like to get rid of the NativeSignal and NativeRelaySignal
signal disambiguation. When I implemented the new changes in
NativeSignal I basically had to duplicate a lot of code and then
figured out that it was a re-implementation of the NativeRelaySignal.

So I would like to delete NativeSignal and rename NativeRelaySignal to
NativeSignal. The fact that NativeSignal (used to ;)) use the native
dispatch vs. one meta listener is only a very implementation specific
detail which one should not rely on anyways since signals are ment to
abstract this from the user.

I would also like to implement INativeDispatcher in the
NativeRelaySignal (which would be renamed to NativeSignal).

Toughts? Is there any particular need for the NativeSignal/
NativeRelaySignal implementation difference?


Best,

Joa

Joa Ebert

unread,
Nov 28, 2010, 4:58:28 PM11/28/10
to as3-signals
One more thing:

var target: URLLoader = ...
var signal: ISignal = new NativeSignalAggregator(target,
IOErrorEvent.ERROR, SecurityErrorEvent.ERROR, Event.CLOSE)
signal.add(function(event: Event): void { trace('loader has been
closed becasue of '+event+'...') })


What do you think? A way to aggregate multiple native events with one
signal.

Mario Vieira

unread,
Nov 28, 2010, 5:12:26 PM11/28/10
to as3-s...@googlegroups.com
sounds very useful though.
I just created 2 instances for one operation...
 
_loadSerializedItem = new NativeSignal(_crud.urlLoader, Event.COMPLETE, Event);
_loadError          = new NativeSignal(_crud.urlLoader, IOErrorEvent.IO_ERROR);


_loadSerializedItem.add(onRetrieve);
_loadError.add(onError);

Tyler Wright

unread,
Nov 29, 2010, 2:04:45 PM11/29/10
to as3-s...@googlegroups.com
What do you think? A way to aggregate multiple native events with one
signal.
 
This approach is reflected in a Flight Framework concept called Response, except that Response is unique to an individual call. Jacob blogged on the general concept though it may have come a little ways since then.

More or less the Response object represents a request to some service (sync or async) and allows "listeners" to be added to its completion or cancelation. The response object is returned in-line to the caller which can then add the listeners. It also has progress updating.

There are possible approaches or compatibilities that can be gleaned from the solution for a NativeSignalAggregator.

Tyler 

Robert Penner

unread,
Nov 29, 2010, 8:30:58 PM11/29/10
to as3-s...@googlegroups.com
> var signal: ISignal = new NativeSignalAggregator(target,
> IOErrorEvent.ERROR, SecurityErrorEvent.ERROR, Event.CLOSE)

This is useful and someone asked for something like this a few weeks ago.

Robert

Robert Penner

unread,
Nov 29, 2010, 8:53:18 PM11/29/10
to as3-s...@googlegroups.com
> When I implemented the new changes in
> NativeSignal I basically had to duplicate a lot of code and then
> figured out that it was a re-implementation of the NativeRelaySignal.

You didn't *have* to duplicate that much code; that's what you chose to do. =)

The concept behind NativeSignal is to use the native EventDispatcher
as much as possible, while adding Signal features on top. "Running
close to the metal"--not for performance reasons but in order to make
fewer assumptions about how EventDispatcher does what it does, and who
else is using it outside of Signals.

///////// Review for others
The main difference in the pre-Joa version is that--

nativeSignal.add(func);

--will directly call target.addEventListener(func). The listener is
directly wired to the EventDispatcher and when it dispatches, there is
no intermediary.

With nativeSignal.addOnce(func), we have to create an intermediary
that calls nativeSignal.remove(func) and then func(). But still there
is a one-to-one correspondence.

The NativeRelaySignal approach is to add a custom handler to the
EventDispatcher that will catch native dispatches and relay them to
the signal's listeners. The difference from NativeSignal was that if
NativeRelaySignal added 5 listeners, it would only have added one
listener to the EventDispatcher.

What Joa did was code the NativeRelaySignal approach into
NativeSignal, seen here:

https://github.com/joa/as3-signals/blob/2be6d9874f65223f2d2cb6d674117b07375e7109/src/org/osflash/signals/natives/NativeSignal.as#L231
/////////

My concern with abolishing the close-to-the-metal approach of
NativeSignal is that it may be messy in some use cases where normal
addEventListener() calls are mixed with signals, especially where
bubbling or priority is involved.

For example, if two listeners are given priorities 1 and 3 with
addEventListener() and two other listeners are giving priorities 2 and
4 with NativeSignal, how can they be called in the right order with
Joa's latest NativeSignal? I don't have a unit test for this but it
would be a good one.

Robert

Joa Ebert

unread,
Dec 1, 2010, 5:02:06 AM12/1/10
to as3-signals
I agree that it makes sense to have a bare-bones approach. But it
should not feel like the default implementation which the name
NativeSignal suggests.

What aboud having a different kind of native signal that is doing what
NativeSignal in the original code was doing? I have no idea for the
name yet, EventDispatcherFacade is kind of right but loses the signals
idea.


Best,

Joa
> https://github.com/joa/as3-signals/blob/2be6d9874f65223f2d2cb6d674117...

Robert Penner

unread,
Dec 1, 2010, 1:30:37 PM12/1/10
to as3-s...@googlegroups.com
> I agree that it makes sense to have a bare-bones approach. But it
> should not feel like the default implementation which the name
> NativeSignal suggests.

To me, "bare-bones" implies fewer features, but NativeSignal has
essentially the same features as NativeRelaySignal.
I would argue that the current NativeSignal is "more native" than is
NativeRelaySignal.

> What aboud having a different kind of native signal that is doing what
NativeSignal in the original code was doing?

By "different kind" do you mean a simple rename, or something else?

Robert

simon

unread,
Dec 2, 2010, 5:21:52 AM12/2/10
to as3-signals
Currently in Joa's implementation the getter and setter "target" is
still in the DeluxeSignal, but hasn't made it to the interface
IPrioritySignal nor ISignal, yet it's still being overridden and
[Deprecated] in the NativeSignal. My question is, should this be
reinstated to the IPrioritySignal interface or even the setter being
dropped? Or are we happy that the getter/setter is currently attached
to the DeluxeSignal only? I was actually wondering what are the use
cases for changing the target on an existing DeluxeSignal, should we
be able to?

Simon.

On Dec 1, 6:30 pm, Robert Penner <i...@robertpenner.com> wrote:
> > I agree that it makes sense to have a bare-bones approach. But it
> > should not feel like the default implementation which the name
> > NativeSignal suggests.
>

Tyler Wright

unread,
Feb 2, 2011, 2:19:45 PM2/2/11
to as3-s...@googlegroups.com
Like Joa I like the thought of simplifying the Interface to Signals. I'd like to pick up the discussion again and offer some suggestions.

I made some changes in my uisignals branch to illustrate: http://j.mp/hjkBQa 
  • combined interfaces ISignalDispatcher & ISignalOwner into ISignal
  • combined similarly in the native interfaces
the above are similar to Joa's proposal, the next are the deviations:
  • added ...params in each add/addOnce for pass-through values provided to the listener
  • removed valueClasses requirement in the Interface, though left it as a feature of the Signal implementation
Everything besides the ...params is a simplification that I don't think will have much effect on Signal implementations, though may cause strain on apps that use signals and have used the ISignalDispatcher interface, etc. However the ...params constitutes a new feature that would be required by concrete Signals, so that's one for scrutiny.

Thoughts?
Tyler

Stray

unread,
Feb 2, 2011, 4:35:20 PM2/2/11
to as3-s...@googlegroups.com
I'm definitely pro the combining of the interfaces.

Can you describe your use case for the ...params arguments?  I'm struggling to think of one that wouldn't be more elegantly solved in the class where the handler is.

If you know what the args are at the point of adding the handler, wouldn't it make more sense to create the handler function at runtime with those args already inside it?

Obviously valueClasses is still needed at a protected level - my concern about removing it from the public API is that you then force people to add functionality by extension rather than composition - though I guess they could always create a wrapper interface that included the valueClasses, extend just adding that getter and then compose from there.

I think it has value as a quick-debugging-of-black-box-code tool as well. If I'm trying to work with your code and I'm not sure what the value classes order is, I can just trace someSignal.valueClasses and I'm golden in 30 seconds ... but perhaps that's a weak use case?

Stray

karfau

unread,
Feb 2, 2011, 5:40:45 PM2/2/11
to as3-signals
After all the great discussion about merging the interfaces:
I like the idea of having the interfaces simplified, and ISignal being
the fully capable thing everybody starts with
(and getting rid of ISignalOwner and IDispatcher).

But would it be so confusing/disturbing if ISignal just extends a
IRestrictedAccessSignal/IListenerSignal (maybe with a better name)
that only allows add,addOnce and remove (and if needed numListeners)?
This would still allow building restricted APIs and keep the
interfaces clean. (In my opinion.)



just my 2 cents,
karfau

Tyler Wright

unread,
Feb 2, 2011, 5:45:06 PM2/2/11
to as3-s...@googlegroups.com
Can you describe your use case for the ...params arguments?  I'm struggling to think of one that wouldn't be more elegantly solved in the class where the handler is.

If you know what the args are at the point of adding the handler, wouldn't it make more sense to create the handler function at runtime with those args already inside it?

Very good points - my reasoning: Events/Signals represent logic that is delayed, asynchronous, something that I'll have to pick up later outside of current context (scope). For example, loader.completed.add(loadComplete); Because of this you don't have direct access to the local variables of your current scope without creating a run-time function as you mentioned. Creating local functions has been taboo for me since AS2 days, I think something to do with how Flash held onto memory to maintain scope.

However, I've realized that NativeSignal by nature can't support the added feature, being that it wraps EventDispatcher and it's not a feature provided by ED. So I think that fact combined with your valid points of alternative approaches kills this feature. Unless NativeSignal is converted permanently into NativeMappedSignal.

Obviously valueClasses is still needed at a protected level - my concern about removing it from the public API is that you then force people to add functionality by extension rather than composition - though I guess they could always create a wrapper interface that included the valueClasses, extend just adding that getter and then compose from there.

I haven't used Signals a lot yet but it seems the use-case is that ValueClasses are defined when the Signal is created and then it's all internal afterwards. If that's true, then the one time you need to reference valueClasses is when you are referencing the concrete class: new Signal( ...valueClasses);

I think it has value as a quick-debugging-of-black-box-code tool as well. If I'm trying to work with your code and I'm not sure what the value classes order is, I can just trace someSignal.valueClasses and I'm golden in 30 seconds ... but perhaps that's a weak use case?

For pure debugging purposes someSignal['valueClasses'] works just as well. If we're going for elegance. :)

So ...params isn't necessary and it creates undue requirements on signal implementations, but I feel the same for valueClasses - undue implementation requirements. Of course an empty interface allows me the most flexibility to build what I want but doesn't provide any value either, so stop me if I'm going too far.

thanks!
Tyler

Zachary Pierce

unread,
Feb 2, 2011, 5:49:36 PM2/2/11
to as3-s...@googlegroups.com
Here's a notable use case for keeping the valueClasses property around in the public Signals interfaces.

The valueClasses property of ISignal is used by Joel Hooks' excellent SignalCommandMap extension for Robotlegs.  Having access to the valueClasses regardless of ISignal implementation is pretty important if any Signals+Robotlegs lovers out there want to mix and match their Signals implementations.

Even if you don't care about Robotlegs in particular, the valueClasses field is currently the only standardized means of runtime inspection into exactly what a signal expects to be passed through its dispatch.  I'd rather not miss out on whatever imaginative injection, manipulation and analysis future libraries that build on Signals might conjure up using this data.

Also, while I doubt many people use this option, the valueClasses setter theoretically presents a means of changing a signal's expected parameters post-construction. If you want to wire up signals dynamically, or reuse signal objects in an object-pooling scheme, such a setter would be handy.  I don't necessarily suggest this level of dynamism, but recognize its potential value.

TL;DR Summary:  Please keep the public valueClasses getter around in the interface(s).  It's really in use.
The valueClasses setter is less important, but possibly powerful.

karfau

unread,
Feb 2, 2011, 7:08:29 PM2/2/11
to as3-signals

Thats exactly what I think about valueClasses in the interface.

Robert Penner

unread,
Feb 2, 2011, 9:25:55 PM2/2/11
to as3-s...@googlegroups.com
I was going to say what Zachary said about SignalCommandMap, to which
I and my colleagues are now addicted.

I'll add that valueClasses is central to what a Signal aspires to be:
a multi-cast type-safe delegate. We can't currently express that
pattern very elegantly in AS3 compared to other languages. But if/when
we get generics and function types, look out.

The reason valueClasses was recently made writable was to enable MXML
definition, e.g.:

<!-- With Flex SDK 4, a single value class can go in the attribute,
using only curly braces.
With Flex SDK 3, it must be wrapped in an array: {[Boolean]} -->
<signals:Signal id="tabEnabledChanged" valueClasses="{Boolean}"/>

<!-- Wrap multiple value classes in square braces. -->
<signals:Signal id="tabIndexChanged" valueClasses="[int, Boolean]"/>

https://github.com/robertpenner/as3-signals/blob/master/tests/org/osflash/signals/support/SpriteWithSignals.mxml

Robert

joel...@gmail.com

unread,
Feb 2, 2011, 11:27:24 PM2/2/11
to as3-s...@googlegroups.com
In terms of Flex declaration I really like what Jens Halm has done in
Parsley. He defines Tag classes and uses a manifest to 'rename' the
tag class for declaration. The declaration is really a wrapper and
allows for validation and other functionality.

karfau

unread,
Feb 3, 2011, 9:22:30 AM2/3/11
to as3-signals


On 3 Feb., 03:25, Robert Penner <i...@robertpenner.com> wrote:
>
> The reason valueClasses was recently made writable was to enable MXML
> definition, e.g.:
But that is not a reason to put it on the interface, is it?
MXML always needs classes for its tags.

And if it is very important to force this functionality for Signal-
Extensions maybe another interface is needed: IMXMLSignal.
(Hm, i know we were just trying to reduce those interfaces, but...)

karfau

Tyler Wright

unread,
Feb 3, 2011, 12:19:24 PM2/3/11
to as3-s...@googlegroups.com
It's not essential to have valueClasses for MXML because your tags are concrete types - you don't create interfaces:

<signals:Signal id="tabIndexChanged" valueClasses="[int, Boolean]"/>
vs
<signals:ISignal id="tabIndexChanged" valueClasses="[int, Boolean]"/>

The interface is for public API and does not restrict implementation, just public access outside of instantiation scope. If valueClasses are used, or could be used, from the outside looking in, on all ISignal implementations generically, then it's a keeper. And if not it's still a keeper, just in the implementation of most Signals and not necessarily in the Interface.

Robert said ~ valueClasses is central to what a Signal aspires to be:
a multi-cast type-safe delegate. We can't currently express that
pattern very elegantly in AS3 compared to other languages.

- that's good enough for me. I think most of the other reasons are implementation-specific and can be handled there, but if it's a core concept then I should change the way I'm conceptualizing Signals.

thanks!
Tyler

markstar

unread,
Feb 4, 2011, 4:16:41 AM2/4/11
to as3-signals
Why are people discussing removing things from the ISignal interface?
You can't start removing things in a library, especially one as big as
this. Developers are using this in their production code and could be
relying on those elements you wish to remove. Everyone knows that once
you make an API public (i.e. you release the library) that you can
only add things, not remove them.

I for one rely on valueClasses being part of the ISignal interface in
my StarRequests library.

I also agree that dispatch() shouldn't be part of ISignal.

The improves suggested by Joa look very interesting.

Cheers,

Mark

On Feb 3, 5:19 pm, Tyler Wright <xty...@gmail.com> wrote:
> It's not essential to have valueClasses for MXML because your tags are
> concrete types - you don't *create* interfaces:
>
> <signals:*Signal* id="tabIndexChanged" valueClasses="[int, Boolean]"/>
> vs
> <signals:*ISignal* id="tabIndexChanged" valueClasses="[int, Boolean]"/>

Robert Penner

unread,
Feb 4, 2011, 10:18:46 AM2/4/11
to as3-signals
> Everyone knows that once
> you make an API public (i.e. you release the library) that you can
> only add things, not remove them.

This is true from 1.0 onward. Developers who build to a prerelease
like v0.8 assume a risk of API change. They can stay with v0.8 forever
if they like, but if they want to migrate to a newer version it's
their responsibility to deal with API changes.

http://semver.org/

"Major version zero (0.y.z) is for initial development. Anything may
change at any time. The public API should not be considered stable.

Version 1.0.0 defines the public API. The way in which the version
number is incremented is now dependent on this public API and how it
changes."

Robert

Stray

unread,
Feb 4, 2011, 10:19:56 AM2/4/11
to as3-s...@googlegroups.com
Signals is still a 0.x release - so Robert / the people developing signals are at liberty to change the API - and it has changed somewhat between 0.6 and 0.8, with the creation of the compound interface etc.

The library is still under development - and until it's 1.0 then there's no real 'rules' regarding semantic versioning - at which point I have no doubt that Robert will absolutely follow the versioning rules because he's a stickler for them as far as I can tell.

Early adoption has its drawbacks. The feedback that comes from the 0.x releases should be used to shape the 1.x release API, but to suggest that because some people have started using it before it was a 1.0, there can be no 'breaking' changes for the 1.0 release is just unworkable. That's the whole point of a beta release - that you know it's not right yet and you need to find out what's not right about it.

Stray

Simon Richardson

unread,
Feb 4, 2011, 10:23:33 AM2/4/11
to as3-s...@googlegroups.com
This does beg the question though, should we be already at version 1.0.0 already?

Quote from the FAQ:
How do I know when to release 1.0.0?

If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you're worrying a lot about backwards compatibility, you should probably already be 1.0.0.

The reason I state this, is that I know there is already a lot of software in production that is running Signals. So should we be already looking at version 1.0.0 and then new changes should be revision on that?

si

Stray

unread,
Feb 4, 2011, 10:35:28 AM2/4/11
to as3-s...@googlegroups.com
The impression I got from Robert's "Discuss the possible API changes: GO!" message was that - based on the outcome of that discussion - 1.0.0 probably isn't that far away now.

Is that right Robert?

Robert Penner

unread,
Feb 4, 2011, 10:58:59 AM2/4/11
to as3-s...@googlegroups.com
In my recollection, FlexUnit, Swiz and RobotLegs were widely used in
production before hitting 1.0.

A few months ago I thought Signals had stabilized and was on the verge
of a 1.0. But then Joa entered the picture. =) The level of
discussion on the list has shot up as well. I would like the 1.0 to
include these developments. For example, I'm so over ISignalOwner and
IDispatcher and I and I'd rather not drag them around until 2.0.

I would like to see specific topics in these long discussions split
into separate threads so we can hash them out, decide and implement.

Robert

Robert Penner

unread,
Feb 4, 2011, 11:01:26 AM2/4/11
to as3-s...@googlegroups.com
> 1.0.0 probably isn't that far away now.

It feels like we can get to 1.0 within a few months. Starting 3 weeks
from now I'll have a lot more free time. As in order of magnitude. =)

Robert

Joa Ebert

unread,
Feb 5, 2011, 3:47:51 AM2/5/11
to as3-s...@googlegroups.com
1) Signals with changes is pretty much backwards compatible.
2) Do not use it if you are happy with the old version.
3) This thread is exactly the place to raise your concerns, valueClasses is something people rely on so I think it should be kept.
Reply all
Reply to author
Forward
0 new messages