September 30, 2014

8 Patterns to Help You Destroy Massive View Controller

View controllers become gargantuan because they're doing too many things. Keyboard management, user input, data transformation, view allocation — which of these is really the purview of the view controller? Which should be delegated to other objects? In this post, we'll explore isolating each of these responsiblities into its own object. This will help us sequester bits of complex code, and make our code more readable.

In a view controller, these responsibilities might be grouped into #pragma mark sections. When that happens, it's usually time to start thinking about breaking it apart into smaller components.

Data Source

The Data Source Pattern is a way of isolating the logic around which objects live behind what index paths. Particularly in complicated table views, it can be useful to remove all of the logic of "Which cells are visible under these conditions?" from your view controller. If you've ever written a table view where you're constantly comparing integers of rows and sections, a data source object is for you.

Data source objects can literally conform to the UITableViewDataSource protocol, but I've found that configuring cells with those objects is a different role than managing index paths, so I like to keep these two objects separate.

A simple example of a data source might handle sectioning logic for you.

@implementation SKSectionedDataSource : NSObject

- (instancetype)initWithObjects:(NSArray *)objects sectioningKey:(NSString *)sectioningKey {
    self = [super init];
    if (!self) return nil;

    [self sectionObjects:objects withKey:sectioningKey];

    return self;
}

- (void)sectionObjects:(NSArray *)objects withKey:(NSString *)sectioningKey {
    self.sectionedObjects = //section the objects array
}

- (NSUInteger)numberOfSections {
    return self.sectionedObjects.count;
}

- (NSUInteger)numberOfObjectsInSection:(NSUInteger)section {
    return [self.sectionedObjects[section] count];
}

- (id)objectAtIndexPath:(NSIndexPath *)indexPath {
    return self.sectionedObjects[indexPath.section][indexPath.row];
}

@end

While this data source is designed to be abstract and reusable, don't be afraid to make a data source that's used in only one place in your app. Separating index path management logic from your view controller is a noble goal in itself. Especially for highly dynamic table views, it's good to have an object that notifies the view controller with messages like "Hey, I have a new object at this index path"; the view controller can then pass that along to the table view in the form of an animation.

This pattern can also encapsulate your retrieval logic. A remote data source can fetch a collection of objects from an API. UIViewController is a UI object, and this is a great way to get networking code out of your view controller.

If the interface to all your data sources is stable (with a protocol for example), you can write a special data source that is composed of an arbitrary number of other data sources. Each sub-data-source becomes its own section in the multi data source. Using this logic to combine data sources is a great way to avoid having to write dreadful index comparison code. The data source will manage it all for you!

Standard Composition

View controllers can be composed using the View Controller Containment APIs introduced in iOS 5. If your view controller is composed of several logical units that could each be their own view controller, consider using Composition to break them apart. A practical application of this litmus test is a screen with multiple table views or collection views.

On a screen with a header and a grid view, we could lazy load our two view controllers, and lay them out properly when prompted by the system.

- (SKHeaderViewController *)headerViewController {
    if (!_headerViewController) {
        SKHeaderViewController *headerViewController = [[SKHeaderViewController alloc] init];

        [self addChildViewController:headerViewController];
        [headerViewController didMoveToParentViewController:self];

        [self.view addSubview:headerViewController.view];

        self.headerViewController = headerViewController;
    }
    return _headerViewController;
}

- (SKGridViewController *)gridViewController {
    if (!_gridViewController) {
        SKGridViewController *gridViewController = [[SKGridViewController alloc] init];

        [self addChildViewController:gridViewController];
        [gridViewController didMoveToParentViewController:self];

        [self.view addSubview:gridViewController.view];

        self.gridViewController = gridViewController;
    }
    return _gridViewController;
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    CGRect workingRect = self.view.bounds;

    CGRect headerRect = CGRectZero, gridRect = CGRectZero;
    CGRectDivide(workingRect, &headerRect, &gridRect, 44, CGRectMinYEdge);

    self.headerViewController.view.frame = tagHeaderRect;
    self.gridViewController.view.frame = hotSongsGridRect;
}

The resulting sub-view controllers, each with their own collection view, handle one uniform type of data. They are much smaller and easier to understand and change because of it.

Smarter Views

If you're allocating all of your view controller's subviews inside of the view controller's class, you may consider using a Smarter View. UIViewController defaults to using UIView for it's view property, but you can override it with your own view. You can use -loadView as the access point for this, as long as you set self.view in that method.

@implementation SKProfileViewController

- (void)loadView {
    self.view = [SKProfileView new];
}

//...

@end

@implementation SKProfileView : NSObject

- (UILabel *)nameLabel {
    if (!_nameLabel) {
        UILabel *nameLabel = [UILabel new];
        //configure font, color, etc
        [self addSubview:nameLabel];
        self.nameLabel = nameLabel;
    }
    return _nameLabel;
}

- (UIImageView *)avatarImageView {
    if (!_avatarImageView) {
        UIImageView * avatarImageView = [UIImageView new];
        [self addSubview:avatarImageView];
        self.avatarImageView = avatarImageView;
    }
    return _avatarImageView
}

- (void)layoutSubviews {
    //perform layout
}

@end

You can simply redeclare @property (nonatomic) SKProfileView *view, and because it is a more specific type than UIView, the analyzer will do the right thing and assume self.view is an SKProfileView.

Presenter

The Presenter Pattern wraps a model object, transforms its properties for display, and exposes messages for those transformed properties. It is also known in other contexts as Presentation Model, the Exhibit pattern, and ViewModel.

