Injection error in command

67 views
Skip to first unread message

Jesse Warden

unread,
Nov 15, 2009, 7:36:49 PM11/15/09
to robo...@googlegroups.com
Injector is missing a rule to handle injection into target (it's thrown for the connectService)

Any clue what that means?  It claims it can't inject a service into a Command, but other things seem to be working.  Confused.

Joel Hooks

unread,
Nov 15, 2009, 7:39:54 PM11/15/09
to robo...@googlegroups.com
ConnectService isn't mapped. That's what the error means anyway.

Shaun Smith

unread,
Nov 15, 2009, 7:41:21 PM11/15/09
to robo...@googlegroups.com
Have you set up an injection rule for it? Something like:

injector.mapSingleton(ConnectService);

Jesse Warden

unread,
Nov 15, 2009, 7:41:29 PM11/15/09
to robo...@googlegroups.com
...er, what does that mean?

Jesse Warden

unread,
Nov 15, 2009, 7:41:54 PM11/15/09
to robo...@googlegroups.com
..no... I thought I all I needed to do was use the [Inject] tag?

Joel Hooks

unread,
Nov 15, 2009, 7:42:54 PM11/15/09
to robo...@googlegroups.com
RL doesn't have magic pixies living in the SWC ;)



Jesse Warden

unread,
Nov 15, 2009, 7:44:21 PM11/15/09
to robo...@googlegroups.com
...I thought all the [Inject] tag did was instantiate it on the fly vs. me creating the instance manually?

Stray

unread,
Nov 15, 2009, 7:44:54 PM11/15/09
to robo...@googlegroups.com
Dammit.

But you did include the intelligent hamsters didn't you?

Shaun Smith

unread,
Nov 15, 2009, 7:45:06 PM11/15/09
to robo...@googlegroups.com
You need to tell the injector how to deal with that injection somewhere. Check out the IInjector interface for your options.

Jesse Warden

unread,
Nov 15, 2009, 7:45:54 PM11/15/09
to robo...@googlegroups.com
Jesus H... so to use the [Inject] tag, I have to utilize one of those injector methods for it in the Context class?

Shaun Smith

unread,
Nov 15, 2009, 7:47:35 PM11/15/09
to robo...@googlegroups.com
Yup, how else would we know what to inject?

Shaun Smith

unread,
Nov 15, 2009, 7:50:40 PM11/15/09
to robo...@googlegroups.com
No, it marks a property for injection. That could mean instantiating a new instance to inject, or it could mean re-using an existing one.

Joel Hooks

unread,
Nov 15, 2009, 7:51:03 PM11/15/09
to robo...@googlegroups.com
Jesus H... so to use the [Inject] tag, I have to utilize one of those injector methods for it in the Context class?

You can map the injector anyplace where the IInjector is available (by default the context or a command)

Stray

unread,
Nov 15, 2009, 7:56:18 PM11/15/09
to robo...@googlegroups.com
Speaking of mapping an injection in a command - can we overwrite / replace an injection on the fly? As in - can I effectively (lazily - in the lazy coder sense) create a state machine via remapping the injection in a command?

Shaun Smith

unread,
Nov 15, 2009, 7:58:25 PM11/15/09
to robo...@googlegroups.com
It would be naughty, but yes, that should be possible.. Although DI containers don't generally like that kind of thing. But I don't think SwiftSuspenders complains. Till?

Shaun Smith

unread,
Nov 15, 2009, 8:01:19 PM11/15/09
to robo...@googlegroups.com
On 16 Nov 2009, at 2:51 AM, Joel Hooks wrote:

Jesus H... so to use the [Inject] tag, I have to utilize one of those injector methods for it in the Context class?

You can map the injector anyplace where the IInjector is available (by default the context or a command)

And you can make it available anywhere else by simply depending on it [Inject]. Though I'm pretty sure mapping injections in a Mediator would get you in trouble with your future self.

Joel Hooks

unread,
Nov 15, 2009, 8:01:24 PM11/15/09
to robo...@googlegroups.com
There is unmap() on the injector. Looking at the SwiftSuspenders Injector, it simply replaces the value in the dictionary with the new rule. So the answer is "yes" you can change mapping on the fly.



Stray

unread,
Nov 15, 2009, 8:08:01 PM11/15/09
to robo...@googlegroups.com
Thanks Joel - not sure I'll definitely use it that way but it opens up possibilities...

Why do you say it would be naughty Shaun?

If the state pattern is mostly about using different concrete classes of the same interface to implement logic instead of a bunch of 'if / else' statements... why is it naughty to achieve the same thing via switching the injector mapping instead?

It may well be naughty - but I'm intrigued as to why you think it is... can't state/command breed? (You may know this path leads to pain... !)

Joel Hooks

unread,
Nov 15, 2009, 8:09:49 PM11/15/09
to robo...@googlegroups.com
If I wanted a state machine I'd use the StateMachine utility. Best of both worlds :>

Stray

unread,
Nov 15, 2009, 8:10:32 PM11/15/09
to robo...@googlegroups.com
Good answer :)

Jesse Warden

unread,
Nov 15, 2009, 8:15:42 PM11/15/09
to robo...@googlegroups.com
I really don't understand the value of DI, then.  I thought it was so I have to write less code.  The way I'm reading this:

1. The Context has knowledge of how a Service is created.  It shouldn't have to have all of this knowledge.  To say it another way, why must it know about the boiler-plate construction of a class?

2. Not using Inject, I could just write 1 line of code instantiating my instance, and going on about my day.

I get mapping Commands & Mediator's using DI.  I don't get mapping Services, DisplayObject instances for the Mediator, or anything else at all... makes no sense, I see no value.  Seems totally un-encapsulated.

I've seen some implementations of Prana and SpringAS that basically allow you to swap your Interface injections with mock-implementations for either testing with fake data while your back-end is being developed.  But I'm not doing that here.  It seems like this DI stuff is being used just to use it.  I don't get it...

