S for Service. A new kind of thing that should also be encapsulated.*
A good service layer is easy to use and has entirely out of the box functionality. I usually do this kind of thing the same every time, using a pattern I’ve seen around that works well. For every service that an app needs to connect to I have a utility class that has an API for requesting specific things from the service. All networking code required to talk to a service is encapsulated inside one of these classes and the class just exposes a nice, handy API to get things done.
A good name for one of these things is usually My<#SERVICENAME#>Client or My<#SERVICENAME#>Service, where ‘My’ is your class prefix and ‘SERVICENAME’ is the actual name of the service the app is requesting things from. I lean towards MySomethingClient because it is more correct, since our app and specifically this utility class is technically the client to the service that it’s hitting.
Watch out for including things like ‘REST’ in a class name, because all things network specific are an implementation detail. I would reconsider names like Fetcher and DownloadManager as well. While we know the class is doing these things, I think this behavior terminology is too specific to include in a class name. Plus Fetcher sounds kind of lame, and Manager is a name I think should only be used wisely, if ever. Also, I personally don’t think Controller makes sense here, because it is something else, and at a project level the behavior of a service class called Controller usually isn’t clear.
So here’s how I do it.
The client API will have methods like…
- (void)requestThingamajigsWithCompletionBlock:(void (^)(NSArray *thingamajigs, NSError *error))block;
- (void)requestThingamajigWithName:(NSString *)name
completionBlock:(void (^)(FOOThingamajig *thingamajig, NSError *error))block;
All API methods call an an internal method like…
- (void)requestValueForEndpoint:(NSString *)endPoint
completionBlock:(void (^)(id result, NSError *error))block;
Each API method’s implementation builds an end-point, calls the request method and handles the result, which usually comes in the form of a JSON or property list object. A handy category for unpacking property list objects is arrayOfClass:forKey:. Once this internal method is set up it’s fast and easy to add more API calls. APIs that create or change things usually call an internal method like sendPOSTValues:toEndPoint:completionBlock:. And optional behavior like canceling and queueing can be added as necessary.
That’s about it. Service is a new layer that should be encapsulated, clean and easy to use, like Cocoa.
Here’s a quick and dirty sample I put together. If you have any opinions, feedback or better designs for this kind of thing, hit me up.
* Chris Parker’s great post on coding ruthlessly motivated me to finally post this.