@implementation SKUserPresenter : NSObject

- (instancetype)initWithUser:(SKUser *)user {
    self = [super init];
    if (!self) return nil;
    _user = user;
    return self;
}

- (NSString *)name {
    return self.user.name;
}

- (NSString *)followerCountString {
    if (self.user.followerCount == 0) {
        return @"";
    }
    return [NSString stringWithFormat:@"%@ followers", [NSNumberFormatter localizedStringFromNumber:@(_user.followerCount) numberStyle:NSNumberFormatterDecimalStyle]];
}

- (NSString *)followersString {
    NSMutableString *followersString = [@"Followed by " mutableCopy];
    [followersString appendString:[self.class.arrayFormatter stringFromArray:[self.user.topFollowers valueForKey:@"name"]];
    return followersString;
}

+ (TTTArrayFormatter*) arrayFormatter {
    static TTTArrayFormatter *_arrayFormatter;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _arrayFormatter = [[TTTArrayFormatter alloc] init];
        _arrayFormatter.usesAbbreviatedConjunction = YES;
    });
    return _arrayFormatter;
}

@end

Crucially, the model object itself is not expoosed. The Presenter serves as the gatekeeper to the model. This ensures that the view controller can't sidestep the presenter and directly access the model. Architecture like this limits your dependency graph, and since the SKUser model touches fewer classes, changing it will causes fewer effects in your app.

Binding pattern

In method form, this might be called -configureView. The Binding Pattern updates a view with model data as it changes. Cocoa is a natural place to use this because KVO can observe the model, and KVC can read from the model and "write" to the view. Cocoa Bindings are the AppKit version of this pattern. Third-party libraries like Reactive Cocoa are also effective for this pattern, but may be overkill.

This pattern works really well in conjunction with the Presenter Pattern, using one object to transform values, and another to apply them to your view.

@implementation SKProfileBinding : NSObject

- (instancetype)initWithView:(SKProfileView *)view presenter:(SKUserPresenter *)presenter {
    self = [super init];
    if (!self) return nil;
    _view = view;
    _presenter = presenter;
    return self;
}

- (NSDictionary *)bindings {
    return @{
              @"name": @"nameLabel.text",
              @"followerCountString": @"followerCountLabel.text",
            };
}

- (void)updateView {
    [self.bindings enumerateKeysAndObjectsUsingBlock:^(id presenterKeyPath, id viewKeyPath, BOOL *stop) {
        id newValue = [self.presenter valueForKeyPath:presenterKeyPath];
        [self.view setObject:newvalue forKeyPath:viewKeyPath];
    }];
}

@end

(Note that our simple presenter from above isn't necessarily KVO-able, but it could be made to be so.)

As with all of these patterns, you don't have to figure out the perfect abstraction on your first attempt. Don't be afraid to make an object that is only usable in one specific case. The goal is not to eliminate code reuse, it's to simplify our classes so that they're easier to maneuver through and understand.

Interaction pattern

The ease of typing actionSheet.delegate = self is part of the reason that view controllers become too big to fail. In Smaltalk, the entire role of the Controller object was for accepting user input and updating the views and models. Interactions today are more complex, and they cause bulky code in the view controller.

Interactions often include an initial user input (like a button press), optional additional user input ("Are you sure you want to X?"), and then some activity, like a network request or state change. The entire lifecycle of that operation can be wrapped up inside the Interaction Object. The example below creates the interaction object when the button is tapped, but adding the Interaction Object as the target of an action, like [button addTarget:self.followUserInteraction action:@selector(follow)] is also good.

@implementation SKProfileViewController

- (void)followButtonTapped:(id)sender {
    self.followUserInteraction = [[SKFollowUserInteraction alloc] initWithUserToFollow:self.user delegate:self];
    [self.followUserInteraction follow];
}

- (void)interactionCompleted:(SKFollowUserInteraction *)interaction {
    [self.binding updateView];
}

//...

@end

@implementation SKFollowUserInteraction : NSObject <UIAlertViewDelegate>

- (instancetype)initWithUserToFollow:user delegate:(id<InteractionDelegate>)delegate {
    self = [super init];
    if !(self) return nil;
    _user = user;
    _delegate = delegate;
    return self;
}

- (void)follow {
    [[[UIAlertView alloc] initWithTitle:nil
                                message:@"Are you sure you want to follow this user?"
                               delegate:self
                      cancelButtonTitle:@"Cancel"
                      otherButtonTitles:@"Follow", nil] show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if  ([alertView buttonTitleAtIndex:buttonIndex] isEqual:@"Follow"]) {
        [self.user.APIGateway followWithCompletionBlock:^{
            [self.delegate interactionCompleted:self];
        }];
    }
}

@end

The old style of alert view and action sheet delegates make this pattern more apparent, but it works just as well with the new iOS 8 UIAlertController APIs.

Keyboard Manager

Updating the view after the keyboard state changes is another concern that is classically stuck in the view controller, but this responsibility can easily be shifted in a Keyboard Manager. There are implementations of this pattern designed to work in every case, but again, if that's overkill, don't be afraid to write your own quick version of this.

@implementation SKNewPostKeyboardManager : NSObject

- (instancetype)initWithTableView:(UITableView *)tableView {
    self = [super init];
    if (!self) return nil;
    _tableView = tableView;
    return self;
}

- (void)beginObservingKeyboard {
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}

- (void)endObservingKeyboard {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)note {
    CGRect keyboardRect = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0f, CGRectGetHeight(keyboardRect), 0.0f);
    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
}