Stray

unread,
Nov 15, 2009, 8:28:58 PM11/15/09
to robo...@googlegroups.com
How about...

1) If I have a bunch of classes which all create the same class within them, I only have to map it once (in the context). In the composed classes I just inject it.
2) If I want to use a local version of a service, or a test version with hard-coded dummy data, I only have to change the context mapping...

So far - and I've actually used it on deliverables for clients - I've found it to be cleaner. It's not necessarily quicker to type because I'm less fluent with it, but given that probably 90% of my time is spent in 'wtf?' and only 10% typing in code I think is going to work until I hit the 'wtf?' then I really appreciate the way it's making me think, as well as how easy it is to have a test-context, a local-context and so on... 

But - if you don't dig it, don't use it!

The context doesn't have knowledge about How the service is created by the way - just which service you want to map to the injection. Where you create the service is up to you - context injector mappings just say "When someone asks for an IFruitService give them PineappleService".

Something I'm digging is how easy it is to keep track of which classes I've written are actually working and which are just placeholders to get a framework hooked up.

Shaun Smith

unread,
Nov 15, 2009, 8:32:50 PM11/15/09
to robo...@googlegroups.com
On 16 Nov 2009, at 3:08 AM, Stray wrote:

Thanks Joel - not sure I'll definitely use it that way but it opens up possibilities...

Why do you say it would be naughty Shaun?

Well, the whole dynamic DI container thing is considered "too much rope" by some very strict folks. They would say that dynamic containers lead to unpredictable systems. They might be right. Depends on your belief system ;)

If the state pattern is mostly about using different concrete classes of the same interface to implement logic instead of a bunch of 'if / else' statements... why is it naughty to achieve the same thing via switching the injector mapping instead?

Dynamic state is harder to track than static state. It's also time based. Not that the state in RL is static as it is.. but it could (almost) be - you could set up a DI container before even instantiating your context, pass it through (wrapped in the appropriate adapter so that RL can use it), and make sure not to do any mapping type stuff in your actors. We still need to flip-flop the view components in the MediatorMap, and the events in the CommandMap though - so a completely sealed container would never work with RL. 

It may well be naughty - but I'm intrigued as to why you think it is... can't state/command breed? (You may know this path leads to pain... !)

My intuition tells me that stable systems need to be static (deterministic). But during design/dev/proto phase this would be too huge a constraint.. well, for me anyway.

Jesse Warden

unread,
Nov 15, 2009, 8:34:31 PM11/15/09
to robo...@googlegroups.com
1. That sounds like a great optimization technique... AFTER you're done, not ahead of time.  In small projects sure... but seriously?  I just don't see my brain cells being used to "think about which class I can possibly inject to save a few lines of code".

2. Right, but no one does that.  They say they do, but they don't.  I agree with having it for those who will use it, but it's like 10% of the market.

Another problem I didn't mention is the exceptions disappear... the throws are getting swallowed by something in 10.0.x, and I don't see 'em unless I debug.

Till Schneidereit

unread,
Nov 15, 2009, 8:34:34 PM11/15/09
to robo...@googlegroups.com
On Mon, Nov 16, 2009 at 02:15, Jesse Warden <jesse....@gmail.com> wrote:
> I really don't understand the value of DI, then.  I thought it was so I have
> to write less code.  The way I'm reading this:
> 1. The Context has knowledge of how a Service is created.  It shouldn't have
> to have all of this knowledge.  To say it another way, why must it know
> about the boiler-plate construction of a class?

Something has to know about it, so what do you think would be a better
place for that? And as Stray said: Your context only does the mapping,
it doesn't have to do the creating.

> 2. Not using Inject, I could just write 1 line of code instantiating my
> instance, and going on about my day.

How do you get access to a singleton instance of a shared service in
your command without DI or some boiler-plate?
If your answer is "by using MyService.getInstance", then: How do you
get access to a singleton instance of a shared service typed as an
interface? If you don't need that, I guess you don't need DI here.

> I get mapping Commands & Mediator's using DI.  I don't get mapping Services,
> DisplayObject instances for the Mediator, or anything else at all... makes
> no sense, I see no value.  Seems totally un-encapsulated.

In mediators, it's really the only way to set the mediated view with
its' concrete class (or as an interface you want it to be injected as)
without forcing you to cast it.

> I've seen some implementations of Prana and SpringAS that basically allow
> you to swap your Interface injections with mock-implementations for either
> testing with fake data while your back-end is being developed.  But I'm not
> doing that here.  It seems like this DI stuff is being used just to use it.

I'm doing exactly that quite often and I love that I can switch
between implementations by changing just one line in my injector
mappings without having to do a lot of plumbing.
And that's exactly the tremendous value of DI: It lets you built very
complex interrelated object trees that share exactly the amount of
knowledge they have to without having to write lots of boiler-plate
code for it.


Ok, going to bed now.
cheers,
till

Joel Hooks

unread,
Nov 15, 2009, 8:36:12 PM11/15/09
to robo...@googlegroups.com
 It seems like this DI stuff is being used just to use it.  I don't get it...

How would you get the service into the command otherwise? Service Locator? Globals/Statics? Create a new instance every time?

This particular method of automated dependency injection allows one to define the mapping up front (in code) and then simply declare the public properties with [Inject] and have it placed wherever you need it.

The Context has knowledge of how a Service is created.  It shouldn't have to have all of this knowledge. 

It has nothing to do with the Context. The startup() method is just a convenient place to bootstrap. Outside of trivial examples I would always do this in a stateless command. Even in the startup method, there is no knowledge of how a Service is instantiated (ie "new" is not used)

Not using Inject, I could just write 1 line of code instantiating my instance, and going on about my day.

