Unit testing multithreading code: Just Don’t Do It

Seriously, don’t try to write unit tests for multithreaded code. It will bite you in the ass later.

The reason unit testing code that runs on multiple threads is hard is the fact that you can’t control the order of execution of threads, nor the allocated time per thread – this is an OS decision.

Thus, in order to make sure the code submitted on the other thread executes and populates the expected data, you’ll need to block the main thread, where unit tests usually runs, for an amount of time large enough to be sure the other thread finishes the work.

Now, the tricky part is to find what that amount of time should be. Make it too short and you’ll see random failures of your unit tests, make it too long and you’ll increase the duration of your unit tests more and more. And theoretically there’s no upper limit for how long will need to wait for the other thread to finish, as this is out of our control (remember, the OS decides which thread to pick up next and how much time to allocate to it).

And worse, when a unit test like this starts failing on a CI machine but it doesn’t fail on your machine, who’s to blame: the CI machine for being too slow, or your code misbehaving in some conditions that happen only on the CI machine? This ambiguity can lead to lot of time wasted in trying to figure out what the hack happens with the tested code.

Conclusion: don’t try to write unit tests for code that executes parts of its work on a different thread. The reason is simple: robust unit tests need to have control over all inputs of the tested code, and the second thread is not something it can control (unless you mock the thread dispatching, but that’s another story).

Instead, push as much logic as you can into single-thread methods, and tests those methods instead. In the end, most of the bugs occur due to incorrect business logic.

Objective-C: new is dangerous (and old), avoid it at all costs

Using the new factory method might seem appealing: you no longer have to type [[MyClass alloc] init], you no longer need to write custom factory methods to your class, in short less code. And this is not a bad thing, less code to write means less code to maintenance, test, etc.

new unfortunately has a big flaw, mainly caused by the fact that new translates to alloc+init. This makes it easy to mistakenly use init where you should not be allowed to. One situation that falls into this category is when init is declared with the NS_UNAVAILABLE attribute, which causes compile errors when used directly.

Let’s consider a short example:

@interface MyPerson: NSObject

@property (nonatomic, readonly, strong, nonnull) NSString *name;

- (nonnull instancetype)init NS_UNAVAILABLE;
- (nonnull instancetype)initWithName:(nonnull NSString *)name NS_DESIGNATED_INITIALIZER;

@end

We try to be very clear and specific regarding the class: it should have a non-nil name, and you should be able to instantiate it only via the initWithName: intializer. The basic init would not make sense here, since we’d end up with an invalid instance (name would be nil), so we mark it as unavailable.

Trying to write [[MyPerson alloc] init] results in a clear compile error: 'init' is unavailable. On the other hand [MyPerson new] successfully compiles and silently fails at runtime as we end up with an invalid instance. This can result in some bugs hard to find, especially if new is used only in some places of the application.

And even if new makes sense at the time the class is written – i.e. init gives a valid instance, things can change in the future if other developer (or even yourself) change the class initializers and make init unavailable, at which point things might start to go wild if some of the new calls are missed and not replaced by the new ones. On the other hand alloc init doesn’t suffer from this problem, as you’ll instantly get compile errors all over the place where the construct is used.

Swift handles this a little bit better by crashing the app if new is used on a class that has init exported as unavailable – for example if you add a required parametrized initializer to the class. The code still compiles, but you no longer get a silent failure, and the app simply crashes. This helps as it gives you the exact root cause of the problem, but, depending on the application, might not be a preferable solution.

alloc init gives you bug free code courtesy of the compiler. new leads to error prone and less forward compatible code. Let’s stop using it.

When the Coordinator fails for you, hire an Assistant

Update. This approach is no longer valid, an Assistant is basically a Model, as what I wrongly described here was an MVC without the M part.

I’ve been lately using the the Coordinator pattern (actually its variation Coordinator+ViewModel), and while the pattern is a very good one in terms of separation of concerns, it does have some limitations that you might run at a certain point.

The good parts of the Coordinator pattern:
– Orchestrates the navigation flow, decoupling this logic from the Controller
– Because the Coordinator handles mainly the navigation logic it’s easier to grasp the actual flow within the app
– It’s a clean way to build up UI hierarchies, starting from the root level, meaning less code in AppDelegate
– Adding a ViewModel along means way less business logic in the Controller (yay!)