- (void)keyboardDidHide:(NSNotification *)note {
    UIEdgeInsets contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0f, self.oldBottomContentInset, 0.0f);
    self.tableView.contentInset = contentInset;
    self.tableView.scrollIndicatorInsets = contentInset;
}

@end

You can call -beginObservingKeyboard and -endObservingKeyboard from -viewDidAppear and -viewWillDisappear or wherever's appropriate.

Navigator

Navigating from screen to screen is normally done with a call to -pushViewController:animated:. As these transitions get more complicated, you can delegate this task to a Navigator object. Especially in a universal iPhone/iPad app, navigation needs to change depending on what size class your app is currently running in.

@protocol SKUserNavigator <NSObject>

- (void)navigateToFollowersForUser:(SKUser *)user;

@end

@implementation SKiPhoneUserNavigator : NSObject<SKUserNavigator>

- (instancetype)initWithNavigationController:(UINavigationController *)navigationController {
    self = [super init];
    if (!self) return nil;
    _navigationController = navigationController;
    return self;
}

- (void)navigateToFollowersForUser:(SKUser *)user {
    SKFollowerListViewController *followerList = [[SKFollowerListViewController alloc] initWithUser:user];
    [self.navigationController pushViewController:followerList animated:YES];
}

@end

@implementation SKiPadUserNavigator : NSObject<SKUserNavigator>

- (instancetype)initWithUserViewController:(SKUserViewController *)userViewController {
    self = [super init];
    if (!self) return nil;
    _userViewController = userViewController;
    return self;
}

- (void)navigateToFollowersForUser:(SKUser *)user {
    SKFollowerListViewController *followerList = [[SKFollowerListViewController alloc] initWithUser:user];
    self.userViewController.supplementalViewController = followerList;
}

This highlights one of the benefits to using lots of small objects instead of one big object. They can be changed, rewritten, and replaced very quickly. Instead of shameful conditional code all over your view controller, you can just set self.navigator to [SKiPadUserNavigator new] when on the iPad, and it will respond to the same -navigateToFollowersForUser: method. Tell, don't ask!

Wrapping up

Historically, Apple's SDKs only contain the bare minimum of components, and those APIs push you towards Massive View Controller. By tracking down the responsibilities of your view controllers, separating the abstractions out, and creating true single-responsibility objects, we can begin to reign those gnarly classes in and make them managable again.

September 19, 2014

Anatomy of a Feature: Push Notifications

Sites like Stack Overflow naturally fall into the groove of giving quick answers to common problems. Take, for example, this question, with answers containing code snippets removed from any method, or worse, answers with code injected right into the app delegate. This code shows you how to do the thing you’re trying to do, but doesn’t show you the bigger picture. Where does this stuff go? How does it talk to other components?

In this post, I hope to describe how a common subsystem of an app, such as push notifications, might be architected. It’s an object-oriented architecture, and we will talk about interfaces more and implementations less.

Our requirements are pretty straightforward:

  • Handle token registration
  • Forward push notifications recieved while backgrounded to a router object, so that the app can configure its screens properly
  • Show a toast notification for notifications received while the app is foregrounded
  • Allow any object (such as a conversation view controller) to supress the toast notification
  • Allow any object to be informed when a push notification is received, so it can execute any releveant code, such as animating in new messages

The App Delegate

Ah, my old nemesis, the app delegate. Apple uses this pattern as a central point to get information into our app. Notably, methods like - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken encourage developers to put the code right into the app delegate, quickly bloating it. We should dispatch to another object immediately. This will separate our intent from our implementation, and make the resulting code easier to read.

The Push Center

We need a central object to store state (such as which objects want to be able to suppress notifications) and to make decisions about how to handle push notifications. That object, RGPushCenter, will be a singleton. Singletons are bad, and if our object were only accessed from the app delegate, it could easily just be a property on the app delegate. However, it also needs to be accessed from elsewhere in the app (other objects need to tell it to suppress notifications), so global access is required.

There are a few things we can do to mitigate the damage a singleton can do. Primarily, our singleton will have only one point of access, which is the +sharedCenter class method. Having lots of class methods makes it hard to have state in your object, which makes it hard to refactor.

The push center is the home for code like push notification registration. If you’re tempted to just leave this code (it’s only one line!) in the app delegate, consider the complexity that might be added. For example, while I was writing this code, I learned that iOS 8 handles push notification registration differently. Because the code was hidden in the push center, I was able to easily change it, leaving the app delegate none the wiser.

- (void)registerForRemoteNotifications {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
    {
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    }
    else
#endif
    {
        UIRemoteNotificationType types = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
    }
}

This way, the code behaves correctly for iOS 7 and 8, in Xcodes 5 and 6. Adding this to the app delegate would only serve to confuse the reader (“What is this #define for?”, “What happened in iOS 8?”, etc). Hiding things at the right level of abstraction makes it easier to understand then code when you read it later.

We should always be dispatching immediately to our push center object, like so:

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
    [[RGPushCenter sharedCenter] didRegisterForRemoteNotificationsWithToken:deviceToken];
}

Inside this method, we have to convert our NSData object to an NSString, and then register it to the API. You might be tempted to use a C function to convert the data to a string, but let’s initialize a special object for it.

The Push Token

RGPushToken *pushToken = [[RGPushToken alloc] initWithTokenData:token];

