Hello folks,
I'm dealing with some asynchronous communication situations (Event-driven XML parsing, NSURLConnection response processing, etc.). I'll try to briefly explain my problem:
In my current scenario, there is a service provider (that can talk to a xml parser or do some network communication) and a client that can ask the service provider to perform some of its tasks asynchronously. In this scenario, when the service provider finishes its processing, it must communicate back the results to the client.
I'm trying to find a kind of pattern or rule of thumb to implement this kind of things and I see 3 possible solutions:
1. Use the delegation pattern: the client is the service provider's delegate and it will receive the results upon task completion.
2. Use a target/action approach: The client asks the service provider to perform a task and pass a selector that will have to be invoked by the service provider once it has finished the task.
3. Use notifications.
(*Update*) After a while of trying solution #2 (target and actions), I came to the conclusion that, in my case, it is better to use the delegation approach (#1). Here are the pros and cons of each option, as I see them:
Delegation approach:
1 (+) The upside of option 1 is that we can check for compile-time errors because the client must implement the service provider's delegate protocol.
1 (-) This is also a downside because it causes the client to be tight-coupled with the service provider as it has to implement its delegate protocol.
1 (+) It allows the programmer to easily browse the code and find what method of the client, the service provider is invoking to pass its results.
1 (-) From the client point of view, it is not that easy to find what method will be invoked by the service provider once it has the results. It's still easy, just go to the delegate protocol methods and that's it, but the #2 approach is more direct.
1 (-) We have to write more code: Define the delegate protocol and implement it.
1 (-) Also, the delegation pattern should be used, indeed, to delegate behavior. This scenario wouldn't be an exact case of delegation, semantically speaking.
Action/Target Approach
2 (+) The upside of option 2 is that when the service provider method is being called, the @selector specifying the callback action must also be specified, so the programmer knows right there which method will be invoked back to process the results.
2 (-) In opposition to this, it's hard to find which method will be called back in the client while browsing the service provider code. The programmer must go to the service invocation and see which @selector is being passed along.
2 (+) It's a more dynamic solution, and causes less coupling between parts.
2 (-) Perhaps one of the most important things: It can cause run-time errors and side effects, as the client can pass a selector that does not exist to the service provider.
2 (-) Using the simple and standard approach (#performSelector:withArgument:withArgument:) the service provider can only pass up to 2 arguments.
Notifications:
- I wouldn't choose notifications because I think they are supposed to be used when more than one object need to be updated. Also, in this situation, I'd like to tell directly the delegate/target object what to do after the results are built.
Conclusion: At this point, I would choose the delegation mechanism. This approach provides more safety and allows easily browsing the code to follow the consequences of sending the delegate the results of the service provider actions. The negative aspects about this solution are that: it is a more static solution, we need to write more code (Protocol related stuff) and, semantically speaking, we're not talking really about delegation because the service provider wouldn't be delegating anything.
Am I missing something? what do you recommend and why?
Thanks!