views:

76

answers:

1

I am designing a (SOAP-like) inter-process communication protocol for making function calls over a network. I want to make sure an older client can talk to a newer server. After thinking over it for a while, it seems like the only thing I can do are:

  • avoiding API changes
  • make it possible to add functions
  • make it possible to add function parameters

However, when the server's functionality thoroughly changes, this isn't enough. For example:

  • a parameter that has to be moved from one function call to another.
  • a parameter type that changes, for example from an integer to a string.

My question is: can this kind of changes be made while staying backward compatible, or is the only option simply not to make them?

Note: I know, I am suffering from the not invented here syndrome, but in my opinion that doesn't invalidate this question.

+1  A: 

You haven't said exactly how you are implementing the IPC, so I might be making some poor assumptions here. Anyway, off the top of my head, there are a couple approaches to an issue like this.

First, regarding the point of parameter order/type changing, you can use a dynamic language like Python to get around this.

>>> def discriminant(a,b,c):
...     return b*b - 4*a*c

>>> discriminant(1,8,2)
56
>>> 
>>> discriminant (c=2, a=1, b=8)
56

Python allows you to use named parameters so that you can name variables in any order you like, and all variables are dynamically typed.

A less efficient approach to the ordering issue might be to pass all arguments in as a dictionary (written in Python, but can be adapted for whichever language):

>>> def disc2(in_dict):
...     return in_dict['b']*in_dict['b'] - 4 * in_dict['a'] * in_dict['c']
... 
>>> d = dict(a=1, b=8, c=2)
>>> d
{'a': 1, 'c': 2, 'b': 8}
>>> disc2(d)
56

To expand upon this idea, you could also contain a "version" field in your dictionary (or arguments, whatever) to allow the server to adjust accordingly to the incoming arguments. It doesn't have to be a dictionary, you could put a version field in the packet containing the IPC message as well. This might be a contrived example, but you could account for missing fields this way as well.

>>> def disc3(d):
...     if d['version'] == 1: # original spec
...             return d['b'] * d['b'] - 4 * d['a'] * d['c']
...     else: # newer clients returning smaller values of c
...             return d['b'] * d['b'] - 4 * d['a'] * (2*d['c'])
... 
>>> d['version'] = 1
>>> disc3(d)
56
>>> d['version'] = 2
>>> disc3(d)
48
Mark Rushakoff
Thank you very much for your response.
Dimitri C.