It might seem like overkill to allocate memory for a whole object for our push token, but allocation is pretty cheap, all things considered. Further, once we have an object, it’s very easy to add a simple message like [pushToken registerWithAPI] to perform the API call to the server. The RGPushToken class now nicely encapsulates the NSData to NSString conversion as well as the network request, leaving the push center dumber and better off for it.

Inside the push token class, we can make a one line call to our HTTP session manager:

- (void)registerWithGeniusAPI {
    [[RGAPI manager] POST:@"/account/devices" parameters:self.POSTParameters success:nil failure:nil];
}

Because this is its own class, the -POSTparameters can be wrapped up into their own method as well. At each layer of abstraction, we push down the complexity into another abstraction until the thing is so simple that it can be understood by glancing at it.

The Push Notification

In some cases, we don’t want to dispatch immediately to the push center, but make a decision first. When receiving a push notification when the app is running, we need to make a decision based on whether or not it’s backgrounded.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    if (application.applicationState == UIApplicationStateActive) {
        [[RGPushCenter sharedCenter] presentToastWithUserInfo:userInfo];
    } else {
        [[RGPushCenter sharedCenter] performRoutingForNotificationWithUserInfo:userInfo];
    }
}

This is the right place for this decision for a number of reasons. We don’t want the push center to have to know about different ways that the same data comes in; in fact, if it were up to me, this would probably be two delegate methods. We also already have access to the application object, and we can quickly query it’s state to send more intelligible messages to the push center, leaving it much cleaner.

What do we do with the notification dictionary once it comes into our push center? If you guessed “make an object!”, you’d be correct.

RGPushNotification *notification = [[RGPushNotification alloc] initWithDictionary:userInfo];

Object-oriented programming is all about encapsulation. What are we encapsulating here? Whether or not the push notification is silent, the type of notification (“new message!”, “update the unread count!”), and where the app should go when the notification is activated, which is stored in the routing URL. This also gives us the flexiblity to transform or expose more as needed in the future, and localize those changes to only this class. Once we have our notification object, we can grab its routing URL and pass it a router object that handles configuring our view controllers:

[[RGNavigationManager sharedManager] handleOpenURL:notification.routingURL];

This code could access the raw data from the userInfo dictionary, but we’d end up with stringly-typed NSURL conversion in our push center. [NSURL urlWithString:userInfo[@"genius"][@"url"]] is a lot less elegant and truthfully, we just don’t care where the URL string is or how it’s converted into an NSURL. Offload that responsibility to another class!

The Delegates

The only complex component remaining is the preventing the toast from being shown if any other objects wish to suppress it. We need to be able to ask other objects that care whether they want to prevent the toast from happening, but we don’t want to be too tightly coupled to the other objects. Of the common communication patterns, most of them (NSNotifications, KVO, target-action) can’t return data. Blocks are an interesting solution, but would require some kind of complex token-based system to deregister a block, so we will use delegates for simplicity.

Having just one delegate can be dangerous with a singleton, since another object can be take away your delegateness at any point without telling you. For safety’s sake, let’s keep multiple delegates. Order doesn’t matter, so we can use a set-like construct, but we want to it to hold a weak (not strong or unsafe) reference to each of the items in it. Forunately, the Foundation SDK gives us [NSHashTable weakObjectsHashTable], which is essentially a set with weak references, exactly what we’re interested in.

From there, we need a way to register and deregister objects as delegates.

- (void)addDelegate:(id<RGPushCenterDelegate>)delegate;
- (void)removeDelegate:(id<RGPushCenterDelegate>)delegate;

We can now write a method to check if any of the delegates want to suppress the notification.

- (BOOL)shouldSuppressNotification:(RGPushNotification *)notification {
    for (id<RGPushCenterDelegate> delegate in self.delegates) {
        if ([delegate pushCenter:self shouldSuppressNotification:notification]) {
            return YES;
        }
    }
    return NO;
}

Finally, we’ll create an NSNotification called RGPushNotificationWasReceived, which observers can listen to and perform their own actions. We already have delegates, why include a separate communication pattern here? The reason is simple. We want to keep the concept of suppressing a notification separate and decoupled from the concept of listening for notifications. Some objects will just need to know that a notification is recieved (such as the conversation list, which needs to update, but not suppress the toast). Notifications also don’t really require any knowledge of the push center class, only the push notification object, which is another reason to keep them separate.

This writeup doesn’t provide code that you can copy and paste into your own project, but it’s not particularly complex either (the actual push center is only 130 lines of code). I hope that it provides you with a framework for thinking about how to architect features like this in future.

May 26, 2014

Smalltalky Control Structures

I’m reading Kent Beck’s Smalltalk Best Practice Patterns and learning a lot about how control structures work in what’s probably the purest object-oriented language. For example, if isn’t used to manage conditionals. In Smalltalk, since all things are objects, including booleans, you can just send the message -ifTrue: and -ifFalse:, with blocks, to the True object.

Let’s try that out with Objective-C:

@implementation NSNumber (IfTrue)

- (BOOL)isBoolean {
    return [@([self objCType]) isEqualToString:@(@encode(BOOL))];
}

- (id)ifTrue:(void (^)())onTrue {
    if ([self isBoolean]) {
        if ([self boolValue]) {
            if (onTrue) onTrue();
        } else {
            return self;
        }
    }
    return nil;
}

- (id)ifFalse:(void (^)())onFalse {
    if ([self isBoolean]) {
        if ([self boolValue]) {
            return self;
        } else {
            if (onFalse) onFalse();
        }
    }
    return nil;
}

@end

When the case is not satisfied (i.e., the NSNumber is @YES, but we messaged -ifFalse:), we return self, so that the messages can be chained, like so:

[[@YES ifTrue:^{
    NSLog(@"this code block is entered!");
}] ifFalse:^{
    NSLog(@"this one is not");
}];

Pretty elegant! Smalltalk also allows us to ask an object to execute block if it’s nil. Hm. This actually presents a problem for us, since nil in Objective-C eats all messages and returns nil again. Our message would be swallowed and our block wouldn’t get executed. Fortunately, the runtime is here to save us! Let’s #import <objc/runtime.h>. Grab the whiskey.

Bill Bumgarner teaches us how to create our own nil object and tell the runtime that we’d like to use it instead of the built in nil. First, let’s make STNil. It eats all messages, just like good old regular nil:

@implementation STNil

+ (BOOL)resolveClassMethod:(SEL)sel { return NO; }

+ (BOOL)resolveInstanceMethod:(SEL)sel { return NO; }

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [NSObject instanceMethodSignatureForSelector: @selector(description)];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation { }

- (void)ifNil:(void (^)())onNil {
    if (onNil) onNil();
}

@end

And let’s add the -ifNil: message to NSObject as a category and make it a no-op:

@implementation NSObject (IfNil)

- (void)ifNil:(void (^)())onNil { }

@end

And then lets use _objc_setNilReceiver (which is private!) to set STNil as the nil receiver;

extern id _objc_setNilReceiver(id newNilReceiver);

int main(int argc, const char **argv)
{
    @autoreleasepool {
        id smalltalkyNil = [STNil new];
        _objc_setNilReceiver(smalltalkyNil);

        NSString *nilString = nil;

        [nilString ifNil:^{
            NSLog(@"this object is nil");
        }];


        _objc_setNilReceiver(nil);

    }
    return 0;
}

This works! We can now message nil as easily as any other object.

Let’s take it even further. In Ruby on Rails, objects support something called presence. Presence makes truthiness behave in a more useful and consistent way. Nil, empty strings, and empty collections are “not present” (or “blank”), so you can call myArray.blank instead of the more convoluted myArray.count == 0. Let’s bring that stuff over to this new block based model as well.

Let’s put some more stuff on NSObject:

@implementation NSObject (Presence)

- (BOOL)present {
    return YES;
}

- (BOOL)blank {
    return !self.present;
}

- (void)ifPresent:(void (^)())onPresent {
    if (self.present && onPresent) onPresent();
}

- (void)ifBlank:(void (^)())onBlank {
    if (self.blank && onBlank) onBlank();
}

@end

And then, all we have to do create a category on NSArray that overrides present (and optionally forward -ifEmpty: to -ifBlank:):

@implementation NSArray (Presence)

- (BOOL)present {
    return !!self.count;
}

- (void)ifEmpty:(void (^)())onEmpty {
    [self ifBlank:onEmpty];
}

@end

Now, we can call -ifEmpty: exactly as we’d expect to:

[@[] ifEmpty:^{
    NSLog(@"this array is empty!");
}];

Who knew Smalltalk could be so much fun?

May 16, 2014

Cells

Cells can exist because their membranes define what is in and out and determine what can pass.

Love this analogy of objects from Domain-Driven Design.

May 16, 2014

Replace Enumerations with Types

In the last post, we talked about wrapping simple Foundation types in their own class, so that the type checker can let you know that you’re passing the wrong kind of string to a method. We can extend this idea of value objects further.

I’m quickly falling in love with this pattern: replacing enumerations with polymorphic objects. In the last post, it was important to wrap a value, but here, there’s no value, just a kind. Normally, to represent a kind of thing, we create an enumeration, which is just an integer with a little bit of type sugar.

Where do enumerations fall short? Let’s look at some terrible code I wrote for an old app.

+ (NSString*) stringForType:(PodcastListType)listType {
    if (listType == unplayedType) {
        return @"Unplayed";
    } else if (listType == favoriteType) {
        return @"Favorites";
    } else if (listType == archiveType) {
        return @"Archive";
    } else if (listType == trashType) {
        return @"Trash";
    } else if (listType == downloadsType) {
        return @"Downloads";
    } else if (listType == recentlyAddedType) {
        return @"Recents";
    }
    return @"";
}

+ (PodcastListType) listTypeForString:(NSString*)name {
    if ([name isEqualToString:@"Unplayed"]) {
        return unplayedType;
    } else if ([name isEqualToString:@"Favorites"]) {
        return favoriteType;
    } else if ([name isEqualToString:@"Archive"]) {
        return archiveType;
    } else if ([name isEqualToString:@"Downloaded"]) {
        return downloadsType;
    } else if ([name isEqualToString:@"Recently Posted"]) {
        return recentlyAddedType;
    }
    return unplayedType;
}

This code is bad for several reasons.

  1. The enumeration can’t be messaged, so any code or behavior that should live with the enumeration now hangs out wherever the code needs to be used.
  2. Everything in iOS revolves around the view controller, so the “easy” place to put this code is in a class method on the view controller (which is what I did!). This makes your view controller longer and cruftier. The reader of the view controller class doesn’t care how list types are converted into display strings.
  3. It’s not immediately obvious if cases aren’t covered, especially as the number of cases increases. The astute reader will note that +listTypeForString: doesn’t include the “Trash” case, which was an actual mistake I made writing this code. (Creating C functions can be a solution to the view controller problem, but the cases are still easy to miss.)
  4. I can call [MyClass stringForType:2] with no compiler warning. The compiler will warn if I send a different typedef, but not if I send a plain old integer.

It’s not called Enumerative-C! Let’s make some objects.

SKPodcastListType.h:

@interface SKPodcastListType : NSObject <NSCopying>

- (instancetype)initWithString:(NSString*)string; //probably from the server

@property (nonatomic, readonly) NSString *displayName;

@end

@interface SKUnplayedPodcastListType : SKPodcastListType @end

@interface SKFavoritesPodcastListType : SKPodcastListType @end

//...

And SKPodcastListType.m:

@implementation SKPodcastListType

- (instancetype)initWithString:(NSString *)string {
    if ([string isEqualToString:@"unplayed"]) {
        self = [SKUnplayedPodcastListType new];
    } else if ([string isEqualToString:@"favorites"]) {
        self = [SKFavoritesPodcastListType new];
    } else {
        self = nil;
    }
    return self;
}

- (NSString *)displayName {
    return @"";
}

- (NSUInteger)hash {
    return [NSStringFromClass(self.class) hash];
}

- (BOOL)isEqual:(id)object {
    return [self isMemberOfClass:[object class]];
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

@end

@implementation SKUnplayedPodcastListType

- (NSString *)displayName {
    return @"Unplayed";
}

@end

@implementation SKFavoritesPodcastListType

- (NSString *)displayName {
    return @"Favorites";
}

@end

//...

Now, while this is more lines of code, the code is now out of the way. It now lives in the right place. My view controller no longer knows the possible types of podcast lists and is shorter and simpler for it. Any additional behavior can be put right on these classes, instead of adding more class methods, and if you make a new PodcastListType, it’ll be immediately obvious if you haven’t implemented the right methods.

The compiler will also now check our work to make sure we’re passing around SKPodcastListType objects, instead of accidentally passing around numbers for enumerations.

Note that it doesn’t matter which SKUnplayedPodcastListType object you have. It doesn’t hold any data except for its type. This means our -isEqual: method just checks to make sure the classes are the same. And -copyWithZone: can just return itself, since it’s immutable, which feels very elegant. You can get even more crazy and make each subtype be its own singleton, so you could just compare firstListType == secondListType. You could metaprogram the -displayName message to take the class name and remove the “SK” and the “PodcastListType”. The possibilities are limitless.

May 15, 2014

The Value of Value Objects

Value Objects are my new favorite thing. We’re all familiar with Entities. Entities are objects that have an important sense of identity. Like entities, value objects also live in the model layer, but, unlike entities, they don’t have that same sense of identity. A very practical way of looking at it is that value objects don’t get their own row in a database, they usually get represented in a single field of some other object’s row.

Why are value objects so awesome? Two big reasons: first, they have a distinct type; and second, they can give a home to behavior that doesn’t otherwise have a place. Let’s go in a little deeper.

Types

In my last blog post, Tests and Types, I talk about how useful it is to have the computer checking that the right objects are going to the right places. This is a simple extension of that. Darren Hobbs calls it Tiny Types, and it’s a simple class that lets you wrap some existing type (usually a Foundation type like NSString or NSDate) in a class that has its own type. That way, you can never put a FirstName object into a slot for a LastName type.

I made a quick gist with an implementation for Objective-C that implements -isEqual:, -description, -compare:, -hash, and NSCopying, which you can find here: https://gist.github.com/khanlou/170cb132c90c86f68e72. From, there, it’s trivial to make subclasses for your value objects. For example:

SKFirstName.h:

@interface SKFirstName : SKValueObject

- (instancetype)initWithString:(NSString*)firstName;

@property (nonatomic, readonly) NSString *firstName;

@end

SKFirstName.m:

@implementation SKFirstName

- (instancetype)initWithString:(NSString *)firstName {
    return [self initWithBackingObject:firstName];
}

- (NSString *)firstName {
    return self.backingObject;
}

@end

That’s all the code you need for a new tiny type! Now a FirstName object will never accidentally go into the slot made for a ServerHostname.

Behavior

The other great thing is that behavior around this name now has a great home. Instead of doing validation on the Person entity, we can just add it as a method here, optionally returning nil in the initializer if we get malformed input.

- (BOOL)isValid {
    return [self.firstName matchesRegex:@"^[A-Z][a-zA-Z]+$"]; //this is a terrible regex for a name
}

Coupling behavior with state is the whole point of Object-Oriented Programming!

- (NSString *)slug {
    return [self.firstName lowercaseString]; //probably also want to convert spaces and apostrophes to hyphens
}

In the next post, I’ll talk about how we can use the same concept to make way better enumerations.

April 14, 2014

Tests and Types

The programs we write are complex beasts. Even the smallest changes can have ripple effects into unexpected parts of our apps. And of course since we’re programmers, we’ve worked towards programmatic solutions to this problem. To help us analyze the effects of changes to our code, we write a second program to check our first program. This second program makes assertions and checks expectations about the state of the program at any given point.

If you’re checking the state of the first program while its running, you’re talking about executing a test suite.

If you’re checking the state of the source code of the first program, you’re talking about static type checking.

A static type system is one where each object is given a type. The type has information about what messages objects of that type can respond to. Those messages, in turn, have slots in them for parameters. These slots are have the shape of other types, so that only objects of those types can fit in those slots. They let you set an expectation. “I am a method. I want these kinds of objects, which will in turn respond to these messages. When I’m done, I’m going to return this kind of object.”

Of course, you can circumvent this whole system by using prodigious casting or by using the id type for everything. Using a so-called “untyped” system, like Ruby or the id subset in Objective-C, is purposefully crippling yourself. Instead of pretending that there are no types in such a system, we need to realize that we’re actually shoehorning every semantic type into one.

Types are useful, because the computer, dozens of times per minute, can assert that your code is meeting the expectations of the code around it. There’s a reason we call it type safety. You can also get this with a comprehensive test suite, but that means painstakingly writing hundreds of tests while you write code. The beauty of types when compared with tests is that, as long as you’re using semantic types to model your app’s universe, you’re going to get all of that type-checking for $free.99.

I’m not saying that tests aren’t tremendously valuable. Type-checking, generally speaking, can’t verify the behavior of your methods. But the rote tests in your system, the boring ones, the ones you hate writing, these should be automatically checked by the computer, with no input from you. To get even more benefit out of type checking, wrap even the simplest value objects (like NSString) in a type: this pattern is called Tiny Types.

Tests and types reveal their similarities in other ways too. A Massive View Controller is completely untestable and doesn’t gain much from type checking either. A better architecture, which generally involves more objects (and more types!) with less logic each, will be both way more testable and way more type-checkable.

We write tests because programs never stay the same. Requirements change, new features are added, and old code must be updated to more closely match the domain. We use refactoring to make sure our domain and our code stay aligned. We don’t write tests to assure that our code works right now, we write them to assert our that our new code is isomorphic to our old code.

Types are useful in the exact same way. The moment you change a method’s signature, the compiler immediately points out where you were using the old methods’s name, and lets you fix it. As long as you’re refactoring in small composable chunks, you’ll immediately know what you’ve broken. Type checking isn’t a panacea: an app that compiles with no warnings isn’t a necessarily going to behave perfectly, but that’s true of a project with all tests passing as well.

Types and tests are very similar, both leveraging the power of computers to do lots of mechanical tasks quickly. If you’re not taking advantage of both tests and types to wrote stronger, safer code, you’ll never know what bugs you’re leaving in your wake.

April 7, 2014

Replace Conditional With Message Construction

I’m slowly starting to appreciate the role of metaprogramming in Objective-C and how to do it in a compiler-safe manner. With dynamic methods, there are are two cases: you can either send a message that the receiver doesn’t necessarily know about at compile-time, or you can receive a message that the sender might know about at compile time.

Dynamic Method Resolution

Receiving a message that you didn’t publicize at compile-time is called dynamic method resolution. Rails uses this to great effect with dynamic finders. They let you call User.find_by_email('soroush@khanlou.com'). That message will be caught at run-time in the User class and dynamically return the result of User.find_by('email', 'soroush@khanlou.com'). This would automatically work for every property you have on your model object. Strictly speaking, this is possible in Objective-C (I show how exactly in an article about dynamic Objective-C on the Rap Genius tech blog). However, there are a number of things in Objective-C that prevent us from writing code like this, including

  1. ARC, which requires the method signature of every method to be known at compile-time, so that clang can insert retains and releases at the right time
  2. compiler warnings, which assure that the methods we are calling are actually publicized (in a header) and that the methods that we publicize actually exist

Dynamic Message Construction

On the other hand, you can have a method that the sender builds at run-time but the receiver has already defined at compile-time. This is called dynamic message construction, and, crucially, the compiler won’t stand in our way for this technique.

You can see dynamic message construction at play in Core Data’s validators. Core Data will dynamically check for and call methods of the form validate<Key>:error:. For example, if you had a “name” property, Core Data would dynamically call -(BOOL)validateName:(id *)ioValue error:(NSError **)outError, giving you the power to validate it, return an error describing why it’s not valid, or even change the pointer to the object its asking you to validate. This could all be rolled up into one big method called -validateValue:forKey:withError:, but that could grow to be a pretty big method! You’d probably want to separate each of the validations like so:

- (void)validateValue:(id *)value forKey:(NSString *)key withError:(NSError *)error {        
    if ([key isEqualToString:@"name"]) {
       [self validateName:value error:outError]
    }
    if ([key isEqualToString:@"email"]) {
        [self validateEmail:value error:outError]
    }
}

A new refactoring

To that end, I present a new refactoring strategy: Replace Conditional With Message Construction.

Martin Fowler’s book, Refactoring, in addition to outlining the intention behind refactoring and the methodology for doing it safely, also includes a catalog of refactoring strategies (including Replace Conditional With Polymorphism, which is what inspired this blog post).

Core Data shows us how this is used in the model layer, but let’s look at an example in the view layer as well.

In the Rap Genius app, we use -configureCell:atIndexPath: when setting up cells to separate the creation of the cell from its configuration. If a table view has many types of objects represented in its rows, we want to break down our configuration method even further:

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    id object = [dataSource objectAtIndexPath:indexPath];

    if ([object isKindOfClass:[RGArtist class]]) {
        [self configureCell:cell withArtist:object];
    } else if ([object isKindOfClass:[RGSong class]]) {
        [self configureCell:cell withSong:object];
    }
}

