November 18, 2014

Wink in All Colors

November 12, 2014

A Controller By Any Other Name

What’s in a name? Isn’t this stuff supposed to be a hard problem anyway? What is a DownloadController, and how is it different from a DownloadQueue?

I love this quote by Graham Lee so much:

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.

Charged with bridging between models and views, view controllers grow to become untenable nightmares quickly. It’s become valuable to question what the word “controller” even means to us.

What’s a gesture recognizer? It gets attached to views, suggesting that maybe it belongs in the view layer, but it’s definitely not a view. However, in Smalltalk (the first object-oriented lanugage), user input is classically a controller concern. Which of the two is it? The answer is simple. A gesture recognizer is just that: a gesture recognizer.

Not all objects have to be models, views, and controllers. Some objects are data sources, gateways, routers, and interactions; others still are players, presenters, and operations.

Models and views are easy; they are Things. Representing them in your brain in not a challenge. Controllers are much more amorphous. With models and views, shared behavior in them can be moved up to a superclass, and specific behavior can be moved down to a subclass. All of the models in your app could descend from one class; say, MTLModel. Views could do the same (and in fact, must, if you expect them to play nicely with UIKit). View controllers also have lots of shared behavior and benefit from a supertype. What would a hypothetically-named SKController superclass even do? With responsibilities so broad, what would that interface declaration even be? It would probably be empty.

@interface SKController : NSObject

@end

What useful thing is this object doing? What shared behavior can we give it? And if there’s nothing sensible in SKController, why call things controllers at all? They’re also all objects. It would be just as appropriate to append the word “Object” to every class name.

The harm caused by the “Controller” suffix is subtle, too. When you call something a Controller, it absolves you of the need to separate your concerns. Nothing is out of scope, since its purpose is to control things. Your code quickly devolves into a procedure, reaching deep into other objects to query their state and manipulate them from afar. Boundless, it begins absorbing responsibilities.

The scope of a policy object is very narrow, and it quickly becomes obvious when it starts acting outside of that scope. It has very clearly defined boundaries, and it’s perfectly testable. It is everything a MusicLibraryController is not.

MusicLibraryController can be decomposed into a MusicLibrary with LibraryItems, a Player, and a PlayQueue. We’ve granted a specific role to each component. A new developer needs to know only the names of classes to intuit how they work together. She can do this without reading a single line of code. That’s incredibly powerful.

Naming is hard, but calling things “controller” is easy. (“Manager” is a cop-out too. Sorry.) Spend a little time and think about what role your new object plays in your architecture. Give it an expressive name based on its purpose. If a meaningful name is hard to pin down, it might encapsulate more than one responsibility. Break it up. Read Gang of Four and Patterns of Enterprise Application Architecture from cover to cover. Learn about the different patterns that programmers have been using for decades. Or make up your own! If it feels right, try it out. You’ll know if it’s good.

October 22, 2014

The Myth of the Builder

Software often eludes analogy. It's written in code, compiled into assembly, translated into CPU instructions, run on a kernel, and finally executed on invisibly tiny transistors. Such a complex beast is hard to map onto the real world.

The analogy we've settled on for the creation of software is the architect/builder separation. The designer is the architect: he provides a specification for the product. The programmer is the builder: she implements it. However, this formulation is functionally a myth, and understanding why it's wrong will help explain why software is delivered late, low-quality, and over-budget.

This koan on the Codeless Code is an interesting one. In addition to being cute and snarky, it makes a very strong case that the civil engineer and the software engineer do very different things. We know that the designer is not doing the building; if programmer is also not doing the building, how is software turning from idea into reality?

What is happening is that the designer presents the software as very high-level blueprints to the programmer. The programmer then takes those and creates a lower-level set of blueprints for the compiler.

(Incidentally, the compiler is producing an even lower-level blueprint, called the Intermediate Representation, which is translated in to a final set of blueprints, the specific instructions for different CPUs. It's blueprints all the way down.)

The compiler takes the programmer's blueprints and arranges them (nearly instantly!) into their final form. The actual "construction" phase of software engineering is effectively free. To understand how fundamentally strange that is, imagine a machine that accepts blueprints for a bridge and instantly produces the whole bridge. The completed bridge takes up practically no space so we can produce as many copies of it as we want. In addition, our machine can produce other physical constructs to poke and prod the bridge to make sure it works as expected. That would be a very weird world for civil engineers indeed!

This new analogy helps explain two things about our industry. First, it helps explain why requirements change all the time. People have seen how powerful code is, and how quickly it can be changed. It’s also hard to explain in advance why some changes are much more difficult to make than others, so requirements will change in the process of creating the blueprints. Nothing is final until the "Submit to App Store" button is pressed.

The other thing that this analogy helps explain is the "mythical man month". Bringing on another programmer paradoxically slows the project down. You can add extra builders to a bridge to build it faster, just as you can add extra clock cycles or cores to a CPU to make it compile faster. But nobody has ever suggested that architects are fungible. Smaller teams produce higher quality code for this reason. The "architects" aren't isolated, given a rote task, and managed in a top-down fashion. Designing software architecture takes omnidirectional communication, which gets costly as teams grow.

What else can we learn here? Because the designer's "blueprints" are interpreted by a human, any inconsistencies can be smoothed out. The programmer's blueprints have to be much more detailed, since they will be interpreted literally and unambiguously by a CPU. It pays to have more explicit blueprints earlier in the pipeline, because the programmer will have to do less interpolation to fill those gaps. Creating those specifications will result in better software, and can help with reducing requirement creep.

Because computers only emulate the real world for convenience's sake, it can be hard to remember how many layers of abstraction lie between the code you write and the actual silicon that runs it. In Structure and Interpretation of Computer Programs, Abelson and Sussman say:

A computational process is indeed much like a sorcerer’s idea of a spirit. It cannot be seen or touched. It is not composed of matter at all. However, it is very real. It can perform intellectual work. It can answer questions. It can affect the world by disbursing money at a bank or by controlling a robot arm in a factory. The programs we use to conjure processes are like a sorcerer’s spells.

It's not valuable to think of software as a bridge; it's too weird for that.

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.