Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can dependency injection like Typhoon replace multiple singletons?

I have an app that has about 11 different Singleton instances used throughout the many app's methods and classes; it's getting out of hand, and I want to replace all of them with dependency injection, like Typhoon. However, I am unable to find any doc, sample or mention of how to replace the singletons with dependency injection, including Typhoon. For instance, do I use multiple instances of Typhoon, replacing each singleton with an instance of Typhoon?

like image 970
SpokaneDude Avatar asked Dec 30 '14 22:12

SpokaneDude


1 Answers


Edit: Pilgrim is the official Swift successor to Typhoon!!


Typhoon creator here. Yes, one of the uses of dependency injection it to provide the benefits of singletons without the drawbacks. But you don't necessarily need a library to apply the dependency injection pattern and replace your singletons. In fact it helps to understand the pattern by looking at how to implement it without a framework first:

Hollywood Principle: Don't call us, we'll call you

High level classes, like view controllers defer to collaborators to do their work. As you've mentioned you have around 11 of these. Now there's two ways to couple your class to the collaborator:

Seek out (call) the collaborator:

initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle 
{
    self = [super initWithNibName:nibname bundle:bundle];
    if (self) {
        _serviceClient = [MyServiceClient sharedInstance];
    }
} 

And the above way works, but its not good because:

  • If you want to provide an alternative implementation, then you have to go and change each class that uses it.
  • It makes writing clean unit or integration tests difficult. You have to look at the class's internals (glass box testing) instead of focus on the external interface contract (black box testing).
  • It provides overly tight coupling, which leads to poor cohesion.

The alternative:

Simply pass the collaborator in, via an init method or a property.

initWitServiceClient:(id<ServiceClient>)serviceClient
{
    self = [super initWithNibName:@"MyNib" bundle:[NSBundle mainBundle]; 
    if (self) {
        _serviceClient = serviceClient;
    }
} 

How is this different to just . . . passing arguments?

Instead of hard-wiring a collaborator you pass it in as an argument. But now the next class up is hard-wired! So you keep doing this until you have a top level assembly class, that knows how to build your view controller (and other classes) from the individual pieces. If you do this:

  • All of the references to each singleton points to one place. So replacing one of your singletons with a compatible implementation requires only one line of code change. Similarly you have encapsulated the configuration for this class.
  • Its easy to write unit and integration tests for your classes. In the latter case, you can patch out one component for another. This can overcome two of the drawbacks of integration-style tests. The first being that its difficult to put the system in the required state for a test scenario, and the second being that they can have unwanted, side-effects. Meanwhile, pure unit testing is simplified too, since its now easy to see the dependency contract and pass in mocks or stubs for these.
  • Classes clearly document their "seams" and what are the significant collaborators they'll be delegating to in order to perform their tasks. This leads to "high cohesion".

Now Using Typhoon:

You'll have one retained instance of Typhoon per normal app. It will hold your singletons.

  • Declare an assembly that defines your singletons. Give them singleton scope.
  • Bootstrap Typhoon in your app using plist integration. The Typhoon sample app shows how to do this.
  • Define an assembly that defines and injects your view controllers. The Typhoon sample app shows how to do this. Alternatively use auto-wiring macros. These work very nicely if you're using Storyboards.

If after studying the above material you have a more specific question we'd be very happy to help you.

like image 124
Jasper Blues Avatar answered Oct 23 '22 17:10

Jasper Blues