True enough. Unless you needed it in 2 commands, now it is two lines of code and perhaps a static method to enforce the singleton (unless you like multiple services). It also depends on your feelings about clean code and testability. Should bootstrapping and dependency configuration be provided for classes, or should they manage their own dependency object instantiation? Does it make more sense to configure an application up front, or litter the code with configuration/instantiation? To me it would be a matter of how much value you put into clean code vs "fuck it. git er done." I favor the former where possible, and automated DI is an excellent tool for writing clean code.

Jesse Warden

unread,
Nov 15, 2009, 8:40:34 PM11/15/09
to robo...@googlegroups.com
1. Yeah, but now the class is in 2 places vs. 1.  How does the Context even "know" it's going to be used?  Seems way too coupled.

2. You're right, I don't need an interface, so Singleton.instance it is.

I think the problem here regarding Mediator's is when you all say "Mediator", I hear "Presenter".  So, what I always did in PureMVC was:

new MyMediator(myViewInstance)

And the constructor was:

public class MyMediator(myView:MyView):void
{
   super(NAME);
   this.myView = myView;
}

A Mediator never uses any other View, so this concrete implementation is fine.  Those who try to give me some interface View in the constructor for testing bs are space cadets.  So, I'm not casting it; I get a reference to my View, which I know what it'll be, and go on about my day.

...regarding that you use it... oh.... *sigh* Majority of code I see is never even close to that testable, let alone having enough developers capable enough to go down that road, and even if they did, you'd have a hard time selling on the value of writing the same class twice.

Stray

unread,
Nov 15, 2009, 8:44:21 PM11/15/09
to robo...@googlegroups.com
On 16 Nov 2009, at 01:34, Jesse Warden wrote:

1. That sounds like a great optimization technique... AFTER you're done, not ahead of time.  In small projects sure... but seriously?  I just don't see my brain cells being used to "think about which class I can possibly inject to save a few lines of code".

It's not hard. "Do I need this thing in more than one place?" "Do I want a singleton-like one-time-only version of this?" "Do I want to be able to switch in and out concrete implementations of this - for testing or for versioning?" Answer to any of these = yes, use the Inject...  (it's not a complete list but it's mostly what I'm working from). And of course I don't know at the start what all the injections will be... but I add them as I need them.


2. Right, but no one does that.  They say they do, but they don't.  I agree with having it for those who will use it, but it's like 10% of the market.

I do. It's how I always start... and mostly how I develop. Even when the service is up and running, I cache server data to text files so that I can still work even when my internet connection is failing (happens a lot where I live). It also means that I always hand the client an extra version of the software which runs from local data so that they can use it in a presentation without an internet connection.

Jesse Warden

unread,
Nov 15, 2009, 8:48:34 PM11/15/09
to robo...@googlegroups.com
Yes, ServiceLocator, what is wrong with that?

If I need a class, yes, create a new instance.  If I don't, keep it around on purpose vs. re-create each time (after the fact, since very little CPU to create & use a Service on the fly vs. View).

Again, you're ignoring the fact that the Context has knowledge of the inner workings of a class it shouldn't; doesn't seem encapsulated at all.

What? No knowledge?  Bullshit dude, mapSingleton implies that "The Context is telling the world that you must make this a single instance".  It doesn't use "new" but it sure dictates how it's done.

2 lines of code?  Same using DI; I still have to write the Inject tag in the class, AND 1 line of code in a totally different class.  Yes, major fan of a class taking care of it's own dependencies, with the exclusion of ServiceLocator; that's always worked great for me.  I've never had the opportunity to do what Till suggested since it's easy to comment out 30 lines of code if I needed to go back to mock factories vs. 1 in a Context.  It sounds clever, but dude... very few people do that shit (make mock layers).

I like you Joel, but I'd appreciate it if you re-wrote that paragraph; just say it a different way.  You've been helpful in the past in explaining these things succinctly, so just say the same thing, just say it a different way and I might get it.  Reading it now, I still don't get the value.

Stray

unread,
Nov 15, 2009, 8:52:55 PM11/15/09
to robo...@googlegroups.com
On 16 Nov 2009, at 01:40, Jesse Warden wrote:

1. Yeah, but now the class is in 2 places vs. 1.  How does the Context even "know" it's going to be used?  Seems way too coupled.

Er... but if two areas of application functionality both need to know about - in my example - the user via UserData ... what's the possibility of doing it without coupling?

What's nice though, is that I can TEST (and - holy crap - I actually DO test it because I don't like the 3am frantic bug hunting stuff) those classes that need UserData by injecting a PhonyUserData object that has known properties and then write asserts for my unit test based on that.


2. You're right, I don't need an interface, so Singleton.instance it is.

I think the problem here regarding Mediator's is when you all say "Mediator", I hear "Presenter".  So, what I always did in PureMVC was:

new MyMediator(myViewInstance)

And the constructor was:

public class MyMediator(myView:MyView):void
{
   super(NAME);
   this.myView = myView;
}

A Mediator never uses any other View, so this concrete implementation is fine.  Those who try to give me some interface View in the constructor for testing bs are space cadets.  So, I'm not casting it; I get a reference to my View, which I know what it'll be, and go on about my day.

but you're injecting there - you're passing it via the constructor. So you must have created the myView object prior to that.. so RL is a ton less boilerplate.


...regarding that you use it... oh.... *sigh* Majority of code I see is never even close to that testable, let alone having enough developers capable enough to go down that road, and even if they did, you'd have a hard time selling on the value of writing the same class twice.


As above, yes, it's a hard sell initially, but writing the same class twice (one with known dummy data) is a hell of a lot less time consuming than chasing down a bug later. I only work with coders who unit test. And believe me, if you are going to unit test (and why wouldn't you - it's like not brushing your teeth - seems quicker now but it's gonna be pain in the long run... ) then RL is providing a faster, easier way of doing that.

Jesse Warden

unread,
Nov 15, 2009, 8:59:53 PM11/15/09
to robo...@googlegroups.com
Yes, but you imply you already knew you were going to.  I get what you're saying, but I fail to see how that works with Enterprise code bases.  Those grow, they aren't architected from the start.  I'm saying it's impossible to know, yet you're saying you can know.

