Many people have trouble getting the hang of dependency injection, at first. And I think part of the problem is that it is actually so simple that we’re inclined to look for something more complicated. “Surely that there has to be more to it?!”, so to say. So, with that in mind, imagine that you’re writing an app that gives weather reports. You need a cloud-service (excuse the pun ;) )
to provide the data, and at first you go for a free weather report provider, but in future you’d like to integrate a weather service with better accuracy and more features. So, as do all good object-oriented developers, you make a WeatherClient protocol and back it initially with an implementation based on the free, online data provider.
The thing with this approach is, if you wanted to change to another weather client implementation you’d have to go and find all the places in your code that use the old one, and move them over to the new one. Each time, making sure to pass in the correct initialization parameters. A very common approach is to have a centrally configured singleton:
With either of the above approaches, in order to test your view controller, you now have to test its collaborating class (the weather client) at the same time, and this can get tricky, especially as your application gets more complex. Imagine testing Class A, depends on Class B, depends on Class C, depends on… Not much fun! Sure, you could patch out the singleton with a mock or a stub, but this requires peeking inside the code to find the dependencies. Besides taking time that could be better spent else-where, this ends up becoming “glass-box” testing as opposed to “black-box”
testing. Isn’t it better to be able to test the external interface to a class, without having worry about what’s going on inside? And you have to remember un-patch again at the end of the test-case or risk strange breakages to other tests, where it’s difficult to pin-point what the real problem might be. So with dependency injection, rather than having objects make their own collaborators, we have them supplied to the class instance via an initializer or property setter.
Yes it is. Right now, you might be thinking “Geez! That’s a pretty fancy name for something so plain.” Well, you‘d be right. But let‘s look at the implications on our application architecture: If you do this with significant collaborators throughout your app, it means that the GoogleWeatherClientImpl is now declared in a single place – the top-level assembly, so-to-speak. And all of the classes that need to use some kind of id<WeatherClient> will have it passed in. This means that:
If you proceed with the Dependency Injection pattern (assuming you’re not one of the remaining “flat-earthers”, who believe that Objective-C somehow magically alleviates the need for common-sense: “Oh, I don’t do DI, I use swizzling class-clusters!”), then there are basically two options:
You can do dependency injection without a framework to help you. It is simple after all, and in fact I recommend you do this, at least as an exercise in software design. And yes, it is certainly possible that this will be adequate. But, I think its good to have help, if you can get it. You can also write tests without a test framework, mocks with out a mock library, and software without a compiler.
So, going down the framework route, there’s been quite a lot of action in Objective-C land, over the last three years. In fact, there are now around 15 Dependency Injection frameworks, many following in the footsteps of Google Guice. The authors have done a great job (Objection is especially good). However, I wanted an approach that allows the following:
Non-invasive. No macros or XML required.
Spring-style XML or Guice-style macros are fully supported, but focus is on a powerful Objective-C approach.
No magic strings – supports IDE refactoring, code-completion and compile-time checking.
Provides full-modularization and encapsulation of configuration details. Let your architecture tell a story.
Dependencies declared in any order. (The order that makes sense to humans).
Makes it easy to have multiple configurations of the same base-class or protocol.
Supports injection of view controllers and storyboard integration.
Supports both initializer and property injection, plus life-cycle management.
Powerful memory management features. Provides pre-configured objects, without the memory overhead of singletons.
Excellent support for circular dependencies.
Lean. It has a very low footprint, so is appropriate for CPU and memory constrained devices.
Battle-tested — used in all kinds of Appstore-featured apps.
Returns weather reports from a remote cloud service.
Caches weather reports locally, for later off-line use.
Stores (creates, reads, updates deletes) the cities that the user is interested in receiving reports for.
Can use metric or imperial units.
Clone this repository, open the Xcode project in your favorite IDE, and run it. It’ll say you need an API key.
Get an API key from WorldWeatherOnline
Using your API key, set the application configuration.
Run the App in the simulator or on your device and proceed to the exercises here.
Start using Typhoon! Check out the User Guide.
Engineer. Artist. I enjoy the creative utilization of technology to achieve solutions in business.
I'm passionate about software craftsmanship, automated testing and the design of dependable systems.
I spend most of my time between Cocoa and Ruby, but I always love learning new things.
I feel great satisfaction in building structured and elegant software. You can't build a great app on a weak foundation.
Perfectionist. I like challenging performance problems — optimising code until it achieves the best possible speed.
A. We get this one all the time.
These are the cities where the Typhoon core team members live. It goes to show: you never know where you’ll find a ninja coder lurking these days. They’re also the default cities in Pocket Forecast - the Typhoon sample application. Incidentally, as I’m writing this its +41° celsius in Phnom Penh and -30° in Omsk!
A. There’s a Typhoon tag on StackOverflow,
which is monitored by Typhoon users and contributors.
Alternatively if you’d like professional consultation, please get in touch. While Typhoon is open-source, free and volunteer-based we do maintain a network of skilled consultants, so chances are that we can put you in touch with an expert or company who’d be willing to help you out on a professional basis. For example, Typhoon’s original founder, Jasper Blues, currently works on a freelance basis. And if you need a larger team, perhaps try Al Digit.
A. Typhoon can be used with OS X and iOS. It has not been tested with GnuStep. It can be
used with or without ARC, but not with garbage collection.
Internally, Typhoon relies on some weak references which where introduced in iOS 5.0 (iPhone3gs and up, iPad 1st generation and up) and OSX 10.7 (most Macs built since 2009).
A. Yes, and I love categories, method swizzling, duck-typing, class clusters, associative
references in categories, and all that cool stuff. None of these are replacements for DI.
A. If by elsewhere you mean from everywhere to one place, and (in the case of statically compiled languages) from compile-time to runtime … then yes! That is the purpose of dependency injection.
A. No, not really. It gets the job done (depending on what its being used for).
But what does this have to do with Typhoon?
Not that much, actually. You might have heard that the first release of Typhoon was called Spring for Objective-C? Quite a few people took that to mean XML. This is not what we meant, at all.
What we did mean, was that like Spring, Typhoon takes a two-step approach to dependency injection. It first parses all of the component definitions into an internal model, with hooks for post-processing. We followed the Spring Framework’s example here, because it is a powerful and versatile approach, and affords the opportunity to define many styles of dependency injection, as well as an easy way to have several components of the same type (class or protocol) configured in different ways.
Like Spring, we do support a range of DI styles, including Spring-style XML, and auto-wiring macros. You can use these if they suit you. But we’d really like you to try Typhoon’s powerful native approach.
A. No, its just a light-weight, Spring-style DI container. I personally think that Spring
an excellent DI container, and it’s huge popularity and availability in several languages says a lot. With
regards to other Spring Portfolio products: some I like, and some I don’t.
Update: Objective-C's dynamic/runtime method dispatch makes it very easy to implement the intercept pattern and provide runtime augmentation of classes, however we've observed that there's still an unmet need for a formalized AOP-framework. Specifically, being able to modularize cross-cutting concerns and identify the places where these should be applied using a point-cut expression language. To this end, we've started some work on Typhoon-AOP. More news to follow!
A. Yes! At start-up Typhoon consumes about the same resources as parsing a JSON response
from a network request. Also, Because Typhoon allows the use of prototype-scoped components instead of
singletons, components that aren’t required can be deallocated when they’re not being used.
In fact, the award-winning ACO Virtual’s controller app was deployed on iPad 1s, because these represented very good value for money at the time hardware was being purchased. We received a lot of compliments about this app’s stability.
A. Injecting. Others might consider it banal and somewhat of a drag, but Typhoon actually
gets-off on it. Typhoon lives to inject. Once while travelling through a rough-part-of-town in a
foreign city, Typhoon and I happened upon a psychopath-gangster-singleton from the 80s. This thing was seriously
intimidating and widely reported in the press as being ‘uninjectable’. Well Typhoon injected the shit
out of it without even breaking a sweat.
View controllers? This is child’s play for Typhoon. Initializers and properties, xibs or no xibs and with or without Storyboards. You can also use it to build complex views, if you like. Take a look at the sample app.
A. Over the 2012-13 new year, I had a family holiday booked at one of our lovely beaches… but it turns out there was a late-in-season
Typhoon. So I stayed home and wrote this instead… Also it was inspired by the Spring Framework.
In temperate climates we have Spring, Summer, Autumn & Winter. But here in the Philippines we have
hot-season, sizzling-hot-season and Typhoon-season ;).
Update: Since then we have had the incredibly destructive super-typhoon Haiyan, which has been very sad. Our sincere condolensces to all those affected.