Where it fails:
– Reusability: I found it hard to reuse a controller with a dedicated coordinator, as would have to carry the coordinator along, or parts of the coordinator. This couples a controller as part of a single flow
– Sometimes awkward: should we also delegate alert presentation to the Coordinator? Should we add delegate method to support all kind of alerts we want to display?
– State restoration, which iOS gives it to us almost for free, is hard to achieve with Coordinator, as the iOS SDK expects the Controller to be the main actor, thus iOS will restore only the hierarchy of controllers
– Can’t be used efficiently with Storyboards

It’s variation Coordinator+ViewModel brings another concern: from an architectural point of view it feels unnatural to delegate UI actions to the ViewModel, which will simply forward them to the Coordinator; this is at least a matter of mixed responsibilities (even if the ViewModel simply forwards the calls upstream).

Another concern is that once we built up a Coordinator hierarchy, we need to intercept all kind of scenarios, like ones where a Controller is dismissed due to extrinsic causes, to avoid situations when we end up with “zombie” Coordinators.

The thing is, we like it or not, the iOS platform is built around MVC. Many features revolve around the concept of controllers: we build navigation controllers, push other controllers to them, we ask controllers to dismiss themselves, we configure navigation items for them, etc.

We do however need to address the Big Fat Controller concern, as we simply cannot put all our business logic in the Controller just because the MVC pattern doesn’t provide us with a better place for it. We need to delegate this work to another object (like Coordinator and ViewModel did), however we do not need to loose control.

I call this the Assistant object. Basically controllers will either create an assistant for their own, or will receive it from the upstream controller, depending on the situation.

This is a simple way to keep the Controller as the main actor, but still leverage the amount of responsibilities the Controllers needs to handle.

This opens up the way to new possibilities, like injecting the same assistant to the downstream controller. We can use protocols to expose only what we want to expose downstream. Having both controller work with the same assistant means that we no longer need delegates in order for the downstream controller to notify upstream that its job is done and the collected data needs to be recorded, as the data is already in the correct place; we only need to reconcile the UI with the assistant data, and we can do this automatically by being a delegate for the assistant.

Here’s a simplistic example of this pattern in practice. Let’s assume we have a list of persons we want to manage by adding/removing persons from a list:


class PersonsAssistant {
    var persons: [Person] = [] {
        didSet { onPersonsChange?() }
    }
    
    /// Using callbacks instead of delegate as it's more convenient
    var onPersonsChange: (() -> Void)?
    
    func addPerson(_ person: Person) {
        persons.append(person)
    }
    
    func removePerson(at index: Int) {
        persons.remove(at: index)
    }
}

public class PersonsListViewController: UITableViewController {
 
    var assistant: PersonsAssistant
    
    init(assistant: PersonsAssistant) {
        self.assistant = assistant
        super.init(style: .plain)
        navigationItem.title = "Acquaintances"
        navigationItem.rightBarButtonItem =
            UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(onAdd))        
    }

    func viewDidLoad() {
        super.viewDidLoad()
        assistant.onPersonsChange = { self.tableView.reloadData() }
    }
}

extension PersonsViewController {
    @objc func onAdd(_ sender: Any) {
        let addPersonVC = AddPersonViewController(assistant: assistant)
        navigationController?.pushViewController(addPersonVC, animated: true)
    }
}

We’re letting the assistant handle the data operations, while the controller only watches for changes in the data and reloads it’s UI when that happens (I’ve used callbacks here as a data change communication mechanism, but nothing stops you in using delegates, RxSwift/ReactiveSwift, or other techniques).

This is how would the AddPersonViewController might look like:

class AddPersonViewController: UIViewController {
    let assistant: AddPersonAssistant
    
    public init(assistant: AddPersonAssistant) {
        self.assistant = assistant
        super.init(nibName: nil, bundle: nil)
        navigationItem.rightBarButtonItem =
            UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(onSave))
    }
}

extension AddPersonViewController {
    @objc func onSave(_ sender: Any) {
        let person = Person(firstName: "John", lastName: "Doe")
        assistant.addPerson(person)
        navigationController?.popViewController(animated: true)
    }
}

We achieved a couple of things here:
1. The Controller is in the driving seat, at least regarding the UI, and that’s a good thing, as this is it’s meaning
2. We fully decouple the business logic from the controller, we now have a dedicated object that does this for us. This object is very similar to a ViewModel, however I wanted to avoid this term as IMO it doesn’t make so much sense outside of MVVM
3. Interface Segregation (the I from SOLID) – AddPersonViewController knows nothing more about the assistant than it needs to know in order do its job
4. Increased testability – since the Assistant knows nothing about UI components, it should not be hard to obtain high testing coverage over that unit