Secondly, you've clearly stated you're using unit testing and TDD.  What if you're not doing any of those things?  Assuming so, do any of my arguments still seem sound?

Stray

unread,
Nov 15, 2009, 9:01:53 PM11/15/09
to robo...@googlegroups.com
Jesse, You seem to be thinking of the context as some sort of alien invader :)

The context is just a place to tell RL how you'd like some of the mappings to be handled - yes, you can map a singleton there, but does that give the context any more knowledge than a class that knows it has to use .getInstance() instead of new() ?  I don't think it does... so actually, there are fewer classes that know that your singleton is a singleton - everybody except the class that does the mapping (probably the context, but as Joel said, in any kind of meaty app probably a startup command) has no clue that it's a singleton at all.

To me, that looks like less exposure, not more. Less coupling - not more...

If, for some reason, later your app grew and you wanted to not use the singleton approach any more, you could change that one line where you mapped it, and wham - new structure.  Fishing getInstance() out of a bunch of classes would be more annoying.

Josh McDonald

unread,
Nov 15, 2009, 9:03:47 PM11/15/09
to robo...@googlegroups.com
This is exactly what the InjectorContext I'm working on for SP is for. I find it pretty funny that it's a solution to the injection problem known as "robot legs", and the catalyst for getting me off my arse to write it is Robot Legs (the framework).

I guess I'm easily amused ;-)

Anyway, feel free to pick my brain / pinch my ideas for SS.

-Josh

2009/11/16 Joel Hooks <joel...@gmail.com>



--
"Therefore, send not to know For whom the bell tolls. It tolls for thee."

Josh 'G-Funk' McDonald
  -  jo...@joshmcdonald.info
  -  http://twitter.com/sophistifunk
  -  http://flex.joshmcdonald.info/

Stray

unread,
Nov 15, 2009, 9:07:09 PM11/15/09
to robo...@googlegroups.com
On 16 Nov 2009, at 01:59, Jesse Warden wrote:

Yes, but you imply you already knew you were going to.  I get what you're saying, but I fail to see how that works with Enterprise code bases.  Those grow, they aren't architected from the start.  I'm saying it's impossible to know, yet you're saying you can know.

I'm working on a complete rebuild of a well used, well developed 2 year old complicated enterprise Air Application.  But still... I'm not saying you do know - I'm saying that at least you can answer the little questions "Will I need my user data in more than one functional area?". If you can't answer that kind of question then you need to do a hell of a lot more talking to the client and working out what the app is actually going to do before you even think about opening a code editor...

Beyond that, yes - change is the only constant. Refactoring is at least half of what I do - actually the most enjoyable half. Refactor to an injection as the need becomes apparent.


Secondly, you've clearly stated you're using unit testing and TDD.  What if you're not doing any of those things?  Assuming so, do any of my arguments still seem sound?

Well, then I guess one day you're going to need to visit the dentist ;)

If you're building enterprise apps and not doing any unit testing or TDD then I can only surmise that you're a fan of stress / pain, or that the client has bottomless pockets. To be honest I think building enterprise software without ANY unit testing or TDD is tantamount to professional neglect... but I'm a kill joy.

Stray

unread,
Nov 15, 2009, 9:14:24 PM11/15/09
to robo...@googlegroups.com
Thanks Shaun,

thinking about it, I guess the dynamic part of the state - for an example let's imagine a video lesson which can be playing / not playing - should be inside the API and not a case of exposing different implementations of the interface API directly?

I still don't follow the static / dynamic tracking difference though - as far as the class using an interface API is concerned as long as it looks, talks and walks like IDuck it's an IDuck surely? Or do you mean for testing / debugging?

I was just thinking that you could have very simple command that effectively remapped the state in a few different areas by changing the injector mappings.

That said - I guess an API switch is more polite :)

I'm gonna check out the StateMachine utility anyway. I think the possibilities of using remapping during the dev phases, or for testing, are really interesting though.

Shaun Smith

unread,
Nov 15, 2009, 9:21:51 PM11/15/09
to robo...@googlegroups.com
What you're saying is that my devious plan worked: here you are, solving the problem ;-) If you solve it in under 11k I'm switching teams. If I understand you correctly, with the new SP I'd be able to drop the whole stupid RL Context thing, but still use our: MediatorMap, CommandMap, ViewMap etc for "assisted" DI? Or would SP provide a mechanism that's cleaner and simpler that what we've currently got for that kind of thing?

On 16 Nov 2009, at 4:03 AM, Josh McDonald wrote:

This is exactly what the InjectorContext I'm working on for SP is for. I find it pretty funny that it's a solution to the injection problem known as "robot legs", and the catalyst for getting me off my arse to write it is Robot Legs (the framework).

I guess I'm easily amused ;-)

Well, it's less amusing when you consider that you named this framework. Or more amusing, I'm not sure.

Shaun Smith

unread,
Nov 15, 2009, 9:40:21 PM11/15/09
to robo...@googlegroups.com
On 16 Nov 2009, at 4:14 AM, Stray wrote:

I still don't follow the static / dynamic tracking difference though - as far as the class using an interface API is concerned as long as it looks, talks and walks like IDuck it's an IDuck surely? Or do you mean for testing / debugging?

Sure, it's an IDuck. The problem is that your system is not deterministic - it might, for example, get wired up differently based on some timing issue in some configuration method that gets triggered asynchronously from some funny place based on some funny condition.

Anyway, I'm not one of those strict folks - I'm fine with dynamic configuration. If I wanted to design pure systems I'd use a proper OO language or a proper functional one. ActionScript is neither of those. We *have* to make compromises to be productive on this platform. It's the size and cost of those compromises that I'm concerned with.

I was just thinking that you could have very simple command that effectively remapped the state in a few different areas by changing the injector mappings.

