views:

194

answers:

4

I just started using Swiz, and, it seems like Swiz forces you to create classes with weak encapsulation. Swiz requires all event handlers to be public in order to mediate events.

Assume that component 'A' dispatches a few events, which I want to listen to in component 'B'. Traditionally, I'll just add event listeners on 'A' in 'B' and all the event handlers in 'B' can be kept private. However, if, I am using Swiz, I need to make all the handlers, mediating events, public.

Am I missing something here, is there a way to bypass this problem. I really, don't want to pollute the public interface of my class.

Thanks.

+3  A: 

As I mentioned on the mailing list, there is no way around it, unfortunately. Since there is no way to access private members of classes, the only way B can use private event handlers for events from A is if addEventListener() is called from within B. Since Swiz is obviously not operating within your classes, it has no way to access those members.

Swiz aims to keep your application code as free from references (including inheritance) to Swiz classes as possible. Therefore, you can think of it as configuring your app "from the outside". Unlike the JVM, Flash Player simply allows no access to private members, so for Swiz to interact with your code, it has to be public.

bclinkinbeard
A: 

For something outside of and decoupled from the class to invoke the handler, the method can't be private. So you have two choices: make them public and let Swiz mediate them (and reap all the loose coupling), or keep them private and don't use the event mediation. If you think it's worth it (and most do), use it. If you don't, don't.

brian428
Clearly someone doesn't understand how to not sound like a jerk.
Karl
I can see how answering the actual question in a matter-of-fact way would make me sound like a jerk. Sorry. Next time I'll be sure to sugar-coat it so that everyone feels all warm inside.
brian428
GMan
+4  A: 

You can also create a custom namespace that makes them not necessarily public, but not private either. I use what Openflux originally did:

[Mediate(event="UserEvent.LOGIN")]
metadata function loginHandler(user:User):void
{
    ... with namespace
}

[Mediate(event="UserEvent.LOGOUT")]
public function logoutHandler(user:User):void
{
    ... without namespace
}

You then have to add use namespace metadata into the Swiz Processors, and probably to their metadata MediateQueue. As long as the namespace is imported in the correct classes, something that's dynamically referring to a method will work:

so in the setUpMetadataTag method in MediateProcessor (or at the top of the class):

use namespace metadata;
// bean.source[mediateTag.host.name]
// service["loginHandler"] and service["logoutHandler"] both work
addMediatorByEventType( mediateTag, bean.source[ mediateTag.host.name ], eventType );

Makes the code clean, and keeps things from being public. But some people think it's too much work :).

Best, Lance

viatropos
I'm putting all methods that are annoteded with [Mediate] or [PostConstruct] in a custom namespace. Since Swiz 1.0 RC1 you don't even have to patch any Swiz classes. It works out of the box.
Gerhard
A: 

"Swiz requires all event handlers to be public in order to mediate events."

That's true, but Swiz's strength is that it doesn't force any (more or less) design choices on you, it just provides powerful tools (dependency injection, event mediation, et al) that you can choose to apply where you think appropriate.

Using Swiz does not require the use of the [Mediate] tag at all - you can still use addEventListener() and listen from private methods as you normally would (as I'm sure you're well aware). As far as I can tell, the Swiz event mediation is intended primarily for use with system/application level events. If you're calling event listeners within a single component, or within close family components, you would usually use the standard event listeners. To communicate between individual, otherwise-unrelated components, you can handle the message with Swiz's mediator.

In short, in any case where you have access to private event listeners (i.e. within close components), you probably wouldn't be using [Mediate] to capture the event, and so that listener could remain private. When you're using the [Mediate] tag, the event handler is generally in a completely separate location in the application (e.g. presenter -> controller) where it couldn't practically be private in any case.

I may be slightly off, but this is how it appears to me. Swiz may encourage weak encapsulation in some situations, but to me it offers greater modularisation overall.

Pie21