How to introduce a special case in the API design?
I'm developing API for a library which will be used by a customer.
The library should provide single interface to access several remote resources. So, I should create API and several its implementations (correspondent to the number of remote resources).
I met the next problem: all resources except one has API for logging in. So, I can create method
void authenticate (String login, String password) throws AuthenticationException;
But I can't pass authentication to that one resource with this method.
To pass authentication on that resource I need to perform some actions and receive URL for authentication, then I should give this URL to the caller, caller program use some magic to pass authentication, and after that it should give me back "the flow".
So now I need 2 more methods to achieve necessary result:
String getAuthenticationURL () throws Authentica开发者_如何学CtionException;
void postAuthentication () throws AuthenticationException;
If I add these methods to the API then I'll have to create their empty implementations (or implementations which throws RuntimeException) in all API implementations for 'normal' resources.
If I do not add them to the API but add them only to one concrete implementation then I'll break the whole idea of unified API.
The approach with these 2 methods is only one of at least several possible solutions. So, any advices and suggestions are welcome.
You could have an abstract base class with two concrete child classes--each child containing a different authentication mechanism.
The other (probably better) method, however, might be to create an abstract "Authentication" object with two APIs (two concrete implementations). One would have your authenticate method, the other would have your get/post.
The advantage here is that your authenticate class contains all the functionality specific to authentication.. might even have some of the code in the class that is an abstract parent of your two authentication objects.
You can still keep your authenticate method if you like, it's implementation would simply be delegated to the authenticate object.
Note that this also gives your user a more "Minimal" api whereas extending your original interface gives you an entire second copy & paste class to consider.
Also, consider passing the correctly constructed authentication object to the constructor of your original class. Makes for a nice, clean system.
Whenever I break a piece of functionality into it's own class like this I always gain some great refactoring possibilities.
I love Bill K solution, but you could also have your authentication classes work like some kind of factory, providing you with a logged in resource when the authentication is done.
This way the first step for the user would be to chose the right authentication method, authenticate and get it's resource ready for use.
精彩评论