I'm getting started with Typhoon and finding that it is annoying to keep writing constructors with additional assembly arguments. So it is tempting to just make my TyphoonAssembly a singleton. But I've yet to see that done in any examples, and I do see examples where constructor or property injection is used to provide an assembly. So maybe there is a case against it - it does seem kind of bad, but how bad, I don't know.

So my questions are:

  1. Is there a strong case against making my TyphoonAssembly a singleton?
  2. Is there a way to do so within the framework, or should I just do it my usual way?

Edit: I'm just starting out, but let's say I have a single (for now) ApplicationAssembly that is used as follows:

- (NavigationController *)customDefaultNavigationController {
    return [TyphoonDefinition withClass:[NavigationController class]
            configuration:^(TyphoonDefinition *definition) {
                [definition useInitializer:@selector(init)];
            }];
}

- (id<IRootWireframe>)rootWireframe {
    return [TyphoonDefinition withClass:[RootWireframe class]
            configuration:^(TyphoonDefinition *definition) {
                [definition useInitializer:@selector(init)];
            }];
}

Nothing even worth mentioning, but the point is that I have at least three or four clients of this assembly in my new application that is still at the "Hello World" level of functionality.

Going forward, if I need to be writing initializers with assembly parameters, I'll do it, but if I can get away with just making my ApplicationAssembly a singleton (or scoped in an object that is) then I will.

1

There are 1 answers

0
Jasper Blues On BEST ANSWER

I don't think anything will break if you make your assembly a singleton, but it should never be necessary. Your assemblies contain recipes or blueprints to instantiate objects, and at startup, behind the scenes, all of this information goes into a TyphoonComponentFactory. The assemblies themselves, at this point, have essentially done their job, and its now the responsibility of the TyphoonComponentFactory to build or emit a scope-cached instance, when asked. . .

. . after startup, we continue to use the assembly interfaces, so that we don't have to resort to 'magic strings', but this just results in Objective-C message forwarding through to TyphoonComponentFactory's componentForKey method.

You can bootstrap a Typhoon (or library, etc) in one of the two following ways:

Using plist integration

This means that you'll have one instance of TyphoonComponentFactory throughout your application.

Manually

For Example:

MiddleAgesAssembly *mainAssembly = [[MiddleAgesAssembly new] 
    activateWithCollaboratingAssemblies:@[
      [QuestsAssembly new]
    ]];

In this case, its up to you to retain the TyphoonComponentFactory for as long as needed, and in the case of an app, it would generally be throughout the lifecycle of the app. For now I recommend retaining it on the app delegate, although once you're comfortable, you'll see that it could be implicitly retained through proceeding from one object graph to another.

So, for either approach of bootrapping Typhoon, there's no advantage to the assembly being a singleton. (In fact for plist integration style, this would simply be ignored).