One downside is that we loose the manager of the initial controller, for which the Coordinator pattern fits perfectly. Now we’re back to either using AppDelegate for this (not a good idea at all, as the AppDelegate might be already burdened with lots of other responsibilities), or delegate this to a RootControllerConfigurator object (still seeking for a better name, open to suggestions here :).

To me, it feels that the Assistant approach fits more naturally within the iOS ecosystem. Haven’t use it much in practice yet, but I plan to 🙂

Swift – make your life easier with promises

A while ago I wrote a series of articles about Promises in Objective-C, and described the way promises help us write async code in an async manner, help us pipeline data streams and recover from errors by giving the pipeline another thing to process. Well, time has passed, Swift came along, and promises look better than ever, thanks to features of the programming language.

Note. The rest of the article makes use of the CKPromise.Swift library (https://github.com/cristik/CKPromise.Swift).

Let’s dive in, and begin with a simple example – sending a NSURLRequest over a NSURLSession, and parse the received data (we assume it’s a JSON) into a dictionary. To keep things clean we’ll add extensions over NSURLSession, respectively NSData for these two tasks. The code might look like this:

public extension NSURLSession {
    func sendRequest(request: NSURLRequest) -> Promise<NSData,NSError> {
        let promise = Promise<NSData,NSError>()
        let task = self.dataTaskWithRequest(request) { data, urlResponse, error in
            if let error = error {
                // we have an error, means the request failed, reject promise
                promise.reject(error)
            } else if let data = data {
                // we don't have an error and we have data, resolve promise
                promise.resolve(data)
            } else {
                // we have neither error, nor data, report a generic error
                // another approach would have been to resolve the promise
                // with an empty NSData object
                promise.reject(NSError.genericError())
            }
        }
        task.resume()
        return promise
    }
}

public extension NSData {
    func parseJSON() -> Promise<[NSObject:AnyObject], NSError> {
        let promise = Promise<[NSObject:AnyObject], NSError>()
        if let parsedJSON = try? NSJSONSerialization.JSONObjectWithData(self, options: []),
            let result = parsedJSON as? [NSObject:AnyObject] {
            // yay, we were able to parse, and received a dictionary
            promise.resolve(result)
        } else {
            // 🙁 report an invalid json error
            promise.reject(NSError.invalidJSONError())
        }
        return promise
    }
}

public extension NSError {
    class func genericError() -> NSError {
        return NSError(domain: "GenericErrorDomain", code: -1, userInfo: nil)
    }
    
    class func invalidJSONError() -> NSError {
        return NSError(domain: "InvalidJSONErrorDomain", code: -1, userInfo: nil)
    }
}

With the above methods available, the actual code looks something like this:

// Please ignore the forced unwrap for now
let url = NSURL(string: "https://jsonplaceholder.typicode.com/posts/1")!
let request = NSURLRequest(URL: url)
NSURLSession.sharedSession().sendRequest(request).onSuccess({
    return $0.parseJSON()
}).onSuccess( {
    print("Parsed JSON: \($0)")
}).onFailure( {
    print("Failed with error: \($0)")
})

Let’s continue with something more useful. Now that we have the JSON of a post, let’s make use of it and create a model.

struct Post {
    private(set) var id: Int = 0
    private(set) var userId: Int = 0
    private(set) var title: String = ""
    private(set) var body: String = ""

    static func fromDictionary(dictionary: [NSObject:AnyObject]) -> Promise<Post,NSError> {
        let promise = ()
        guard let id = dictionary["id"] as? Int,
            userId = dictionary["userId"] as? Int else {
                // the above two fields are mandatory, reject the promise if missing or invalid
                return Promise<Post,NSError>.rejected(NSError.invalidDictionaryError())
        }

        var post = Post()
        post.id = id
        post.userId = userId
        post.title = dictionary["title"] as? String ?? ""
        post.body = dictionary["body"] as? String ?? ""

        return Promise<Post,NSError>.fulfilled(post)
    }
}

We declared a struct for the model, and we added support for creating a new model in a promised way. Why did we do this? Because it enables us the following flow:

NSURLSession.sharedSession().sendRequest(request).onSuccess({
    return $0.parseJSON()
}).onSuccess( {
    return Post.fromDictionary($0)
}).onSuccess({
    print("Received post: \($0)")
}).onFailure( {
    print("Failed with error: \($0)")
})

We added one more step to the pipeline in one of the most easiest way we could add it. The code is short and clean and transmits very well it’s intend.

We can go even further and consider the pipeline successful only when the post is saved into the local database for example:

NSURLSession.sharedSession().sendRequest(request).onSuccess({
    return $0.parseJSON()
}).onSuccess( {
    return Post.fromDictionary($0)
}).onSuccess( {
    return databaseHelper.savePostToDB($0)
}).onSuccess({
    print("Received and saved post: \($0)")
}).onFailure( {
    print("Failed with error: \($0)")
})

There’s no limit of the length of the chain (pipeline).

We can also go the other way around, send a local post to the server:

databaseHelper.readPostWithID(18).onSuccess({
    return $0.toJSONDictionary()
}).onSuccess({
    let urlRequest = NSURLRequest(....)
    // configure the request payload
    return NSURLSession.sharedSession().sendRequest(urlRequest)
}).onSuccess({
    print("Successfully sent the post to server")
}).onFailure({
    print("Oh no, an error occurred: \($0)")
})

The above code snippets exemplify how promises help us write clean/short code, that helps with the separation of concerns and allow easy development of long processing pipelines, all while allowing asynchronous execution of the operations.

This is only the first part of the series of Swift promises. So stay tuned :).

P.S. As you might have noticed, the parseJSON() method of NSData is not an async one. The main thread is blocked while the json is parsed, so we’re not fully async there. Luckily this is easy to change, just dispatch the json parsing code onto another queue and resolve/reject from there:

func parseJSON() -> Promise<[NSObject:AnyObject], NSError> {
    let promise = Promise<[NSObject:AnyObject], NSError>()
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
        if let parsedJSON = try? NSJSONSerialization.JSONObjectWithData(self, options: []),
            let result = parsedJSON as? [NSObject:AnyObject] {
            // yay, we were able to parse, and received a dictionary
            promise.resolve(result)
        } else {
            // 🙁 report an invalid json error
            promise.reject(NSError.invalidJSONError())
        }
    });
    return promise
}

Now, we’re fully async.

Retrying async functions in Swift via high-order functions

TL;DR; Solution can be also found here.

Supposing we’re writing a client-server communication layer, and we want to add support for retrying failed calls for a number of times before giving up and reporting error. A classical example would be updating a user’s profile when pressing a Save button from the UI.

A typical function might look like this:

func updateProfile(firstName: String, lastName: String, success: Any -> Void, failure: NSError -> Void) {
    let urlRequest = NSURLRequest()
    // ...
    NSURLSession.sharedSession().dataTaskWithRequest(urlRequest,
        completionHandler: { data, response, error in
            // if we have no error and have received data, we're OK
            guard error == nil, let data = data else {
                failure(error ?? NSError(domain: "MyDomain", code: 1, userInfo:  nil))
                return
            }
            success(data)
    }).resume()
}

How can we make this retry-able any number of times we need?

Firstly, let’s add a type alias corresponding to a no-parameter async function that we can
pass around:

typealias Async = (success: Void -> Void, failure: NSError -> Void) -> Void

Next, we need to modify the `updateProfile` function to return an `Async` value, and the `retry` function to make use of that value. This change doesn’t require much effort, it’s just a matter of removing the callbacks from the parameters list and wrapping the function body into a closure:

func updateProfile(firstName: String, lastName: String) -> Async {
    return {success, failure in
        let urlRequest = NSURLRequest()
        // ...
        NSURLSession.sharedSession().dataTaskWithRequest(urlRequest,
            completionHandler: { data, response, error in
                // if we have no error and have received data, we're OK
               guard error == nil, let data = data else {
                   failure(error ?? NSError(domain: "MyDomain", code: 1, userInfo: nil))
                   return
               }
               success(data)
        }).resume()
    }
}

We also need the actual retry function, which could look like this:

func retry(numberOfTimes: Int, task: () -> Async, success: Void -> Void, failure: NSError -> Void) {
    task()(success: success, failure: { error in
        if numberOfTimes > 1 {
            retry(numberOfTimes - 1, task: task, success: success, failure: failure)
        } else {
            failure(error)
        }
    })
}

