There’s a lot that I want to say about composition and inheritance, but Sandi Metz covers the basics better than I can in Nothing is Something. So, since she already covered why inheritance will fail you, I will explore a few techniques we can use to avoid it.

Interior Decorating

Let’s imagine a new networking library. Network requests are defined by template objects that conform to a protocol:

@protocol SKRequestTemplate

@property (readonly) NSURL *baseURL;

@optional  
@property (readonly) NSString *method;  
@property (readonly) NSString *path;  
@property (readonly) NSDictionary *parameters;  
@property (readonly) NSDictionary *headers;

@end  

With this design, we’re given a lot of flexibilty in how we define our request templates, and we can rely on some other component to convert each template into an NSURLRequest, and that request can be fired by some other uninteresting machinery. To create the request, we need to grab each property from the template in turn.

//...  
mutableURLRequest.HTTPMethod = [template method]  
//...  

When we go to use these templates however, we notice that we can’t have any default behavior. Since it’s using a protocol and not inheritance, we can’t use the superclass to set the default method to GET. We can avoid this with a nil-coalescer:

//...  
mutableURLRequest.HTTPMethod = [template method] ?: @"GET";  
//...  

We run this code and realize that we have an even bigger problem. If there’s no implementation defined for -method, our template is going to blow up! We can do something ugly like:

//...  
mutableURLRequest.HTTPMethod = [template respondsToSelector:@selector(method)] ? [template method] : @"GET";  
//...  

But this is inelegant and we wish we could just force our users to subclass something so that we can hide this behavior away. But don’t fret! We have options outside of inheritance. To add behavior in a composition-friendly way, we use the Decorator pattern. Let’s define something called a SafeTemplate:

@interface SKSafeRequestTemplate : NSObject

- (instancetype)initWithUnsafeTemplate:(id)unsafeTemplate;

@property (nonatomic, readonly) id unsafeTemplate;

@property (readonly) NSURL *baseURL;

@property (readonly) NSString *method;  
@property (readonly) NSString *path;  
@property (readonly) NSDictionary *parameters;  
@property (readonly) NSDictionary *headers;

@end  

We can now pass our “unsafeTemplate” into this object, and for each property, it wraps the execution in a check, and can return any default we choose:

- (NSString *)method {  
	if ([self.unsafeTemplate respondsToSelector:@selector(method)]) {  
		return [self.unsafeTemplate method];  
	}  
	return @"GET";  
}  

//...  
URLRequest.HTTPMethod = [safeTemplate method];  
//...  

A particularly elegant note on this solution: the wrapper itself doesn’t conform to SKRequestTemplate, even though its parameter does. This means that if we add a new method to the protocol and try to use it from the safe template, the compiler will groan at us. It must be defined on the safe template before we can use it, and we’ll be reminded to add it there as well. Normally, with inheritance, your “contract” with the outside world includes all of your superclass’s methods; with decoration, you only have to provide what you say you’ll provide. Aaron Patterson documents a case where the rails/core team got bitten by this exact problem.

The Presenter pattern that I outline in 8 Patterns to Help You Destroy Massive View Controller is a more specific version of this technique. Value Objects are also really just a decorator around something like a string or a number.

And that’s the Decorator pattern. It’s very flexible, very useful, and a great weapon in the war on inheritance.

Strategery

One awesome thing that Sandi said is “There’s no such thing as one specialization. If you’re specializing something, you have two things.” This was a revelation for me.

Let’s continue to work with our networking library. Using the data source pattern from 8 Patterns to Help You Destroy Massive View Controller, let’s make an object called SKRemoteDataSource, which fetches a collection of objects from an API for display in table view.

@interface SKRemoteDataSource : NSObject

@property (nonatomic, weak) id delegate;

@property (readonly) NSUInteger numberOfSections;  
- (NSUInteger) numberOfObjectsInSection:(NSUInteger)section;  
- (id) objectAtIndexPath:(NSIndexPath*)indexPath;

- (void)fetchData;

@property (nonatomic) NSURL *URL;  
@property (nonatomic) NSDictionary *queryParameters;  
@property (nonatomic) NSString *keyPath;

@end  

This is a very useful class, but sometimes the remote objects are paginated. So we could subclass SKRemoteDataSource and make SKPaginatedDataSource. Hey, pagination is just a special case of a remote data source, right?

@interface SKPaginatedDataSource : SKRemoteDataSource

@property (nonatomic, readonly) NSInteger currentPage;  
@property (nonatomic, readonly) NSInteger numberOfPages;  
@property (nonatomic, readonly) BOOL hasMorePages;

- (void)fetchNextPage;

@end  

While this seems reasonable, every change you make to the superclass will break the subclass. I can tell you this because I’ve written this exact code in this exact way before.

What I had was a bad version of the Template Method pattern. To implement the template method properly, you need to:

  1. create a superclass with all common behavior
  2. throw an exception from the superclass for all differing behavior
  3. and make your two subclasses (because you can never have one specialization!) and override the points of difference

Even properly implemented, however, the Template Method pattern is probably an anti-pattern. It’s based on inheritance which will always strongly couple your components together. Fortunately, we have an alternative, which is based on composition.

We have two responsibilities here: downloading an array of items from an API, and presenting them as a data source. These two responsbilities have been tightly coupled together. Extracting the shared core will make simpler objects that can be used more often. When we wrap behavior in an object and inject it into other objects, it’s known as the Strategy pattern.

The final solution was SKCollectionFetcher, which downloaded a collection of objects from an API. The paginated and regular remote data sources each had a collection fetcher, and the logic was no longer duplicated.

@interface SKCollectionFetcher : NSObject

@property (nonatomic, strong) NSURL *URL;  
@property (nonatomic, strong) NSDictionary *queryParameters;  
@property (nonatomic, strong) NSString *keyPath;

- (void)fetchCollectionWithSuccessBlock:(void (^)(NSArray *objects))successBlock failureBlock:(void (^)(NSError *error))failureBlock;  
- (void)cancelCurrentFetch;

@end

@interface SKRemoteDataSource : NSObject

@property (nonatomic, weak) id delegate;

@property (nonatomic, assign, readonly) NSUInteger numberOfSections;  
- (NSUInteger) numberOfObjectsInSection:(NSUInteger)section;  
- (id) objectAtIndexPath:(NSIndexPath*)indexPath;

- (void)fetchData;

@property (nonatomic, strong) SKCollectionFetcher *collectionFetcher;

@end  

Since the data source and the collection fetcher are now separated, we can swap them out at will. In some cases, we’ll need a slightly different collection fetcher, and that will work with our remote data source. In other cases, the reverse will be true, and we’ll need a slightly different data source. For example, if we need relative pagination, which is based on timestamps, we can write a new data source while using the old collection fetcher. Writing code with composition makes this sort of flexibilty possible.