views:

71

answers:

2

I'm building an API that post a given message to different platforms (Twitter, FaceBook...).

The problem is that for each platform I may change the wrapper that allow me to post the message. For example, in C# I can post a message on twitter using the yedda API or the CsharpTwitt API, for FaceBook I'll use others APIs...

Hence, I have to be able to use different wrappers to post a message for each platform. alt text

For now, this is the design I use, but it's clear that it will be too complicated if I add more APIs with more wrappers.

I think it's a common design issue and I'm wondering

  1. Am I using the best approach to have a well designed API?
  2. Otherwise, what is the best design for such a situation?
  3. What design pattern is applicable here?
+2  A: 

I like this approach because this way you can dependency inject whatever wrapper you wish and change it with a single line of code.

For example

Bind<Yedda>().To<ITwitter>();
Bind<FBWrapper>().To<IFacebook>();

And now throughout the code ITwitter actually maps to the Yedda wrapper.

Dependency injection could be something worthwhile to look at.

randomguy
I think it's the thing i'm looking for, i'll deep dive into Dependecy Injection.I know that's something intesively used in frameworks so maybe it's the best solution for my API.
iChaib
"I like this" actually referred to your original design, which allows DI (dependency injection). I think it wasn't obvious from that sentence. Anyways, I really think this is a flexible choice. You can focus on designing the generic interfaces and don't need to worry about the actual wrappers. Just implement everything against IBrigde, ITwitter, IFacebook, IPlatformN. The last three inherit IBridge. Then, for example, inherit Yedda and CSharpTwitt (and whatever 'wrappers' you wan't) from ITwitter.
randomguy
Because you have coded everything against those generic interfaces, you can then DI the wrapper of your choice by "configuring" (process called binding in the DI world) to what wrappers the ITwitter, IFacebook and IPlatformN interfaces map to. That binding, like I wrote in the example, is a one-liner in the beginning of the program and you are good to go. Ninject and Moq would be two quite popular DI frameworks for C#. DI can be a bit hard to grasp (took me a while), but once you get it, it makes perfect sense.. Like in your scenario.
randomguy
Once again, using the design i suggested, i'm afraid that it'll be a mess handling all this wrapper for all this platforms.Don't you think that a decorator pattern could be suitable for this case?
iChaib
How I understood your design: Each platform has an interface which is inherited from `IBridge` and furthermore each platform interface can have one or more derived implementations. Those derived implementations (or alternatively we could call them wrappers), like `YeddaTwitter:ITwitter`, then would have concrete instance of the "API object" inside them (`YeddaTwitter` contains instance of `Yedda`).. I think this would be more like the facade pattern. For you to be able to use DI, you have to provide some common interface. For each different "API object", you need an interface implementation.
randomguy
Does this make sense?
randomguy
yeah this make sense, using facade is relevant but i think it doesn't avoid the confusion and the complexity of handling too many classes.
iChaib
Well, to make different things (APIs) share similarities, you have to have some common functionality wrapped into an interface. In bare minimum, if you have N wrappers and you want to abstract some common similarities, then you would need one interface and N implementations of that interface. This allows the flexibility to make some underlying manipulation with each of the APIs inside the implementation, if such is needed.
randomguy
+1  A: 

you may use abstract factory if your create different message wrappers.

abstrcat class Abstractfactory{
       IBridge Create(int type);
}
class Platrofrm1facroty:Abstractfactory
{  
  //type m.b. for Wrapper1 to wrapperN 
  IBridge Create(int type);
}
class Twitterfacroty:Abstractfactory
{  
  //type m.b. for Yedda or CshartTwitt
  IBridge Create(int type);
}
Arseny
ok for the factory, but i think the complexity i have to handle still remain.I mean I have 4 platforms with 4 wrapper each, i'll have to handle 16 factories, couldn't we avoid this complexity?
iChaib
@iChaib well I think you need only 4 concrete factories each per platform. to create a concrete wrapper you need to pass a flag to Create() method it may be a constant or enumerator or whatever. so the factory could handle this flag and create a concrete wrapper.the beauty of abstract factory is that you can create a set of ojbects with own traits. Say your Platform1_factory could creat 4 wrappers for this platform, Planform2_factory creates another 4 wrapper with Platform2 traits.
Arseny
yes indeed @arseny but the thing with the factory is that i've to write the code to handle each wrapper in the class, within a switch block for exemple, hence, if i want to add another wrapper later, i'll have to change the factory code, and recompile my app, which i don't want to do.Am I wrong?
iChaib
@iChaib it depends on how you gonna build up your code. One approach is to split code into assemblyes each for concrete factory. so that you need recompile only changed assembly. Moreover you may think to make it as add-in pattern to dynamically load needed factory at run-time. at this case you may support customer only with his concrete factory (assembly) and not to give him all of them.
Arseny
but is there a way to avoid recompilation ?
iChaib