One minor inconvenient is that the retry function expects a closure that takes no arguments and returns an Async, while our updateProfile function takes two arguments. This is not however a big problem, as we can wrap the updateProfile call into a closure:

retry(3, task: { updateProfile("firstName", lastName:"lastName") },
    success: { data in
        print("Succeeded")
    },
    failure: { err in
        print("Failed: \(err)")
    }
)

Nice and clean, we can easily configure the number of times to retry, as most of all our existing async functions need very few changes in order to benefit of this retry mechanism.

P.S. If however you don’t want or can’t change existing functions, then you can simply add wrappers for those functions, like in this example for updateProfile:

func updateProfileAsync(firstName: String, lastName: String) -> Async {
    return { success, failure in
       updateProfile(firstName, lastName: lastName, success: success, failure: failure)
    }
}

if-let statement in Objective-C

I just found an equivalent to Swift’s if-let construct, and thought to share it 🙂

Swift:

if let result = computeResult() {
    // do something with result
}

Objective-C:

for(SomeClass *result = [self computeResult]; result != nil; result = nil) {
    // do something with result
}

You no longer need an extra line to declare the variable, and also the variable is visible only inside the if branch. Just like in Swift 🙂

To manage or not to manage

This article is intended for those of you that you love and abuse the “manager” concept. I know you’re there, don’t try to hide yourself :).

The idea of a manager quickly gets into the mind of a developer when he designs a project. Sooner or later, you’ll need a manager that will coordinate some stuff. That’s not entirely wrong, but let’s see what managers are suitable for and what are not suitable for.

1. Managers are intended to coordinate multiple similar objects. The words “multiple” and “similar” are the key terms here. Think as in real life: you can’t have a manager for a single person (though there are exception from this, of course), and you can’t ask the same manager to handle both carpenters and welders at the same time, it  will not probably do a good job for neither of the two categories.

2. Managers can’t be used as the main coordinator of the application – i.e. the entity that knows of all modules and instructs them how to behave. That’s simply not a manager, that’s a fat class. And sooner or later you’ll wish you’d never had it. This kind of classes are simply not maintainable over a period longer than a year.

3. Managers are not singletons. Think as in real life, each person should know it’s manager. Thus, dependency injection. Even if implemented as singleton, the objects managed by the manager should receive a reference to that manager, instead of relying on a global instance.

My recommendation is to think twice before choosing a class name that contains “manager”. Reflect if the class really needs to coordinate a group of objects, and if it can do this without getting too fat and without needing the help of another N objects.

A promise implementation for objective-c: CKPromise

Now that we went through all promise technical details in the past articles: Promises and ObjectiveC: no more callback hell, Promises: basics, and Promises: advanced, it’s time to discuss  about one of the available implementations, and for subjective reasons I chose CKPromise. Other good implementations that I know of are PromiseKit and RXPromise.

CKPromise focuses only on implementing the Promise/A+ specs. Nothing else. All callbacks are currently scheduled on the main thread, for simplicity reasons. If there are requests to add support for scheduling callbacks on user-defined queues, I might take that into consideration, and add the support. Thus, I’m trying to follow the YAGNI model.

I think the best way to explain something is via examples, so I’ll try to cover all the features provided by promises, features discussed in the previous articles.

1. Basic usage: CKPromise can be resolved or rejected via the methods with the same name. Callbacks can be added via the then() method, which returns a block, thus it will be called in the C-style rather than the objective-c style.

- (CKPromise*)loginWithEmail:(NSString*)email password:(NSString*)password {
    NSDictionary *params = @{@"email":email, @"password":password};
    CKPromise *promise = [[CKPromise alloc] init];
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

    [manager POST:@"http://myserver.com/api/login"
       parameters:params
          success:^(AFHTTPRequestOperation *operation, id responseObject) {
              MYUser *user = [[MYUser alloc] initWithDictionary: responseObject];
              [promise resolve:user];
          }
          failure:^(AFHTTPRequestOperation *operation, NSError *error) {
              [promise reject:error];
          }];
}

- (IBAction)login:(id)sender {
    [apiClient loginWithEmail:emailTextField.text
                     password:passwordTextField.text].then(^(MYUser *user){
        [self showProgress:NO];
        // move to the regular user or admin screen, based on the user rights
    }, ^(NSError *error){
        [self showProgress:NO];
        // display an alert view
    });

    [self showProgress:YES];
}

