Service with a Large API

kerry.kim.russo's Avatar

kerry.kim.russo

09 Jul, 2012 03:44 PM

Hi All,

Maybe the subject line didn't make much sense so let me try and clarify.

I'm following a tutorial for Robotlegs 1 (so why am I posting in RL2? I'm actually using the RL2 but find this tutorial to be easy to follow. Any answers can be given with either version in mind. Also, the tutorial I'm following can be found at http://www.developria.com/2010/06/an-introduction-to-robotlegs-a-2....). If you don't feel like reading the tutorial, the gist is that services should be separated into four distinct classes:

  1. The service class which implements some kind of interface, which will make testing easier among other helpful things
  2. The parser for the data that gets returned
  3. The custom event and
  4. Its VO

The tutorial uses the Twitter Search service. The service only returns data formatted one way, and therefore only needs one parser. It's a good example to learn from, but in the real world, or atleast my world, it's too convenient. I'm working on a project where I need to request data from a smartfox server. It has a moderately large API that returns differently formatted data depending on the function that's called unlike the Twitter Search example which only returns data formatted one way.

My initial thought is that I don't want to create a service class for each public function as that would probably be class overkill. In the tutorial, the parse is injected into the service class. I was thinking of creating only the necessary parsers (and the necessary VOs) and then inject the required parser at run-time.

What would ya'll suggest?

EDIT: One more question, should I be making an interface for a service like smartfox server, possibly something like IMultiplayerService?

  1. Support Staff 1 Posted by Ondina D.F. on 12 Jul, 2012 09:34 AM

    Ondina D.F.'s Avatar

    Hi Kerry,

    I don’t have enough time these days to get into details on the subject, but I notified Stray and Shaun, and hopefully if they aren’t too busy you’ll get an answer :) I’ll also tweet your question.

    Anyway, I’d say yes to making an interface for your services.

    Cheers,
    Ondina

  2. 2 Posted by simon on 12 Jul, 2012 11:14 AM

    simon's Avatar

    in the scenario of hitting a large API from a service then I would probably have multiple service classes handling specific logic, not necessarily a service class per method more like a service class which would handle say the client API, then a service class to handle the room API etc (I am not familiar with the smart fox API). This will hopefully enable you to have a tighter focus on parsers used on a service class basis.

    Next I would consider one of two routes for the parsing, I would either:

    1) Inject your specific parsers into the service class and then choose which parser to use based on the method based on the api response.

    2) Have your service class method dispatch the response in an event or signal which will then be process by some sort of factory class. So maybe a command who's sole responsibility is to receive the response data, parse it and then distribute the result data in the appropriate format via a signal or event.

    Cheers,

    Simon

  3. 3 Posted by kerry.kim.russo on 12 Jul, 2012 12:53 PM

    kerry.kim.russo's Avatar

    @Ondina Thanks! Also, the only reason I asked about making the API for smartfox server was because I was thinking that the API was pretty specific to SFS so it wouldn't easily be swapped out for another service anyway. Then it occurred to me that even if I will probably never use a different Multiplayer Server other than SmartFox, at least I could then create a new test class to mimic the server and easily swap that in and out.

    @simon Appreciate the suggestions! Let's see if I understand you correctly. You're saying that I should break the SFS API up into smaller chunks (by creating an intermediary class? Using your example I should create a class called SFSRoomService which gets injected with a SFS instance but only exposes the functions that deal with the room?)

    Thanks for the help. I'm learning a lot. May take a while though since I'm not really a hardcore programmer.

    EDIT: 'the only reason I asked about making the API for smartfox server'; i meant interface, not API

  4. 4 Posted by simon on 12 Jul, 2012 01:35 PM

    simon's Avatar

    Yes exactly. Not knowing how the SFS works I would guess your simply hitting the api through a REST api or something similar so you would only need to either inject or pass in the actual SFS url no?

  5. 5 Posted by kerry.kim.russo on 12 Jul, 2012 01:43 PM

    kerry.kim.russo's Avatar

    SFS is actually a socket connection. So maybe it's not technically a web service since most of the time it's pushing data rather than being asked for data. Maybe that changes everything??? I figured it still fell under the S in MVCS. I'm actually pretty new to SFS as well so excuse my lack of knowledge on it.

  6. 6 Posted by simon on 12 Jul, 2012 01:45 PM

    simon's Avatar

    I don't see much of a difference in how you would handle this either way to
    be honest.

  7. 7 Posted by kerry.kim.russo on 12 Jul, 2012 01:59 PM

    kerry.kim.russo's Avatar

    You mean in regards to injecting the URL? I could certainly inject the ip address and socket into my SFS client class but would only want one instance of the client to be injected into all of the surrounding service classes.

  8. Support Staff 8 Posted by Shaun Smith on 13 Jul, 2012 11:06 AM

    Shaun Smith's Avatar

    Whenever you integrate with a 3rd-party API you should wrap that API in an "anti corruption layer". This ensures that your application is coded against an API that you control. When the underlying 3rd-party API changes you only need to change your wrapper. In most cases the surface area of your wrapper API is much smaller than the full 3rd-party API.

    Once you've done that you can inject your new service (the wrapper) into other, higher level (application specific) services. For example:

    Wrapper (psuedo code):

    IRestService
      function post(url, params):Token
      function get(url, params):Token
      function put(url, params):Token
      function del(url, params):Token
    

    User Service:

    UserService ( restService:IRestService )
    
      createUser(params):Token
        -> return restService.post('/users', params);
    
      loadUser(id:String):Token
        -> return restService.get('/users/' + id);
    
      updateUser(id:String, params):Token
        -> return restService.put('/users/'+id, params);
    
      deleteUser(id:String):Token
        -> return restService.del('/users/' + id);
    

    The RestService deals with low level details - it is the anti corruption layer. It is injected into the UserService. The UserService is higher level, and delegates operations through to the RestService. The IRestService is an interface, so multiple implementations could exist (JSON, XML, Socket, CSV, YAML etc). You can swap out the implementation without affecting any of your higher level services as all they care about is the interface.

    Hope that helps!

  9. 9 Posted by kerry.kim.russo on 13 Jul, 2012 12:33 PM

    kerry.kim.russo's Avatar

    That clears things up a lot! Thanks!

  10. kerry.kim.russo closed this discussion on 13 Jul, 2012 12:34 PM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac