SwiftSuspenders and the robot-legs problem

145 views
Skip to first unread message

Till Schneidereit

unread,
Nov 16, 2009, 6:46:53 AM11/16/09
to robotlegs
After re-reading lots of info about the robot-legs problem and
studying Josh's proposal for dealing with it (seen here:
http://groups.google.com/group/robotlegs/msg/315473ea4d375ffd), I
think I might have a good proposal for dealing with in in
SwiftSuspenders.

Basically, since the introduction of mapRule, everything should
already be in place API-wise - except for actually creating child
injection contexts. Thus, my proposal would be to add one method to
SwiftSuspender's injector:
Injector#createChildContext(usedWhenApplyingRule : InjectionConfig) : IInjector;

I hope that I'm not missing anything when I think that child contexts
should be used depending on the currently applied rule. If I do, this
obviously won't work as advertised.

Anyway, using this API, Josh's example as implemented with
SwiftSuspenders would look like this:

//the injectees would stay the same, of course
class ArmlessRobot
{
[Inject(name="left")]
var leftLeg:RobotLeg;

[Inject(name="right")]
var rightLeg:RobotLeg;
}

class RobotLeg
{
[Inject]
var foot:RobotFoot
}

class LeftFoot extends RobotFoot { ... }
class RightFoot extends RobotFoot { ... }

//here's where things change:
function configureInjector(injector : IInjector):void
{
// ...

var leftLegRule : InjectionConfig = injector.mapClass(RobotLeg,
RobotLeg, 'left');
var rightLegRule : InjectionConfig = injector.mapClass(RobotLeg,
RobotLeg, 'right');

var leftLegContext : IInjector = injector.createChildContext(leftLegRule);
leftLegContext.mapClass(RobotFoot, LeftFoot);

var rightLegContext : IInjector = injector.createChildContext(rightLegRule);
rightLegContext.mapClass(RobotFoot, RightFoot);

// ...
}

To me, this looks quite clean and straight forward.
There's one snag, though: the way the dependencies between Robotlegs
and SwiftSuspenders are set up (with Robotlegs depending on
SwiftSuspenders, but not the other way 'round), there's no way to
return types from SwiftSuspenders that Robotlegs knows about. I had
that same problem with Injector#mapRule and resolved it by typing
mapping rules as "*". This kinda worked for that usecase, but it won't
for creating child contexts.
I can only think of two different for solving this problem, of which I
tentatively favor the second one:
1: Integrate SwiftSuspenders into Robotlegs, making the point moot
2: Don't even try to encapsulate the feature. Instead, "just inject
it" into the startup command where the mappings are done, with "it"
being the SwiftSuspenders injector, typed as the concrete class which,
in distinction from IInjector, exposes the createChildContext method.

Another question would be that of when to implement/ integrate this
functionality. If we go the 2nd route, Robotlegs wouldn't be affected
at all, so maybe that's something I should mostly deal with on my own,
but even then I'd really appreciate feedback. My proposal for that'd
be getting SwiftSuspenders 1.0 out of the door quickly and then
pushing out a 1.1 with createChildContext after that. Depending on how
quickly I get through with that, we can then decide with which version
Robotlegs 1.0 should ship.

So, what do you all think about this?


cheers,
till

Till Schneidereit

unread,
Nov 17, 2009, 6:15:28 AM11/17/09
to robotlegs
Any thoughts about this at all? I'm really eager to get started with
this but was hoping for some feedback to the proposed API first.

--
Till Schneidereit
Schneidereit Link GbR
technical concept, consulting, development
Tel: +49 40 970 7848 1

Shaun Smith

unread,
Nov 17, 2009, 12:17:15 PM11/17/09
to robo...@googlegroups.com
Hi Till,

Apologies, I haven't had a chance to wrap my head around this (or
Josh's proposal) yet. I'm not doing much as3 right now (doing a lot of
server-side dev at the mo), so the context switching is causing me
some trouble. Will dig in later tonight.

Till Schneidereit

unread,
Nov 17, 2009, 12:25:12 PM11/17/09
to robo...@googlegroups.com
Hey Shaun,

no worries, it's not like I absolutely need anything from you to get
this started. I thought about the issue some more and am now pretty
confident that my plan should work out. Thus, I think I'm going to
start implementing that tomorrow. With any luck, it won't take more
than a few hours.

There's one interesting point that affect RL, though, and that's about
how to integrate this functionality into RL. I'm more and more
thinking that we shouldn't integrate it at all and just let people
inject the SwiftSuspenders injector into their startup command with
the concrete type. With mapRule, things were pretty hairy already.
With createChildContext, there's just no clean interface to be had,
without marrying the project. And seeing as you where able to fully
resurrect the SP adapter, I think we should relegate such advanced
features to direct usage of the DI solution.

Shaun Smith

unread,
Nov 17, 2009, 6:26:50 PM11/17/09
to robo...@googlegroups.com

On 16 Nov 2009, at 1:46 PM, Till Schneidereit wrote:

> function configureInjector(injector : IInjector):void
> {
> // ...
>
> var leftLegRule : InjectionConfig = injector.mapClass(RobotLeg,
> RobotLeg, 'left');
> var rightLegRule : InjectionConfig = injector.mapClass(RobotLeg,
> RobotLeg, 'right');
>
> var leftLegContext : IInjector =
> injector.createChildContext(leftLegRule);
> leftLegContext.mapClass(RobotFoot, LeftFoot);
>
> var rightLegContext : IInjector =
> injector.createChildContext(rightLegRule);
> rightLegContext.mapClass(RobotFoot, RightFoot);
>
> // ...
> }

Cool, I think the word "context" was throwing me off a bit - I've
worked up such a disliking towards the word that it makes my vision go
blurry (I'll save that for post-v1.0 discussions though!).

Could it not be written as:

var leftLegInjector : IInjector =
injector.createChildInjector(leftLegRule);

I just think createChildContext() would be confusing for RL users (due
to bad naming on my part, but still).

Also, what if it was injector.getChildInjector(Rule)? "Get" instead of
"create", as in: it returns the same object if passed the same rule.
Thinking aloud:

var childInjector : IInjector = injector.getChild(Rule);

or:

var childInjector : IInjector = injector.forRule(Rule);

It might not be worth the effort trying to get the RL adapter to
support this directly. Besides, I think that the people who'd make use
of this would already be dealing with their DI container/injector of
choice directly (rather than the RL adapter). Speaking of which: we
should probably add getAdaptee() to IInjector... maybe.

Thoughts?
> --~--~---------~--~----~------------~-------~--~----~
> You received this message because you are subscribed to the Google
> Groups "Robotlegs AS3" group.
> To post to this group, send email to robo...@googlegroups.com
> To unsubscribe from this group, send email to robotlegs+...@googlegroups.com
> For more options, visit this group at http://groups.google.com/group/robotlegs?hl=en
> -~----------~----~----~----~------~----~------~--~---
>

Till Schneidereit

unread,
Nov 18, 2009, 11:02:52 AM11/18/09
to robo...@googlegroups.com
Hey Shaun,

great feedback, thanks a lot!

On Wed, Nov 18, 2009 at 00:26, Shaun Smith <dar...@gmail.com> wrote:
>
> On 16 Nov 2009, at 1:46 PM, Till Schneidereit wrote:
>
>> function configureInjector(injector : IInjector):void
>> {
>>  // ...
>>
>>  var leftLegRule : InjectionConfig = injector.mapClass(RobotLeg,
>> RobotLeg, 'left');
>>  var rightLegRule : InjectionConfig = injector.mapClass(RobotLeg,
>> RobotLeg, 'right');
>>
>>  var leftLegContext : IInjector =
>> injector.createChildContext(leftLegRule);
>>  leftLegContext.mapClass(RobotFoot, LeftFoot);
>>
>>  var rightLegContext : IInjector =
>> injector.createChildContext(rightLegRule);
>>  rightLegContext.mapClass(RobotFoot, RightFoot);
>>
>>  // ...
>> }
>
> Cool, I think the word "context" was throwing me off a bit - I've
> worked up such a disliking towards the word that it makes my vision go
> blurry (I'll save that for post-v1.0 discussions though!).
>
> Could it not be written as:
>
> var leftLegInjector : IInjector =
> injector.createChildInjector(leftLegRule);
>
> I just think createChildContext() would be confusing for RL users (due
> to bad naming on my part, but still).

Absolutely, "context" is pretty loaded in the, erm, context of RL.

>
> Also, what if it was injector.getChildInjector(Rule)? "Get" instead of
> "create", as in: it returns the same object if passed the same rule.
> Thinking aloud:
>
> var childInjector : IInjector = injector.getChild(Rule);
>
> or:
>
> var childInjector : IInjector = injector.forRule(Rule);

I like "getChildInjector". The other two carry too little meaning for
my taste, compared to the "map*" methods. Also, it's not like one
would write that all the time, so length doesn't matter that much.

>
> It might not be worth the effort trying to get the RL adapter to
> support this directly. Besides, I think that the people who'd make use
> of this would already be dealing with their DI container/injector of
> choice directly (rather than the RL adapter). Speaking of which: we
> should probably add getAdaptee() to IInjector... maybe.

My thoughts exactly. I've tentatively reached the conclusion that
adding "mapRule" to the interface was an error, too - but that train's
left the station. Going forward, I think the message should be to do
all injections in commands (or where ever) and inject the injector
itself with the desired/ needed type. That way, we only ever have to
support the functionality used by the RL core itself in the adapters.


I'll now write documentation for all 1.0 features in SwiftSuspenders
and then release 1.0. After that, I'll give getChildInjector a try and
release a 1.1 pretty soon if everything works out.


thanks again,
till
Reply all
Reply to author
Forward
0 new messages