CKPromise exposes some convenience methods that allow a simple usage in case we are interested only about the success or failure of the promise, or we just want a piece of code to be executed regardless the resolution of the promise: success, failure, always. Their usage is very similar to the one of then().

CKPromise also exposes resolveWith: and rejectWith: that allow you to resolve/reject the promise with multiple values. For example in the case of the login promise, one could have also want to also provide the raw object. This is how the promise would have been used:

[promise resolveWith:user, responseObject, nil];

// later in the code...
[promise success:^(MYUser *user, NSDictionary *serverData) {
    // the desired logic
}];

 

2. Sync-ish coding style when dealing with multiple async operations that need to be executed in cascade. This has been exemplified in the first article of the promises series, I’ll place it here too.

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *bookData = @{@"name": @"Harry Potter"};
[manager POST:@"http://myserver.com/validator/book"
    parameters:bookData].promise.done(^{
    return [manager POST:@"http://myserver.com/book"
              parameters:bookData].promise;

}).success(^(NSString *bookId){
    return [manager GET:[@"http://myserver.com/book/" stringByAppendingString:bookId]
             parameters:nil].promise;

}).success(^(NSDictionary *bookDetails){
    // inform the user that the book was added, move to the appropriate screen

}).failure(^(NSError *error) {
    if([error.domain isEqual:NSURLErrorDomain]) {
        // inform the user that there was a server communication problem
    } else {
        // inform the user about the problem
        // error.domain/error.code can be used to identify which one of the
        // three operations failed
    }
});

The code sample assumes that AFHTTPRequestOperation has a category that exposes a promise method/property. I leave the implementation of this method as an exercise for the reader. Hint: it’s not much different that the login method discussed earlier in the article.

Chains like this work no matter how many async operations we need to do. The chain of async operations will continue as long as the callbacks return a promise that corresponds to an async operation. But you’re not restricted to return only promises in a promise chain, this brings us to the next best thing provided by promises.

 

3. Data transformation: a chain of promises can be used to gradually transform a piece of raw data into a finite form. An example can be a distributed architecture where its components communicate via serialised objects, and that uses cryptography when sending data.

[communicationStream readDataAsync].success(^(NSData *encryptedData, NSUInteger senderTimestamp) {
    // throws MYDecriptException if decription fails
    return [data decryptAsyncWithTimestamp:senderTimestamp];
}).success(^(NSData *decriptedData) {
    // throws MYDataParseException if decripted data could not be parsed
    return [NSDictionary asyncParseMessageData];
}).success(^(NSDictionary *messageDict) {
    // throws MYInvalidMessage if the message dict doesn't contain the proper fields 
    return [[MYMessage alloc] initWithDictionary:messageDict];
}).failure(^(NSException *ex) {
    //based on the exception type we know which operation failed
});

We can see how natural we can transform pieces of data from a raw form to a finite one. Also if we take a look of how the sync version would look like, we notice that we have a very similar code flow.

@try {
    NSUInteger timestamp = 0;
    NSData *cryptedData = [communicationStream readData:&amp;timestamp];
    NSData *decryptedData = [cryptedData decryptWithTimestamp:timestamp];
    NSDictionary *messageDict = [NSDictionary dictionaryWithMessageData:decryptedData];
    MYMessage = [[MYMessage alloc] initWithDictionary:messageDict];
} @catch(NSException *ex) {
    // either based on the exception type we know which operation failed
    // or we add multiple exception handlers
};

 

4. Chain derailing: at a certain point in a chain a promise can decide to break the chain if it’s not satisfied with the results, or can recover and continue the chain with another values.

Chain recovering example:

[authenticator loginWithGoogle].failure(^{
    // not slightly interested about the error, thus the callback has no params
    return [authenticator loginWithFacebook];
}).failure(^{
    return [authenticator loginWithTwitter];
}).then(^{
   // I managed to authenticate with the server
}, ^{
   // none of the allowed authentication methods succeeded
   // I'm not authenticated
});

As for the chain breaking, the cryptic message communication flow described earlier in article serves as a good example. Basically at any time during the data processing the corresponding promise (e.g. the decryption or the data parsing one) can throw an exception or return a failed promise that has the virtual effect of moving straight to the failure callback. I call it virtual because all remaining promises is the chain receive the failure, however as none of them is interested about the failure, this is passed along until the failure callback is reached.

