What is the correct pattern to provide client-server backward compatibility?
I'm developing a client-server application and can't force users not to use older versions of client, or even other clients, since the protocol is WebDAV开发者_StackOverflow社区.
What I need is to support all of them, with some kind of backward compatibility, so that server side will behave different way, depending on what client version it is working with.
My question is how to prepare my application to this situation, before facing it. Do I need to use some design pattern? How to design backward compatibility?
If you create a proper API (Facade design pattern) for your server, you'd make your life easier in the future.
suppose your server provides an API that consists of services A, B & C. These services are implemented in the business logic layer. access to these services from the clients is always through the facade, no direct access. so your facade (version 1) exposes A, B & C. no big deal so far...
now suppose you need to add service D, remove service B, and change service C. you create a new facade (version 2), which exposes services A, D and an updated C. in your business layer you would add the logic for service D, mark B as "obsolete", and as for the change in C, it depends if the change is backward compatible. if yes it's easy, just add an overload. if service C now works completely different, implement it as a new service. sometimes though there are changes that break old clients...
the Facade itself could be a web service (my preferred solution in most cases), and has no business logic of it's own, its only responsibility is to delegate the call from the client to the approproate service.
I think your tricky design problems are at a different level than Design Patterns address.
Of course you can apply Facades in front of your core business logic, exposing different interfaces
MyServiceV1 { // the original interface
MyServiceV2 { // the new interface
and so on. I see the interesting design points coming from how you implement the old interface with the new implementation. For example suppose in the old interface you have a method creating some business item
createItem( String name,
Integer value);
and in the new version you have
createItem( String name,
Integer value,
String justification
);
So when a v1 request arrives at the facade it won't have data for "justification", so what should the facade do? Possibly add in some "UNKNOWN" value, but what you do is not so much a matter of design as a matter of understanding the business requirements. Clearly there are much tricker problems of this kind depending upon the different kinds of change made in creating the new version of the services.
So, first work through interface by interface understanding the requirements, the policies for dealing with the different chnages. This will lead to various implementation problems and when you get to those you may start to see patterns in the implementation that drive you to adopt explicit Design Patterns.
I think the design pattern to use in this situation is the strategy design pattern.
Roughly...the idea is that:
- the
Server
instance is always listening for new connections. - when new connections are established with the
Server
, theServer
creates an instance ofClientConnection
to manage it. all subsequent data received from that connection is routed to and handled by the instantiatedClientConnection
. - each
ClientConnection
manages all communications between theServer
and an individual remote client host. - the first thing a
ClientConnection
does is negotiate with the remote client, and figure out which version it is. once this is done, theClientConnection
will instantiate the appropriate implementation of theServerBehaviorStrategy
to handle all subsequent communications of theClientConnection
.
This way, all the programming of behavior specific things are cleanly isolated in the separate implementations of the ServerBehaviorStrategy
interface.
精彩评论