As this gets more and more complex, it is a ripe place to use this refactoring.

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    id object = [dataSource objectAtIndexPath:indexPath];
    SEL configurationSelector = [inflector selectorWithPrefix:@"configureCell:with" propertyName:[[object class] modelName] suffix:@":"];

    if ([self respondsToSelector:configurationSelector]) {
        [self performSelector:configurationSelector withObject:cell withObject:object];
    } else {
        [self configureCell:cell withObject:object];
    }
}

This code will now dynamically get the modelName of your model (such as “Song”), and call configureCell:withSong: or configureCell:withArtist: as appropriate.

The great thing about this pattern is that it helps separate your code into very logical units without having to include a giant conditional that is brittle and prone to change. It truly shines in a framework, where you may not know what objects are going to be represented in your table view, and it becomes crucial to call their configuration methods dynamically.

March 19, 2014

Model View Whatever

Graham Lee, the security boffin, has been writing a series of posts about Model View Controller and its meanings, with historical and contemporary contexts. His most recent post, Inside-Out Apps, is a good read.

The question is simple: What do we mean when we say MVC? The M and V, of course, are obvious. The Model represents your data and the actions you want to perform on it. The View displays that data. What’s in between is nebulous.

In iOS, Controllers are View Controllers, with the prefix UI, suggesting that they’re very tightly coupled with the View layer. In Rails world, Controllers receive an “action” from the router and fetch and prepare data for the View, which is more of a template. In Java, Controllers explicitly observe their Models, updating their Views anytime something happens.

