
So I had surgery 2 nights ago. Routine Gall bladder thing. But the pain killers, namely morphine, keep me awake, contrary to their typical side effects. This left me up all night, in a hospital room, with such a calm mind and strange thoughts, that my desires for Actionscript began to crystalise.
These are meant to be idea’s to argue over, so please do comment.
Groovy’s Safe Navigation Operator is pretty straight forward:
var a:String = b?.c?.e
If b evaluates to null, a is null. Same for c.
It’s wonderful. I really don’t think I need to use Null Objects as often as I do.
“Alan Kay’s meaning of OOP” and ObjC’s message passing got me thinking about thorough bi-directional decoupling. In the vWork application code, we have a considerable number of modules, which use a notifier bus (Robotlegs Modular context) to pass messages between modules. To properly decouple ‘Module A’ from ‘Module B’, I ended up with something like:
module.a.events.IRaiseThisEventOnTheBus
module.b.events.IExpectThisEventToBeRaised
or to be more concrete:
module.map.workerSelectedEvent
module.workerManager.selectWorkerEvent
and then I have a ‘master’ module manage the coupling. It listens for ‘workerSelectedEvent’ and fires the selectWorkerEvent. Now neither module has an import from the other…
And this is the rub. My master module (usually the application boot module) has knowledge (read: imports) of both modules. Thats not a truly decoupled program.
So the obvious way to get true decoupling is to use untyped messages. Like ruby, or ObjC might do. It works because a module can dissapear, and the other ‘dependent’ module is just listening for a magic string or symbol that never arrives.
I don’t like this approach, because I like type-safety.
My solution is to allow namespaces and classes to be missing. A kind of null-safety if you will. I can only describe it in code:
Describe an event class:
package module.map.events {
import flash.events.*
public class WorkerSelectedEvent extends Event {
... event boilerplate ...
public function get payload():TypeSafeThing {
return _payload;
}
}
}
And ‘Maybe’ consume it:
package module.workerManager.config {
use module.map.events.WorkerSelectedEvent;
use module.map.TypeSafeThing;
public class Config {
... stuff ...
public function configWorkerListener() {
if (WorkerSelectedEvent is _UndefinedClass)
return;
bus.addEventListener(WorkerSelectedEvent.SELECTED, selectedHandler);
}
}
}
Where ‘use’ is defined instead of ‘import’, the compiler will find the Class, but if it cannot, it will replace it with an instance of _UndefinedClass, which has no methods or behaviour, it’s just a marker.
I would quickly replace EventDispatchers with something like Rob Penner’s signals (although I want to see c# style delegates, which I’ll cover in part 2). A signal/delegate message passing system could happily accept an _UndefinedDelegate and make most of this decoupling transparent.
I suspect ‘use’ would be the defacto when specifying message classes/delegates.
© 2010 - VisFleet Ltd
No prawns were harmed in
the making of this website
Comments