Indeed. That's exactly what the CommandMap and MediatorMap do. A single command or class that changes a bunch of state/configuration though.. that sounds like a lot of knowledge coupling.

That said - I guess an API switch is more polite :)

Sorry, I don't follow.. perhaps it's time for my nap.

I think the possibilities of using remapping during the dev phases, or for testing, are really interesting though.

Yeh, and with conditional compilation it's pretty easy to set up.

Josh McDonald

unread,
Nov 15, 2009, 11:09:23 PM11/15/09
to robo...@googlegroups.com
There's two usage scenarios for InjectorContext:

1) You simply want to change the rules ahead of time for various usages. This is the solution to the original "robot legs" problem (keep in mind the DSL is all still a little up in the air):

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 { ... }

function configureInjector(context:InjectorContext):void
{
  // ...

  context.whenAskedFor(RobotLeg).named("left").useClass(RobotLeg);
  context.whenAskedFor(RobotLeg).named("right").useClass(RobotLeg);

  var leftLegContext:InjectorContext = context.createChildContext();
  leftLegContext.whenAskedFor(RobotFoot).useClass(LeftFoot);

  var rightLegContext:InjectorContext = context.createChildContext();
  rightLegContext.whenAskedFor(RobotFoot).useClass(RightFoot);

  context.whenPopulating(RobotLeg).named("left").useContext(leftLegContext);
  context.whenPopulating(RobotLeg).named("right").useContext(rightLegContext);
 
  // ...
}

2) Some framework code in RL (the fw), would be building a mediator / controller, and create a temporary child InjectorContext, set up the rules required, and then make a request through that temporary context to create and inject the mediator / controller interface. That way you can do this:

// App code:

function configureRobotLegs(context:RobotLegsContext):void
{
  // ..
  context.forViewClass(PurpleMonkeyDishwasherView).useMediator(PupleMonkeyDishwasherMediator);
  // ..
}

class PupleMonkeyDishwasherMediator
{
  [Inject(name="viewComponent")]
  var view:PurpleMonkeyDishwasherView;
}

// Framework code:

class SomeCoreClass
{
  [Inject]
  var parentContext:InjectorContext;

  function mediatorKey(viewClass:Class):String
  {
    return "mediator for " + getQualifiedClassName(viewClass);
  }

  function mapMediator(viewClass:Class, mediatorClass:Class):void
  {
    parentContext.whenAskedForAnythingNamed(mediatorKey(viewClass)).useClass(mediatorClass);
  }

  function createViewMediator(viewComponent:UIComponent):*
  {
    var context:InjectorContext = parentContext.createChildContext();
    context.whenAskedForAnythingNamed("viewComponent").useValue(viewComponent);
    return context.forName(mediatorKey(viewClass)).getInstance();
  }
}

Anyway, that's where my train of thought is going. Any early feedback before I do the work is always appreciated!

-Josh

2009/11/16 Shaun Smith <dar...@gmail.com>

Shaun Smith

