While working on the slides for our upcoming talk on TDD for iPhone I asked Eric Meyer why we need the Dependency Inversion Principle. He eagerly answered, “Testing!” which made me laugh because I wasn’t giving him a trivia quiz, and I love Eric’s enthusiasm.
He’s right, but the answer is circular. TDD is great because it gives us better designs that correspond to the DIP which enables TDD. Ha! I win, would you like to buy my consulting services? I have plenty of three letter acronyms where those came from.
Fortunately this isn’t the case, as the DIP existed well before TDD was popularized, but recently there was a bit of a dust-up over the SOLID principles. Many developers don’t understand why dependency inversion is important, so let’s demonstrate the usefulness in the Objective-C language on the iPhone.
The Dependency Inversion Principle reads as follows:
- High level modules should not depend upon low level modules. Both should depend upon abstractions.
- Abstractions should not depend upon details. Details should depend upon abstractions.
So your code should depend on interfaces not on concrete classes, but why? Let’s look at a useful example in the Objective-C built in classes.
1[NSString stringWithFormat:@"Object is: %@", object];
Do you see the DIP at
work? It’s subtle here, but look at the method < code>stringWithFormat>,
which takes a format string and then a list of parameters to fill in the
format specifiers. The format specifier here is “%@” which takes
any Objective-C object and calls descriptionWithLocale
on it, or
description otherwise.
The object that is passed in here could be anything because all the
stringWithFormat
method cares about is that the object provides
at least one of the two methods above. It’s depending on the interface, and
not the concrete class. Let’s imagine a world where this didn’t exist, and
the NSString
method could only be composed of other strings. Suddenly you’d
have something like:
1return [NSString stringWithFormat:@"Object is %s", [object toString]];
That’s not bad at all is it? Well what if there are different objects.
1return [NSString stringWithFormat:@"Object is %s %s %s", [object1 toString],
2 [object2 toS],
3 [object3 stringify]];
Are you starting to see the problem? Suddenly I can’t use this method without being cognizant of the specifics of the object I passed in. The minute one of these interfaces changes I have to change my code. I stole this method from some real code, so let’s look at it with some context.
Once upon a time I was writing a mock object for an iPhone application. Now iPhone doesn’t have a good mock object framework, at least that I’m aware of, so I was rolling my own mock. The mock logged calls to it which I then queried. To construct the string I used this method:
1+(NSString *) createStringFrom: (id) cell at: (CGPoint) point
2 sizeOf: (CGRect) rect
3{
4 return [NSString stringWithFormat:@"%@ %f %f %f %f", cell,
5 point.x,
6 point.y,
7 rect.size.width,
8 rect.size.height];
9}
Don’t sweat the details right now, they’re not important. Instead look at how you
can see the DIP succeeding and
failing in the same code here. The first parameter to
createStringFrom
is a cell object, but it’s of type id, so it
could really be anything.
That’s good because I wasn’t sure when I wrote this mock what type the cell would be and I’d generally prefer that my mock object not have to know the details. In fact the cell did change type several times which is why insulating yourself from change is so important.
There’s an assumption by many developers that you should only worry about the things you’ll be changing in the future, but the best gauge of future changes is present changes, and if you’re changing a module frequently during development as you get it right you’ve found a likely change point.
Even if you haven’t, you’ll make your life simpler in the present by insulating yourself from that change, speeding up your development cycles. I digress.
The rest of this method isn’t so lucky. You see CGPoint
and
CGRect
are C structures, and I am left to write these as floats
in the string (%f). If I was to change the parameter types frequently I would
probably introduce some way to insulate myself from that change as well,
possibly by wrapping them in objects.
Since those parameters have not changed I haven’t done that, although I’m thinking about it.
Our current apprentice Colin has given a first-hand account of refactoring to DIP here as well.
How do I do it?