The powerfulness of promises come from the fact that not only they allow clients to schedule as many callbacks as need, but they also react to the values returned by the callbacks, allowing the clients to instruct how the promise should behave next (although the clients in fact instruct another promise). If I haven’s said it before, promises are awesome! This being said, I hope you enjoyed the last couple of articles of the subject of promises and I encourage you to use them as much as possible wherever you need support for asynchronous execution. You won’t regret it!

P.S. As usual, if you have any questions/comments you can post them as comments below.

Promises: advanced

In the previous article we discussed about the basics of promises: what are and how can be used. Today I will bring into discussion the most powerful feature of promises: chaining.

But first I just want to take a short detour and mention that as the standard for promises emerged on the Javascript platform, it allows completion handlers to be very flexible when it comes to adding success/failure callbacks, in terms of the arguments they expect, and the data they return. Thus the same promise allows callbacks with different signatures (not that you can’t run into problems when the callbacks are executed, but that’s another story).

Now, back to chaining. Thanks to the very well designed specifications of Promises/A+ (I strongly recommend you to read them if you haven’t yet so) , you can achieve at least the following if you use chained promises:

  1. sync-ish coding style when dealing with consecutive async operations that depend one upon another
  2. data transformation from one promise to another
  3. graceful recover from a failed operation, or the other way around marking the chain as failed if the operation result is not the desired one

Before we dive into the three above features, let’s recap: a promise only needs to provide 3 methods – a then() one for adding callbacks, a resolve() one if we want to mark the promise as succeeded and a reject() one if we want to mark the promise as failed. That’s all in terms of the Promise class interface.

The promises great advantage comes from its implementation: then() returns another promise, which gets resolved/rejected based on the callback return value. Calling then()  two times results in two additional promises being dispatched, which be either resolved or rejected based on a combination of the original promise resolution and the value returned by the callback. The specs describe exactly what should happen in every possible combination.

Let’s consider the example from the first article on promises, where adding a book involves 3 calls to the server API: validation of book fields, adding the book which returns it’s ID, fetching the other server generated fields. Having the then() method behaviour in mind, we know that each time it gets called, a new promise is dispatched, promise that continues the chain. This allows us to either continue the chain if the current async operation succeeded, or recover from an error and continue the chain with another operation in case of failure. Isn’t this great?

This leads to another advantage of promise usage, the fact that you can specify only one failure handler, at the end of the chain, and be sure that if any promise in the chain fails, then the failure handler will be executed. Let’s revisit the code from the article:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *bookData = @{@"name": @"Harry Potter"};
[manager POST:@"http://myserver.com/validator/book"
    parameters:bookData].promise.success(^{
    return [manager POST:@"http://myserver.com/book"
              parameters:bookData].promise;

}).success(^(NSString *bookId){
    return [manager GET:[@"http://myserver.com/book/" stringByAppendingString:bookId]
             parameters:nil].promise;

}).success(^(NSDictionary *bookDetails){
    // inform the user that the book was added, move to the appropriate screen

}).failure(^(NSError *error) {
    if([error.domain isEqual:NSURLErrorDomain]) {
        // inform the user that there was a server communication problem
    } else {
        // inform the user about the problem
        // error.domain/error.code can be used to identify which one of the
        // three operations failed
    }
});

As you can see, there’s only one error handler, which gets executed if any of the three async operations fails. This means in the first place no code redundancy, as we will not have to add an error handler for each individual operation.

Another major advantage of promises if the fact that they allow you to transform data. Just look at the following code:

- (CKPromise*)getUserWithId:(NSString*)userId {
    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
    NSString *url = [@"http://myserver.com/user/" stringByAppendingString:userId];
    return [mgr GET:url].promise.success(^(NSDictionary *userInfo) {
        return [[MYUser alloc] initWithDictionary:userInfo];
    });
}