unread,
Nov 16, 2009, 12:20:23 AM11/16/09
to robo...@googlegroups.com
[Edit: Upon review I've determined that I come across sounding like a bit of a dick in this post. Please don't be offended - I'm just really sleepy and I don't feel like editing it and taming it down.. or I'll never get it sent.]

Component design often requires tight coupling between a set of classes, and it's fine - the classes were designed to work together, they can all ref each other, "new" each other up (to a certain extent), and it's OK. You end up with a tightly coupled unit (changes in one class require changes in another class), but the "damage" is localised - isolated to that small, self contained set of classes. Unfortunately, this seems to be how many developers actually wire their entire applications together, and it's a VERY bad idea for enterprise development.

Designing enterprise (read: flexible, rapidly changing) systems requires a good grasp of object oriented programming. If you aren't programming to interfaces, and you *are* new'ing up objects that aren't leaf nodes (outside of factories or DI containers) manually, the chances are slim-to-none that you're following the core principles of good object oriented design: DRY, Law of Demeter, Liskov Substitution, Single Responsibility, Design by Contract, Open/Closed etc.

http://en.wikipedia.org/wiki/Liskov_substitution_principle
These principles exist because they help us to design systems that are simpler and less fragile than the alternatives. So that we can move quickly and confidently. So that we can refactor without fear of breaking the system. So that we can build things that stay stable as requirements evolve (and they *always* evolve).

Dependency Injection helps us follow these principles with less effort than would be required to do so manually. It has the drawback of obfuscating code somewhat for developers who don't follow these principles and are used to digging deeply into objects and passing things around all over the show. I just cannot imagine why anyone would willingly put themselves through the pain that that causes though. Not after they've built at least one moderately complex system that has required continued development and maintenance.

Anyhoo, regardless of whether or not you buy into ANY of that, using DI reduces the amount of code you need to write because the configuration rules can be reused across a given scope, instead of manually spreading that instantiation and dependency knowledge (and code) across your codebase. Every time you write "new" you are writing boilerplate code that couples your class directly to another class. If the class that you are new'ing up has it's own dependencies (constructor arguments for example) then you are coupling yourself exponentially. If other classes also depend on that thing you need to spread the knowledge of "how" to instantiate that class all over your codebase. Do you not see how this violates DRY? Or how boring it is? How is this simpler than setting rules for your scope and explicitly declaring your dependencies?

The irony is that people who refuse to actually learn object oriented programming tend to cite pragmatism as their reason for doing so. In reality, intense study of the aforementioned principles (amongst many others) is required to build high quality systems in acceptable timeframes. It's ALL about building things fast AND well. To ignore this stuff is to be the opposite of pragmatic.

When someone says that it's very unlikely that they'd re-use any of their code across apps, then the changes are high-to-absolute that they are writing a lot of boring code over and over again. Sorry, but that's just not how I want to spend my time.

I highly recommend that anyone interested in this stuff sets aside a couple of hours to read through Misko Hevery's work:


Please don't be put off by the word "Testable". Testable code is just code that is well written. You don't have to write unit tests, but your code will be better if you write classes that are easily testable. Testability is a welcome side effect of clean code.

This is not the stuff of hardcore programmers, architecture astronauts, or any other such derogatory term for people who take their craft seriously; this is merely object oriented programming in a statically typed language. Functional programming and pure oo.. that's another story altogether :)

Short version: DI reduces coupling and boilerplate, but can also reduce clarity for developers who aren't familiar with OOP. Well, not just for those guys. The indirection  reduces clarity regardless.

Ok, that's it! I'm off to bed. Ah, and this looks handy:


I don't know why the word "Advanced" is in the title there - that stuff is pretty core to programming oop. I'm a total noob, and I know that crap.

Ok, really, I'm out. Apologies again for the abrasive tone. And I hope this doesn't kill the debate - we're all learning here.. just throwing my thoughts out there. And if there's one thing I know about me and my thoughts: given enough time I'm always wrong :)

Shaun Smith

unread,
Nov 16, 2009, 12:31:49 AM11/16/09
to robo...@googlegroups.com
Damnit, that hurt my tired head. I'll have a sleep and then look at this again later.

Richard Lord

unread,
Nov 16, 2009, 3:55:14 AM11/16/09
to Robotlegs AS3
Hi Jesse

As I see it, the value of DI is to decouple my classes. If you create
an instance inside a class, the class is tightly coupled to the type
of that instance. If you inject into the class, particularly if you
define the injection based on an interface, the class is coupled only
to the interface it requires, not to the implementation being
injected.

This enables the swapping of the implementation, which in turn makes
your class more reusable and more testable and makes refactoring your
project easier.

Now, with that comes a requirement for discipline. In large projects I
try not to go overboard with the number of injection rules in the
context. Some DI is managed through the DI container and hence
configured in the context and requested via the [Inject] metadata. But
that doesn't stop me also doing manual DI by passing variables into
constructors and methods and passing payloads in events. It all
depends on the situation at hand. However, I do question myself quite
sternly whenever I'm tempted to use the word "new", because when I use
that word I'm fixing the implementation inside the code.

I can imagine the discipline required would not sit well with many of
the teams you consult with.

Richard

On Nov 16, 1:15 am, Jesse Warden <jesse.war...@gmail.com> wrote:
> I really don't understand the value of DI, then.  I thought it was so I have
> to write less code.  The way I'm reading this:
>
> 1. The Context has knowledge of how a Service is created.  It shouldn't have
> to have all of this knowledge.  To say it another way, why must it know
> about the boiler-plate construction of a class?
>
> 2. Not using Inject, I could just write 1 line of code instantiating my
> instance, and going on about my day.
>
> I get mapping Commands & Mediator's using DI.  I don't get mapping Services,
> DisplayObject instances for the Mediator, or anything else at all... makes
> no sense, I see no value.  Seems totally un-encapsulated.
>
> I've seen some implementations of Prana and SpringAS that basically allow
> you to swap your Interface injections with mock-implementations for either
> testing with fake data while your back-end is being developed.  But I'm not
> doing that here.  It seems like this DI stuff is being used just to use it.
>  I don't get it...
>
> On Sun, Nov 15, 2009 at 7:47 PM, Shaun Smith <dars...@gmail.com> wrote:
> > Yup, how else would we know what to inject?
>
> > On 16 Nov 2009, at 2:45 AM, Jesse Warden wrote:
>
> > Jesus H... so to use the [Inject] tag, I have to utilize one of those
> > injector methods for it in the Context class?
>
> > On Sun, Nov 15, 2009 at 7:45 PM, Shaun Smith <dars...@gmail.com> wrote:
>
> >> You need to tell the injector how to deal with that injection somewhere.
> >> Check out the IInjector interface for your options.
>
> >> On 16 Nov 2009, at 2:41 AM, Jesse Warden wrote:
>
> >> ..no... I thought I all I needed to do was use the [Inject] tag?
>

Richard Lord

unread,
Nov 16, 2009, 5:29:38 AM11/16/09
to Robotlegs AS3
Doh! I didn't notice there were two pages of messages, so that post
was in response to something Jesse wrote hours ago on page one of this
thread. Hopefully, it's still relevant.

Stray

unread,
Nov 16, 2009, 6:52:38 PM11/16/09
to robo...@googlegroups.com

On 16 Nov 2009, at 02:40, Shaun Smith wrote:
>
>> That said - I guess an API switch is more polite :)
>
> Sorry, I don't follow.. perhaps it's time for my nap.
>

Ah... I just meant that the object itself should probably have an API
function that can act as a switch as in "setStatusTo()" or whatever,
rather than me effectively reaching inside it by remapping the
injection...

Or - thinking more - I guess the various objects can each listen
individually and do their own switching triggered by the same event.

Which I guess is what you were suggesting - to avoid one command
having knowledge of which various parts of the system all need to be
changed.

Thanks for wrestling this one with me!

Tyler Wright

unread,
Nov 17, 2009, 1:12:12 PM11/17/09
to robo...@googlegroups.com
Sorry, just catching up, and I know this is not the list to share but here goes.

I'm with Jesse on unit testing. I've never really appreciated the value of unit tests in application development, especially when you're doing a lot of refactoring in a large system. Maintaining unit tests in an enterprise system means that there are twice as many classes to update with every refactor. Because of type-checking, debugging and all the other features of Flex Builder I've never had a problem finding and fixing bugs quickly. I think a lot of developers could learn better debugging techniques in place of building and maintaining a test suite for a GUI-strong enterprise application.

Proper architecture, separation of responsibilities and encapsulation are essential to minimizing the scope of your changes, and as a result your testing and bugs. I've never been up at 3am fixing bugs I wished were found by unit tests, which I would have to write and update with each change in the system. A portion of all the time I save by not writing unit tests is applied to testing changes in the application manually (which I understand is still an essential exercise even with a test suite). Sometimes I hear someone excitedly share that their tests found a bug and I just want to push their chair to the side and run the application in debug mode. "Look, see, I found the bug just as easily without all of those hours writing tests".

