SwiftSuspenders 1.5, or: A tale of robots and refactorings

ActionScript,Projects,swiftsuspenders — till on May 15, 2010 at 17:41

Nearly half a year ago, I released SwiftSuspenders 1.0.

As hinted at in the related blog post, this new release contains a solution to the “Robot Legs Problem”: and it goes by the name of Child Injectors.

So, why would robot legs pose a problem for a dependency injection container, you ask. In short: They don’t – their creation does. See, DI containers are all about creating object graphs. That is: They allow you to create complex, nested trees of objects in an automated fashion.

Want to build a car? You can either go about it manually from the outside in: You create the car’s shell, then you realize that your car probably needs an engine. You put that in, at which point you realize that your engine will need need cylinders, so you add some of those, and so on.

Or, you can use a DI container and do everything the other way around: You first create a collection of all the parts your car will consist of, and then you tell the DI container to instantiate the outermost part – the shell. The container inspects the shell and sees that it needs some parts, like an engine. It then looks through the set of parts you supplied, and adds those that fit the dependencies of the shell. In doing so, each of the parts is itself inspected and all its dependencies are fulfilled, recursively.

Now, imagine you want to build a robot. Robots aren’t really special in any way that’s interesting for DI containers at all. It’s just that their construction is commonly used to explain a problem that you’ll sooner or later encounter if you use DI containers to create complex objects.

What is the Robot Legs Problem?

The robot legs problem describes the difficulties that one experiences when trying to construct structures with two or more sub-trees that are very similar, but not identical to one another.

See, that robot, it’s supposed to look like a human being in many ways: It’ll have a head, a torso, two arms and two legs. But there’s an important difference to a human: The robot is much, much simpler. For example, parts of this robot’s legs are identical for both sides. Now ideally, if you’ve got two knee joints that are entirely identical to one another, you only want to define them once. The problem is that for our robot, there are parts further down the legs that differ for each side. say the knee joints are identical, but the ankles are slightly different for each leg. How is the DI container supposed to know that it has to supply different parts somewhere down the leg if some intermediary parts are identical? It can’t. Well, not without some help, at least.

That’s the Robot Legs Problem.

There are (at least) two solutions to this problem: Either you add some differentiating attribute to the knee joints and all other parts that are really the same, functionally; or you somehow add information to the DI container’s configuration that lets it figure out the differences from the outside.

The first option isn’t really attractive, but it’s the easiest from a conceptual point of view: Instead of having one class Knee, you create two classes, LeftKnee and RightKnee, both extending Knee. The only thing that differs for these classes is that they define dependencies for LeftAnkle and RightAnkle respectively (I’m leaving out any intermediary parts such as bones here for reasons of simplicity. For your own, real-world, robot, you’d probably want to have some of those). Apart from adding a lot of boiler-plate code (imagine this with your real-world robot that has about 53 parts in each leg that are functionally entirely identical for both sides!), this creates serious problems in terms of separation of concerns and encapsulation: If the knees truly are functionally identical, it’s none of their business to know anything about which leg they are added to.

What kind of solution does SwiftSuspenders provide?

Obviously, we want to use the second solution – and with SwiftSuspenders 1.5, we finally can. The solution comes in the form of child injectors.

Child injectors are simple things: They try to satisfy all dependencies themselves, but if they can’t find a mapping for one, they turn to their parent and ask if it has a corresponding mapping. Really, they’re kinda dumb.

But here’s the thing: SwiftSuspenders lets you create trees of dependency mappings that use different child injectors to satisfy recursive dependencies. In our example, you’d create rules for the LeftHip and the RightHip:

var injector : Injector = new Injector();
var leftHipRule : InjectionConfig = injector.mapClass(LeftHip, LeftHip);
var rightHipRule : InjectionConfig = injector.mapClass(RightHip, RightHip);

Now in order to differentiate further down the leg, we create parallel structures for both legs in separate injectors. But first, we need to create and set these injectors:

//let your main injector create a child injector:
var leftLegInjector : Injector = injector.createChildInjector();
//you can also create a new injector and set its parent:
var rightLegInjector : Injector = new Injector();
rightLegInjector.setParentInjector(injector);
//Let SwiftSuspenders use the child injectors from the hip on down the leg:
leftHipRule.setInjector(leftLegInjector);
rightHipRule.setInjector(rightLegInjector);

With this, our injectors are all set up as we need them – on to the remaining injection mappings.

Both LeftHip and RightHip have a dependency (and I’m leaving out the knee here

[Inject] public var knee : Knee;

As this dependency is the same in both legs, we can safely add it to the main injector:

injector.mapClass(Knee, Knee);

Upon not finding a rule for the Knee dependency, the child injectors will turn to their parent and get the rule we just defined. After using that to inject the Knee, they will continue on down the tree of dependencies.
The Knee has a dependency for an Ankle:

[Inject] public var ankle : Ankle;

Not that the Knee would care, but this field is actually supposed to contain a different value, depending on which leg the Knee is added to! Because of that, we have to add different mappings to the child injectors:

leftLegInjector.mapClass(Ankle, LeftAnkle);
rightLegInjector.mapClass(Ankle, RightAnkle);

And with that, we’re done with the configuration! Assembling our robot is now a simple matter of letting our injector instantiate the class Robot, which of course defines dependencies for LeftHip and RightHip:

var myRobot : Robot = injector.instantiate(Robot);

Great! And what about the refactorings?

Right, the refactorings. Those have been applied to the SwiftSuspenders source code. Lots of them, in fact. Their primary goal was to support child injectors, but they also lead to a much cleaner separation of concerns. Basically, there are now three basic building blocks in SwiftSuspenders, each with their own very specific concern:

  • The Injector, which acts as the facade to the entire system and keeps everything together
  • The InjectionConfig, which acts as the broker between injection points and injection results
  • Several kinds of InjectionResults, which are held by InjectionConfigs and generate or keep the value that’s injected into injection points

In the future, robotic beings will rule the world. Well, that, and the aforementioned refactorings will allow for a better syntax for defining inection mappings. Something along the lines of injector.map(MyInterface, 'named').toClass(MyClass);. But that’s going to happen in the year 2000. Or version 2.0, I’m not sure.

Introducing SwiftSuspenders

Projects — till on September 21, 2009 at 16:20

Working with RobotLegs

Recently, I started working with the awesome MVCS framework RobotLegs by Shaun Smith.

As I’m not a big fan of the configuration overhead that the Spring framework for Dependency Injection brings with it, I immediately fell in love with the metadata based SmartyPants IOC framework. While I really like the approach and everything worked great, I quickly realized that SmartyPants has two problems: It’s somewhat slow and, due to some dependencies on the Flex framework, rather big.

SwiftSuspenders: A fast, lightweight DI solution

That’s why I started implementing an ultra lightweight DI framework (which hardly even deserves being called a framework) which then became SwiftSuspenders.

SwiftSuspenders implements exactly the functionality needed by RobotLegs, nothing more, but, crucially, nothing less – and it does so as fast and as lean as possible. By focusing on these needs, I was able to implement a solution that’s about an order of magnitude faster and weighs only 10% of SmartyPants file size-wise. And yes: Both of these values are SWAGs and shouldn’t be relied on for, well, anything.

Right after I published SwiftSuspenders on GitHub – as you should do with everything you build that might be of help to your esteemed colleagues – awesome stuff happened: Shaun Smith immediately forked to project, started fixing bugs and embarrasing mistakes in the documentation and switched most of the examples for RobotLegs to using SwiftSuspenders and hinted at creating unit tests – which I shamefully neglected. Yesterday, he followed up on that and pushed a range of unit tests to a new GitHub project!

What now?

Apart from you reading the introductory documentation, starting to use SwiftSuspenders and forking it on GitHub? I’m not sure.

I think that maybe, SwiftSuspenders is pretty much done as it is. SmartyPants still has some features that SwiftSuspenders doesn’t, but for now, I don’t think that those are really essential. Then again, I might implement Provider Binding and Rule Binding sometimes later – whereas I can almost guarantee that I won’t implement live bindings.

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License. | Till Schneidereit