StrangeIoC
This is a high-level introduction to StrangeIoC, a binding framework supporting Dependency Injection written especially for use with C# and Unity. Mostly, it’s a defense of Inversion-of-Control and the principle of employing decoupled architecture.

This article is about why you want to use Strange. For tutorials and more complete documentation on how to use Strange, click here.

When bad code happens to good programmers

I once worked at a company full of great engineers. Smart folks. Lots of experience. Dreadful code. No, really, this company full of smart, experienced engineers produced the worst code library I’d ever seen — an unremitting snarl of interdependent spaghetti. At the time, I imagined many reasons for this oozing canker of a codebase. Management rushed out product before it was ready. Producers were driven like whipped and panicked huskies to show short-term results. Development was on a platform unfamiliar to much of the team, and there was never enough time to refactor. On top of it all, this creaky, fragile codebase was shared between multiple, slightly different, products. It seemed self-evident that the failure lay not in myself nor in my colleagues, but in external forces beyond our control.

In the thick of this impossibly depressing quagmire I dreamed up a utility I termed a scaffold: a mapping system to provide dependencies as-needed at runtime. I hoped that the scaffold would decouple much of the spaghetti and allow for the product variations our shared codebase demanded. Alas, while the idea was sound enough, it was too little, too late to save the struggling project which rapidly approached a degree of technical debt from which it would never recover. But a friend and fellow engineer looking over my scaffold concept asked me if I knew about an Inversion-of-Control framework called Robotlegs? I had to admit that I didn’t know Robotlegs, nor even what Inversion-of-Control meant. “Oh,” he replied, “It’s what you’re doing. It’s just that Robotlegs does it right.”

Standing on our own Legs

Once I looked at Robotlegs, I began to understand what my friend meant. My scaffold was in many senses naive; caught up as I was in our specific interdependency struggle, I failed to see the bigger picture. And while I was for practical purposes engaging in Inversion-of-Control (IoC) and a design pattern known as Dependency Injection (DI), those concepts were too novel to me at the time to grasp their significance. The core principle of IoC is simple: abstract the dependencies between code modules and then satisfy those dependencies at runtime. “Uncle” Bob Martin describes the benefits this way:

“The principle of dependency inversion is at the root of many of the benefits claimed for object-oriented technology. Its proper application is necessary for the creation of reusable frameworks. It is also critically important for the construction of code that is resilient to change. And, since the abstractions and details are all isolated from each other, the code is much easier to maintain.”

This “inversion” expresses the idea that, instead of a class declaring “I need a thing”, some other actor tells it “here is what you need.” Dependency Injection is the process by which a special class (the Injector) provides the things that the other classes need.

“But”, you might argue, “I already practice good Object-Oriented programming. My code is DRY. I follow the KISS and single-responsibility principles. I program to interfaces. I know classic design patterns and anti-patterns. Why would I need anything else?”

Here’s an example why:

Let's say you have a single-player game that connects to Facebook. Every time the game is over and you score a personal best, it wants to prompt you to send a post to the player's Facebook wall. In a classic Unity setup, you might send a score update to a FacebookService like so:

public class MyShip : MonoBehaviour
 {
     private FacebookService facebook;
     private int myScore;
     
     void Awake()
     {
          facebook = FacebookService.getInstance();
     }
     
     void onDie()
     {
          if (score > highScore)
               facebook.PostScore(myScore);
     }
}

There are at least two big problems with this simple code snippet. First, the ship itself is acting as a controller. By telling the FacebookService that it wants to post, it tightly couples itself both to the game logic and to the FacebookService. Second, the FacebookService itself is written as a Singleton. What if the design changes and we need to post to Twitter...or Google+...or even the user’s choice of social site? What if the logic of Facebook's terms of service changes? What if the game suddenly became two-player? If all your code were written like the above, you'd have a lot of refactoring to do. You might even conclude that it was easier to throw it away and start over.

With IoC, you'd write this very differently:

public class MyShip : MonoBehaviour
{
   void onDie()
   {
      dispatcher.Dispatch(GameEvent.SHIP_DEAD);
   }
}

Notice how we've removed any reference to logic. The view has done something that precipitated death, that's all it needs to know. It sends a message. Somewhere else (the view doesn't know or care where), the logic that governs what to do about that death is handled. Specifically, it's handled by a Command, which looks like this:

public class OnShipDeathCommand : EventCommand
{
   [Inject]
   ISocialService socialService{get; set;}
   
   [Inject]
   IScoreModel scoreModel{get; set;}
   
   override public void Execute()
   {
      if (scoreModel.score > scoreModel.highScore)
         socialService.PostScore(scoreModel.score);
   }
 }

Notice the [Inject] tags, which are tied to Interfaces, not concrete classes. By injecting classes that satisfy Interfaces, rather than declaring the classes themselves, we remove any dependencies that force this part of the code to expect a Facebook, Twitter or Google+ class. It simply knows that there's some social service to which it can post.

And to answer the question of what gets concretely bound, there's a single, central class called a Context:

#if UNITY_ANDROID
injectionBinder.Bind<ISocialService>().To<GoogleService>().AsSingleton();
#else
injectionBinder.Bind<ISocialService>().To<FacebookService>().AsSingleton();
#endif
//...or...
//injectionBinder.Bind<ISocialService>().To<MultiServiceResolver>().AsSingleton();

injectionBinder.Bind<IScoreModel>().To<ScoreModel>().AsSingleton(); commandBinder.Bind(GameEvent.SHIP_DEAD , OnShipDeathCommand);

See how easily we can swap between Facebook, Google+ or anything else? With IoC, there's no need to bind anything concretely. Also notice how we never need to write a Singleton. We simply map it. Writing your code so that it has to be a Singleton presumes that it can never be anything else. IoC moves you away from this limitation. We've also bound the event the Ship fires to the Command that runs the logic. Each piece is isolated, modular and portable. By binding, instead of coupling, code remains flexible and highly maintainable.

We’ve even snuck in an example of dynamic binding based on platform. You can readily imagine other powerful use cases.

The Robot dances

Robotlegs took the IoC principle and built on top of it a small but crazy useful micro-framework that paired IoC with a common event bus (so communication may be global) and a few basic patterns. Provided a team followed a handful of fairly simple rules (such as writing to interfaces), this effectively isolated controls and eliminated much of the confusion about where to put things and how to build them. This in turn removes lots of grunt work and frees developers to concentrate on more interesting and important tasks. It is not too hyperbolic a statement to say that understanding IoC/Dependency Injection was as profound for me as was my introduction to Object-Oriented Programming. Since the day my friend mocked my scaffold, it has fundamentally shifted the way I approach coding.

Unity: it’s time to get Strange

When ThirdMotion started using C# and Unity3D, we were surprised to find no serious IoC framework available for Unity. After a couple of projects in which our standard code libraries began to take shape, we formalized our in-house framework and decided to share it with the entire Unity community.

StrangeIoC is a super-lightweight and highly extensible Inversion-of-Control framework, written specifically for C# and Unity. We’ve validated Strange on web, standalone, iOS, and Android. It contains the following features, most of which are optional:

In addition to organizing your project into a sensible structure, Strange offers the following benefits:

Binding it all up

They say generals are always fighting the last war. In a way, I guess that's what I'm doing here: fixing the problems that so beset the team I described at the top of this post. IoC leads to minimized interdependency — less spaghetti. A standardized, unified design pattern leads to less confusion as to where things go and why. A common event bus means never having to figure out how a message will travel from point-to-point. View mediation separates the volatile display code from the intricacies of how and where data is processed and stored.

In writing this first public release of Strange (v0.5), we’ve focused on flexibility, both in the framework itself and for you, and on the structures that make the most of IoC. We’ve probably missed a lot, and doubtless some aspects will need improvement. But overall we believe we’ve delivered a powerful new tool to the Unity community, one which we’ve seen bear out to astonishing effect in other environments. As Unity3D is exploding just now, we hope the release of a simple micro-framework that encourages rapid, organized development by engineers of radically different styles and abilities will be a useful addition to the available tool chest.

I hope you use Strange and find it worthy of all my claims. I hope to hear from you with lots of Strange ideas and Strange insights. Happy coding!