Testing has it's place to be sure. Building reusable libraries for release is different and unit tests are justifiable. They're a value-add to the project and guarantee stability and peace of mind. TDD can help you design your API well and forces you to use your library. Wherever you release documentation of code (such as an OS project) unit testing would be appropriate. But if I ever see a unit test targeting an application-specific MXML component I'd delete it promptly.

I'll admit I may be ignorant, maybe I haven't given testing a long enough trial. Joel said that the modularization of RobotLegs isn't for unit tests, but that they're a nice bi-product. I can dig that. I just wanted to back up Jesse on this one because I feel the same way (and since we've been opposite on many other discussions ;)

I think sometimes to make things easier for the 1% we complicate the 99% - to me unit testing often falls into this category. 

Tyler

Stray

unread,
Nov 17, 2009, 1:58:54 PM11/17/09
to robo...@googlegroups.com
This is interesting - it got me wondering why I end up with so much crap to fix when I don't write explicit tests for TDD. I don't always run asunit based tests - I have a mini-test-suite called "QuickAssert" which I often just use in a "runTests" function on a class for rough-and-ready testing. But if I don't write the tests something always, always screws up, and takes me longer to fix than writing the tests. Which may well be as much about me as about my projects.

You're right: unit testing can be a pain. However, the right automation (textmate, sprouts etc) can reduce the amount of create-new-file and boilerplate you're doing to minimally more than writing the class being tested. The unit tests only need changing if the refactor has changed the API. If the API has changed then you've got other classes to refactor anyway... (otherwise why is this refactored function API when it could be private?) If the refactor hasn't touched the API then the unit test just confirms that everything is as it was. Phew.

We used to use manual testing - and still do some of that - but found that getting good manual testers was as hard as getting good developers, and for me it's quicker to write and repeat unit tests than to manually test a whole list. But, honestly - I don't think it takes me any longer to add the tests to the unit test class when I add or change functionality than it used to take to add or change them in the manual tests document.

I'm glad you've never been up at 3am fixing bugs - if I counted up every hour of sleep I've lost on the night before a project releases I'd just sob I think!

Maybe I just need unit testing because I get interrupted so often? Dog, kid, a bunch of people working on my projects, clients... makes it hard to stay on track. Unit tests are like my camping list. I could probably pack everything I need without it, but I'd spend the whole time worrying I'd forgotten something.

Joel Hooks

unread,
Nov 17, 2009, 2:12:23 PM11/17/09
to robo...@googlegroups.com
On Nov 17, 2009, at 12:12 PM, Tyler Wright wrote:

Testing has it's place to be sure. Building reusable libraries for release is different and unit tests are justifiable. They're a value-add to the project and guarantee stability and peace of mind. 

I don't understand how one can make this statement after getting through saying large enterprise applications don't benefit from unit tests. I have difficulty making the distinction. If the large enterprise application I work on and maintain everyday wasn't unit tested on the front and the back we'd be double fucked on more than one occasion. The "value-add" is far from superficial.

Sometimes I hear someone excitedly share that their tests found a bug and I just want to push their chair to the side and run the application in debug mode. "Look, see, I found the bug just as easily without all of those hours writing tests".

Run in debug mode, travel the happy path, and there it is! Meh. Devil is in the details, and frankly I don't think I'm smart enough to NOT unit test. YMMV

Shaun Smith

unread,
Nov 17, 2009, 2:40:56 PM11/17/09
to robo...@googlegroups.com
I don't entirely disagree. Personally, I'm waaaay behind on TDD, BDD and all that good stuff. As you hinted towards, unit testing is quite appropriate for libraries and frameworks - especially when a given library is being developed by an OS team; one needs to guarantee that applications written against such a library can depend on the API working predictably even as development moves forward.

I don't see a hell-of-a-lot of value in unit testing the wiring of an application - which, generally speaking, is where a large portion of time is spent when building Flex/Flash apps: building composite view components, layout, message passing, wiring views to models etc.

I *do* see a lot of value in testing the functional components of a system however. I'd like to be confident that the building blocks against which I write my application are performing as expected - and that they continue to do so as they get refactored.

More below:

On 17 Nov 2009, at 8:12 PM, Tyler Wright wrote:

Sorry, just catching up, and I know this is not the list to share but here goes.

What? This is the sharing-is-caring list! (aside from my little rant the other night, apologies all, and a special apology to Jesse! sorry dude).

I'm with Jesse on unit testing. I've never really appreciated the value of unit tests in application development, especially when you're doing a lot of refactoring in a large system.

Unit testing is what enables refactoring. "If you don't have any tests you're not refactoring you're just moving shit around" (I can't track down where that quote comes from, anyone?). Large systems that require refactoring are *good* candidates for unit testing - especially if the team itself is large. But, as with code, unit tests can be badly written. If refactoring your code requires you to edit all your tests.. you're doing it wrong.

Maintaining unit tests in an enterprise system means that there are twice as many classes to update with every refactor.

Again, that's not what refactoring is. Refactoring is cleaning up your code *without* breaking anything (and to a large extent, this should include your tests).

Because of type-checking, debugging and all the other features of Flex Builder I've never had a problem finding and fixing bugs quickly.

But you can only do that *after* you've become aware of the bug. That's not what unit testing is for. It's to prove that an API works as expected. You start from the outside: "How would I like to *use* this library?", then you write tests to prove that usage.

I think a lot of developers could learn better debugging techniques in place of building and maintaining a test suite for a GUI-strong enterprise application.

All developers *must* learn both. You have to know how to debug, and you have to know how to write *good* tests. The GUI-strong nature of Flash/Flex development doesn't put us in some magical position far removed from desktop application developers - to produce stable software there are known techniques and disciplines that have been proven to increase quality *and* productivity. Bad tests will slow you down, good tests will speed you up - same as the rest of your code.

Proper architecture, separation of responsibilities and encapsulation are essential to minimizing the scope of your changes, and as a result your testing and bugs.

Exactly, and these things enable you to write small, focused tests.

I've never been up at 3am fixing bugs I wished were found by unit tests, which I would have to write and update with each change in the system. A portion of all the time I save by not writing unit tests is applied to testing changes in the application manually (which I understand is still an essential exercise even with a test suite). Sometimes I hear someone excitedly share that their tests found a bug and I just want to push their chair to the side and run the application in debug mode. "Look, see, I found the bug just as easily without all of those hours writing tests".

Again, this is only possible once you know about the bug. Unit tests help prove that everything is *still* working as expected after changes, *before* you run into the bug in the application itself.

Testing has it's place to be sure. Building reusable libraries for release is different and unit tests are justifiable.

That's a perspective thing. Parts of an application are often very much like libraries after you've encapsulated them, and with the appropriate tests in place, can often be extracted into stable stand-alone libraries ready for distribution (along with their tests).

They're a value-add to the project and guarantee stability and peace of mind.

Stability and peace of mind are not merely "value-add" in my opinion ;)

TDD can help you design your API well and forces you to use your library.

Ba-boom!

Wherever you release documentation of code (such as an OS project) unit testing would be appropriate.

Why only for OS projects? Documentation and unit tests will help anyone who has to work on your app in the future (even if that person is yourself six months down the line).

But if I ever see a unit test targeting an application-specific MXML component I'd delete it promptly.

What if that unit test covers an application-critical MXML component? That's a stretch, and probably a symptom of bad design, but it's possible.

I'll admit I may be ignorant, maybe I haven't given testing a long enough trial.

I'm on the flip-side: I'm promoting something that I don't do properly myself... and it makes me feel funny. But I've learnt a lot about programming through the development of the RL unit tests, and I'm excited at the prospect of releasing applications that I can *prove* work, rather than applications that I can merely *suggest* work.

Tyler Wright

unread,
Nov 17, 2009, 6:19:29 PM11/17/09
to robo...@googlegroups.com
:D thanks all for the replies! I thought I might stir up a few ...
Sorry, just catching up, and I know this is not the list to share but here goes.
What? This is the sharing-is-caring list! (aside from my little rant the other night, apologies all, and a special apology to Jesse! sorry dude).

I meant this isn't exactly the best place to slam unit testing. Though everyone on this list is more than fair.
 
I don't see a hell-of-a-lot of value in unit testing the wiring of an application - which, generally speaking, is where a large portion of time is spent when building Flex/Flash apps: building composite view components, layout, message passing, wiring views to models etc.

Ok ok, so maybe deep down this is what eats at me. It bothers me that many architectural frameworks modularize the tiers and actors so much that it's harder to debug, all in the name of unit testing. To test the composite views, to test the wiring, tests that test those tests. And in the end the separation makes it so difficult to follow and debug the logic of an application that those tests are all you've got. PureMVC is the best example of this, but how many other frameworks subscribe to the same standard? Robot Legs claims to have very little boiler plate, but how much functionality do you get for all the work of wiring a full RL application? Love you guys, still think RL is the premier IoC framework, just struggling to justify the cost-benefit of that level of separation between tiers.

Tyler

Joel Hooks

unread,
Nov 17, 2009, 6:38:40 PM11/17/09
to robo...@googlegroups.com
On Nov 17, 2009, at 5:19 PM, Tyler Wright wrote:

> It bothers me that many architectural frameworks modularize the tiers and actors so much that it's harder to debug, all in the name of unit testing.

It isn't about unit testing, it is about clear separation of responsibilities. Seriously, who unit tests in the Flash world? You want just enough abstraction, not too much, not too little. To me, monolithic MXML files with some shitty code behind as sidecar is not enough. Whereas 6 levels of abstraction for each bit of functionality is too much. I want to be Goldilocks here. Just right. To me, the modularization is about providing discreet tiers of an application that other tiers can access and communicate with. I have my data model, that stores data, and is accessed by many part of the view. While I can see why people don't really want to bother with the Mediator layer, I like to do that because it creeps me out to have system logic inside of my components, and I also do really try to reuse them in multiple applications. Mediators provide a nice system specific layer of abstraction. With PureMVC I always had the Service bits in my Proxy classes. Shaun sold me on the idea of separating the two, and I haven't looked back.

In terms of unit testing, I think that business and domain logic should be tested. I'm not interested (so much) in integration testing while building an application. I know that Robotlegs works, so that isn't my interest. I'm not going to test view components (try to keep them dumb), rarely will I test a mediator (they are just pitching events), certainly not testing the wiring, but Service and Model classes are prime candidates for unit tests. They do stuff, manipulate data, that sort of thing. Given A does my model properly return A+B/C. Sneaky shit, that might even LOOK right, but isn't right. The kind of work robots are made to do. Unit tests are little helper robots to free my brain of having to worry about minor errors that I likely wouldn't catch anyway, but I know might occur. Sanity. I don't know if you're familiar with David Allen's Getting Things Done (http://en.wikipedia.org/wiki/Getting_Things_Done), but unit tests are his trusted dump bucket where you can offload the myriad of things you have to worry about and concentrate on the important aspects of your application.

Regarding PureMVC, of which I am a fan, the layers/tiers/abstraction are a godsend when I have long-running/large-scale app projects that I have to maintain and support. I have 3 huge PureMVC apps that I get to do this on right now, and I can jump into any of them and quickly know what is going on. Open the model folder, there is all my data, open the view folder and don't even sweat the view components, it is all there in the mediator (take that MXML). If I crammed all that into the view component I'd need to physically look at that declarative markup when I am debugging. Yick. Don't even get me started on the code-behind approach to MXML components. It gets me stabby.

Reply all
Reply to author
Forward
0 new messages