These are all very different ways of considering the C in MVC. They probably should all have different names. In fact, they do all have different names. And pretty pictures.

Model View Controller

MVC

True Model View Controller, as imagined in the Smalltalk world, is defined by three components that, crucially, each talk to both of the others. Models and Views with direct interaction! If someTableViewCell.object = object makes you gag, then you should definitely not be calling your work “MVC”. Controllers here exist to capture user input, and update the views and models.

Model 2

Model 2

Rails-land behaves a little bit differently. The basic architecture originates from Java-based servers and is called Model 2. Because all of the user inputs come in the form of page requests, those are routed through the Controller as “actions”, which massage the Models and send the data over to the Views. The Views render a response as output and return that to the browser.

Model View Adapter

Model View Adapter

In Objective-C, the pattern that we generally call MVC is more technically referred to as Model View Adapter. In this system, Models and Views have no direct interaction, and actions (in the form of IBActions, target-actions, KVO observation, delegate calls, and NSNotifications) flow through the Adapter and update the relevant Models and Views.

Funneling all these different actions through a single object (the view controller) will result in a giant class, jokingly referred to as a Massive View Controller. It’s no wonder that the largest view controller in Brent Simmons’s Vesper codebase is 2900 lines long. You can tell a Ruby developer about a class with 3,000 lines of code, but not without fetching them a fresh pair of underwear first. Objective-C certainly is verbose, but verbosity can’t explain a god class.

I could talk about Massive View Controller for quite a while, so I will leave the discussion of that for another day/blogpost series/anthology.

MVVM

MVVM

Model-View-ViewModel, hailed as a savior to Massive View Controller, does address some of the problems we face. Ash Furrow wrote a great writeup on the Teehan+Lax blog about MVVM. The View Controller is more formally bound to the View Layer (as it should be, since it’s really a View-level object). A new layer is inserted between the Model and the View couplet, called the View Model, and it is in charge of storing all of the presentation logic for a given view. Other texts might call this the Presenter pattern, which is a name I like, since it doesn’t include the name of both of the other components in the triad.

VIPER

VIPER

The great thing about programming is that you can do whatever you want. Don’t be bound by ideology or mythology. If we can add a new layer between our View/View Controller combo and our Model, why can’t we add some more layers? VIPER — View-Interactor-Presenter-Entity-Router — attempts to do just that.

  • The Model is renamed Entity, probably to make a contrived acronym
  • The Router handles sending a requested “action” to the relevant Interactors
  • Interactors (also sometimes called Service Objects) represent all business logic involving multiple Entities
  • Presenters prepare data for display
  • The View is now dumb as rocks

A small note: Interactors differ from classic Rails controllers in that they’re not bound to a Model (the way UsersController might be tied to the User model), but instead perform some task that involves one or more Entities. Controllers might still exist in this world to receive an action from the router and kick off the relevant Interactors or fetch data from the database.

The best part about adding more layers like this? Each layer, now with a specific role, is way more testable, and the View, usually the hardest layer to test, is now so dumb it doesn’t need unit testing.

So where does this leave us?

Primarily, it leaves us with a language for describing the patterns that we use on a day-to-day basis. What pattern is most appropriate for your app? That’s going to have to be for you to decide. Do you have a Model whose properties require a lot of transforming before display? Take that transformation code out of your View Controller, or — worse — your View, and place it in a Presenter object. A complex interaction between two Models might go in an Interactor. A table view that shows variable content might need a custom Data Source that knows how to manage all of its various states. An app that has content on each View Controller that could link to any other View Controller might need a Router. The possibilities are endless, and the only thing standing between you and your well-factored application is the New Class dialog.

Further reading and watching:

  • Gang of Four: I’m still working my way through this text, but it has a lot of the prototypical versions of a lot of these patterns.
  • Patterns of Enterprise Application Architecture: A more practical resource for this day and age, this one practically reads as a cookbook for a framework like Rails.
  • Refactoring: A great way to think about how to improve your application’s architecture after it’s been built.
  • collective/interactor: A simple Ruby Gem implementing the Interactor pattern.
  • Architecture: The Lost Years: A talk from a Ruby conference in 2011, describing the similar issues that our Ruby-focused brothers and sisters are facing. 65 minutes.

I’ll leave you with Graham Lee:

When you get overly attached to MVC, then you look at every class you create and ask the question “is this a model, a view, or a controller?”. Because this question makes no sense, the answer doesn’t either: anything that isn’t evidently data or evidently graphics gets put into the amorphous “controller” collection, which eventually sucks your entire codebase into its innards like a black hole collapsing under its own weight.