//how to use it later in code:
[SomeUserManagerClass getUserWithId:@"aUserId"].then(^(MYUser *user) {
    // I received the user, yay
}, ^(NSError *err) {
    // some error occured
}

Basically, the Promises/A+ specs tell that if the promise callback (either success or failure) returns a value, then the promise created as a result will be resolved with that value. As I said before, any callback method called on a promise will return a new promise, that will get resolved with the result returned by the callback. This is very helpful as you can gradually transform data from a raw form into some concrete object.

If we think about it, we can have a promise that returns a raw NSString JSON, one that parses the NSString into a NSDictionary, and one that initialises an object from that dictionary. All in one place, all offering the support for async execution. Isn’t this also great?

[myAPIClient GET:@"http://someServer.com/user/1234"].success(^(NSString *response) {
    return [MYJSONParser parseString:response];
}).success(^(NSDictionary *dict) {
    return [[MYUser alloc] initWithDict:dict];
}).failure(^(NSError *error) {
    if([error.domain isEqual:NSURLErrorDomain]) {
        // there was an error communicating with the server
    } else if([error.domain isEqual:MYJSONParserErrorDomain]) {
        // the server sent an invalid JSON
    } else {
        // there only one possible error left
        // the MYUser initialisation failed for some reason
    }
});

Exceptions also have their place in promises specs. Basically if a promise callback throws an exception, then the promise created when adding the callback will be rejected with the thrown exception as reason. Having said this, I think promises cover all possible scenarios when it comes to async operations.

So far so good, however there is a catch. Javascript, for which the original promises were designed, is a loosely typed language. It doesn’t care if you pass one or three params to the callback, it doesn’t care about the types of those params, it doesn’t complain if you return a value or not in those callbacks. How this concept can be implemented for strongly typed languages, like a language from the C family, where every function must be clearly defined, and you cannot have the same method sometimes return something and sometimes return void?

The good news is that at least in Objective-C the promises as defined by the A+ specifications can be implemented. How exactly? I’ll try to describe in the next article, where I will present CKPromise in details.

Did this article answered some of your questions? Did it raise another ones? You can use the comment form if you have something to ask.

Update: You can check the last episode of the series here: http://blog.cristik.com/2015/03/a-promise-implementation-for-objective-c-ckpromise/

Promises: basics

In my previous article, I introduced the concept of promise, a technique that allows us to write async code in a more sync-ish manner. In this article and the following ones I will try to dive into the definition and expectancies of a promise.

So what is a promise? A promise represents the eventual result of an asynchronous operation. This means that you can use a promise wherever you use an async operation, and the promise will send the result of that operation (success or failure) to you.

Please note that the promise does not correspond to the async operation itself, but to the result of the operation. Thus, promises don’t offer support for cancelling, retrying, or another features of async operations. Promises are here to deliver the operation result to you.

A promise can only be in one of the following three states: pending, resolved, or rejected. A newly created promise is in the pending state, from which it can move to the resolved state by calling its resolve method, or it can move to the rejected state by calling its reject method.

Their usage is also simple: once you get your hands a promise, you can add success or failure callbacks on it. Adding callbacks can be done by calling the then method, method that accepts two parameters: a callback for success, and a callback for failure. Any of them can be nil, telling the promise that we don’t care about that certain resolution of the async operation.

// authenticateWithEmail:password: returns a promise
[authenticator authenticateWithEmail:email password:password].then(^(MYUser *user){
    // I got authenticated, yay
}, ^(NSError *error){
    // Something bad happened
});

The success callbacks are called when the promise gets resolved, while the failure callbacks are called when the promise is rejected. The promise guarantees that: 1) the callbacks will be executed in the order they were added, and 2) the callbacks will be executed after the current scope ends.

#2 allows developers to make  some extra configuration after the promise is dispatched. Below you can find a short example.

//retrieveBookWithId: returns a promise
[booksManager retrieveBookWithId:@"1234"].then(^{
    self.fetching = NO;
}, nil);
self.fetching = YES;

Even if the retrieveBookWithId: promise gets instantly resolved (e.g. if we return from a cache), we can be sure that the fetching flag will be set in the order we expect to.

At the very basic level you can use promises when you need support for multiple operation completion callbacks. But that’s not all a promise can do, executing callbacks based on the operation result. Thanks to the very well designed specifications of Promises/A+, you can do much, much more. One of the real power of promises comes from the fact that they can be chained in such a way that: 1) you write code in a sync-ish manner by naturally writing the promises one below the previous one, and 2) failed promises that should break the chain will break the chain. More on this in a future article.

To summarise the discussion so far, if you want to add promise support to your async operation, you need to create a promise and resolve or reject it when the operation finishes execution. If you want to use a promise, you need to add resolve/reject callbacks to that promise.

Stay tuned for continued discussions on promises. Meanwhile, if you have any questions you can leave them as comments.

Update: You can check my next article on promises here: http://blog.cristik.com/2015/03/promises-advanced/