Eric and I are working on a program to run Conway’s Game of Life. On the iPhone screen you see Rounded Rect Buttons that change color based on whether a cell is alive or dead. The problem is that we don’t really want to drag and drop 300+ tiny buttons on the screen with interface builder.
Instead we want to create them programmatically, when the GameOfLifeViewController
is
loaded. Again I don’t want to overload you with extraneous details, so just take my word
for it that there is a GameOfLifeViewController
, and it needs to generate buttons. Here’s
what my first pass at a test looked like in rough pseudocode:
1for (int row = 0; row < 15; row++)
2{
3 for (int column = 0; column < 15; column++)
4 {
5 button = GetButtonViewAt(row, column)
6 STAssertEquals(expectedSize, button.size)
7 STAssertEquals(expectedLocation, button.location)
8 STAssertAction(expectedAction, button.action)
9 }
10}
There’s a lot wrong with this test. The most obvious is the hard coded 15. What happens when we want to change the number of rows and columns? Now we have to change code in multiple places.
Naturally we did in fact change this, so I would have paid for this decision quickly if I hadn’t already refactored it away.
The second is that there’s going to be more than one test for creation, each of which will have to perform the same 15x15 loop.
The annoyance of constantly changing this will reveal the root the problem,
the GameOfLifeViewController
should really only be in charge of
GameOfLifeView
and really doesn’t need to know the details of
the creation of its subviews. It’s violating the Single Responsibility
Principle.
We can fix that with a factory object, and will do so, but that will violate the Dependency Inversion Principle. So we’ve got one DIP violation, an SRP violation, and a potential second DIP violation, all demonstrated in 6 lines of test code.
Fortunately we’re going to introduce some interfaces to clean that up. The first is an interface to the board object. Why the board?
Well the board should know the number of rows and columns it has, and if we can inject a fake version of the board we can actually set those to be 1 and 1. That’s will make our test focus on what we are truly concerned about.
The second thing we’re going to do is introduce the Abstract Factory pattern to create our button views. It’s a bit of a heavyweight solution but its going to pay off by cleaning up our client code dramatically.
We’ll have a View Controller concerned with controlling the view, and a creation factory concerned with creation, as well as a board that keeps track of rows. Let’s take a look at the test now, again in rough pseudocode.
1-(void) setUp
2{
3 controller = [[GameOfLifeViewController alloc] init];
4 controller.board = [[MockBoard alloc] init];
5 controller.buttonControllerFactory = [[MockButtonFactory alloc] init];
6}
7
8-(void) testCreationOfButtons
9{
10 [controller viewDidLoad];
11 bool called = [controller.board calledWith: params that: I want: true];
12
13 STAssertTrue(called);
14}
So what’s going on here? In the setup we load up the board with a fake board,
one that returns 1 for its rows and columns, and we load up its
buttonControllerFactory
with a fake buttonController
Factory.
In our test we call the viewDidLoad
method, which is called on
controllers after their view is loaded. Duh. That’s the method where we use
the buttonControllerFactory
.
Then we call a method on the mock factory calledWith
: that takes
the parameters I expected the creation factory to receive. Finally we check
that it was called with the assertion. So far I’ve only been showing test
code, because I wanted to demonstrate how much cleaner our tests have become.
Now there’s no loop, no hard coded constants, and no testing the internals of
the creation factory in the view controller. That isn’t to say we don’t test
the creation, we just do that in a different test case, the one that
corresponds to the ConcreteButtonFactory
class.
As a rule if our test code is cleaner, our implementation code is cleaner, and that’s the case here as well.
Let’s now look at the real class, and how to enable Dependency Inversion on it. We have to start with Objective-C protocols. Protocols are very similar to Java interfaces, and just as useful, but are strangely underrepresented in XCode.
As best I can tell just create an NSObject
subclass and remove the .m file and any
imports from the .h
. Here’s the protocol from the unfortunately named
ButtonControllerFactoryProtocol.h
:
1#import "ButtonController.h"
2
3@protocol ButtonControllerFactoryProtocol
4
5-(ButtonController*) createButtonControllerForCell: (id) cell
6 at: (CGPoint) point
7 sizeOf: (CGRect) rect;
8
9@end
As you can see the interface only defines one message,
createButton
ControllerForCell
. It returns the
ButtonController
object, although it could return an object
conforming to a protocol. Indeed one could argue it should, as that would
streamline my mock object. Hmmm…I see a refactoring in my future.
Now let’s look at the class definition for the
ConcreteButtonControllerFactory
, which is the object that is
actually used when the real app is running.
1#import <uikit />
2#import "ButtonController.h"
3#import "ButtonControllerFactoryProtocol.h"
4
5@interface ConcreteButtonControllerFactory :
6 NSObject<buttoncontrollerfactoryprotocol> {
7
8}
9
10@end
Not much here is there. The important part to look at is
NSObject
. ConcreteButtonControllerFactory
inherits
from NSObject
, as all Cocoa objects do, and conforms to the
ButtonControllerFactoryProtocol
.
Like a Java interface this is a contract to later implement
createButtonControllerForCell
in my implementation file and
that’s exactly what I’ve done.
1#import "ConcreteButtonControllerFactory.h"
2
3@implementation ConcreteButtonControllerFactory
4
5-(ButtonController*) createButtonControllerForCell: (id) cell
6 at: (CGPoint) point
7 sizeOf: (CGRect) rect;
8{
9 ButtonController *controller =
10 [[ButtonController alloc] initWithCell:cell];
11
12 UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
13 [button setFrame:rect];
14 [button setCenter:point];
15 [button setImage:[UIImage imageNamed:@"dead_cell.png"]
16 forState:UIControlStateNormal];
17
18 [button addTarget:controller
19 action:@selector(bringToLife:)
20 forControlEvents:UIControlEventTouchUpInside];
21
22 controller.view = button;
23 return controller;
24}
25
26@end
This isn’t an article on UIKit
so I’m not going to get into the details of
creating the button. You can see again that I’ve ignored the DIP for creating
the UIButton
and the ButtonController
.
Since this is a factory I’m okay with this violation. I could have created abstract
factories for the UIButton
and ButtonController
and
passed them in here but I don’t believe I’d gain any benefit from that
implementation.
That’s verified by my testing, as writing tests for the creation of these objects was hard before I introduced this factory but isn’t any longer.
If it becomes difficult then I’ll consider making the change to two factories. Now we need to inject the concrete dependency. In a Java project you could do this in a main method or with a DI framework like Spring. We’re going to be using my favorite DI framework of all time: Interface Builder!
It’s a common misconception that IB is just a GUI builder. What’s great about it is that it doesn’t just generate a bunch of code, but instead “freeze dries” real objects to be instantiated when the program loads the NIB file.
Furthermore while the most common Outlets are UI
elements there’s no reason other objects can’t be used. Let’s take a look at my
NIB document window for the
GameOfLifeViewController
:

As you can see I’ve got objects for the Game,
ConcreteButtonController
Factory, and the Board. That’s because
all three of the objects are injected at runtime, while the code depends on
protocols. To add your own objects to a NIB file simply by selecting it from the Library:
It’s inspector window will have a class drop down, so set this object’s object to your class. Finally you need to connect the outlets to actual outlets in your code. Let’s look at the Outlets tab in IB for my controller (the File’s Owner):
Notice how the controller still thinks of them all as NSObject
?
So if I change the objects it doesn’t care, as long as I conform to the
interface? Finally let’s take a peek at the controller interface file:
1#import "BoardProtocol.h"
2#import "ButtonControllerFactoryProtocol.h"
3#import "GameProtocol.h"
4
5@interface GameOfLifeViewController : UIViewController {
6 IBOutlet NSObject<boardprotocol> *board;
7 IBOutlet NSObject<buttoncontrollerfactoryprotocol> *buttonFactory;
8 IBOutlet NSObject<gameprotocol> *game;
9}
10
11@property(nonatomic, retain) NSObject<boardprotocol> *board;
12@property(nonatomic, retain) NSObject<buttoncontrollerfactoryprotocol> *buttonFactory;
13@property(nonatomic, retain) NSObject<gameprotocol> *game;
See any dependencies on the actual objects? Nope—just protocols. There are properties for the objects so that I can inject the dependencies through the tests, all of which pass in fake versions as various times depending on how it suits the test. It may be unhealthy—but I find this incredibly cool.
Summary
What I love about Interface Builder is setting this up is extremely simple. Writing tests for the controller that is based on these dependencies is also extremely simple, far simpler than just depending on the concrete objects.
It’s funny how developers often complain about the time wasted writing tests or “over-engineering” in this way, but once I broke these dependencies I got things done a lot faster. I’m writing working code without loading the actual simulator.
I write my tests first, making progress, and when I’m done for the session I run the app once or twice just to verify I haven’t done anything like forgotten to inject the dependency.
Compare that to running the simulator constantly, each time hoping your code is functional. Who’s wasting their time now?