-
Notifications
You must be signed in to change notification settings - Fork 268
Modularizing Assemblies
Typhoon allows you to group related components together under a TyphoonAssembly sub-class.
- Keep things organized and group related parts of an application assembly.
- Expose an interface containing the public component(s) to be produced. The internal details need not be exposed.
- Allow plugging in different implementations of an assembly when [activating](Activating assemblies).
While grouping components together in logical, modular TyphoonAssembly
units is great, they're not very useful if they are all isolated from each other.
Let's say you have separate TyphoonAssembly
s for each of your application's three main concerns: UI (UIAssembly
), network operations (NetworkComponents
) and persistence (PersistenceComponents
).
In NetworkComponents
you might have a httpClient
that handles RESTful API calls, like so:
@implementation NetworkComponents
- (id<SignUpClient>)httpClient
{
return [TyphoonDefinition withClass:[HttpClient class]
configuration:^(TyphoonDefinition* definition)
{
//etc. . .
}];
}
@end
Now let's suppose we have a signUpViewController
in UIAssembly
that takes a new user's credential information and needs httpClient
to submit the information onto the backend. No problem:
@interface UIAssembly : TyphoonAssembly
// Typhoon will automatically inject the two collaborating assemblies (NetworkComponents and PersistenceComponents) here.
@property(nonatomic, strong, readonly) NetworkComponents* networkComponents;
@property(nonatomic, strong, readonly) PersistenceComponents* persistenceComponents;
// Local components that require components from collaborating assemblies ...
- (RootViewController *)rootViewController;
- (SignUpViewController *)signUpViewController;
- (StoreViewController *)storeViewController;
@end
@implementation UIAssembly
// signUpViewController consumes httpClient component from 'NetworkComponents'
- (SignUpViewController *)signUpViewController
{
return [TyphoonDefinition withClass:[SignUpViewController class]
configuration:^(TyphoonInitializer* initializer)
{
[definition injectProperty:@selector(client) with:[_networkComponents httpClient]];
}];
}
... // Other UIAssembly components here
@end
Viola.
NOTE: For each collaborating assembly that is declared, one that fulfills this role must be provided during [activation](Activating assemblies). It can be the declared class, a subclass or even a protocol that fulfills the role. This gives plenty of flexibility, for example, to patch out the network components for stubs in integration tests. If an assembly fulfilling the role of the collaborator is not provided during activation, Typhoon will fail at start-up.
###Activating
We can provide a different realization of the NetworkComponents or PersistenceComponents when [activating the assembly](Activating Assemblies) as long as the objects they build conform to the same class or protocol.
UIAssembly *uiAssembly = [UIAssembly assembly];
NetworkComponents *networkComponents = [TestNetworkComponents assembly];
PersistenceComponents *persistenceComponents = [PersistenceComponents assembly];
[[TyphoonAssemblyActivator withAssemblies:@[
uiAssembly,
networkComponents,
persistenceComponents]] activate];
SignUpViewController* viewController = [uiAssembly signUpViewController];
##Layered architecture
Modules can really help to promote a neat, robust architecture. But without a little discipline its still easy to get things messed up. Try to avoid heavy coupling between your modules. A good rule-of-thumb is to aim for a layered architecture, as shown below. We have infrastructure components at the bottom, with increasing levels of abstraction until we reach our top-level application assembly. Visibility between the layers can point downwards, preferably to the layer immediately below, but should not point upwards.
See also: The The Typhoon Sample Application for an example showing the use of modularized assemblies.
See also: TyphoonPatcher, as described in Integration Testing is another approach to swapping out components for another implementation.
Something still not clear? How about posting a question on StackOverflow.
Get started in two minutes.
Get familiar with Typhoon.
- Types of Injections
- What can be Injected
- Auto-injection (Objective-C)
- Scopes
- Storyboards
- TyphoonLoadedView
- Activating Assemblies
Become a Typhoon expert.
For contributors or curious folks.