On the protocol adopted by Dycapo
It took us more than two months of discussions in order to decide which protocol to adopt for procedure calls in Dycapo.
As we are trying to extend an existing XML-based protocol, the first solution we took in consideration was to implement a remote procedure call protocol based on OpenTrip. That is, directly passing OpenTrip objects over HTTP methods.
Unfortunately, the most elegant solution immediately appeared as unsuitable for those reasons:
- It is against the DRY principle, as there exist many other RPC protocols out there
- A new RPC protocol implies the creation of new parsers and utilities for (Un)Marshalling data: nobody would write a client for Dycapo if he/she has to implement everything else from scratch
- OpenTrip is at a “0.1 draft” status. It may change very often in the future. I would not have the time to create and update parsers and utilities while developing Dycapo.
Therefore, we took the decision to adopt OpenTrip entities and propose OpenTrip Dynamic over some existing protocol. We looked at REST, XML-RPC and SOAP.
REST was seriously taken into consideration, as it is successfully used by Flickr, Delicious, Yahoo and Twitter (and many others). Even if it is not a protocol, it permits to define coincise locations for resources, and imposes some rules on the vocabulary used, creating self-descriptive messages. Moreover, there are many Django extensions that support REST.
Unfortunately, I could find more reasons against the adoption of REST than in favor:
- It is NOT a protocol but an architecture, or a set of conventions. Therefore, it does not define a format for data exchange. There exist SON, YAML 1.0, YAML 2.0, arbitrary XML formats. Every successful REST-ful WS either defines its own XML format or provides support for all these formats. We would like to be completely architecture independent. Therefore we need a strong data exchange format in order to handle our quite complex objects sent and received by and from clients.
- REST is a Resource-Oriented Architecture. Everything is thought around representation of resources. Dycapo implementation would fit with difficulty in this way of thinking. A Service-Oriented Architecture fits our needs and way of thinking.
- It may still require a lot of work on the client side caller of the library to make use of data (custom serialization and so forth)
Regarding XML-RPC and Soap, we know that they are very similar (first drafts of Soap were about XML-RPC with namespaces). After analyzing both of them, we agreed on the adoption of XML-RPC because
- It is lighter than SOAP: you just put objects/method calls encoded in XML in HTTP methods. SOAP adds overheads by using namespaces, envelopes, a header, body and fault sections.
- It exists since 1998. It is supported by all mobile devices, from iPhone to Android to Symbian. Moreover, its data exchange and message formats are very simple. It would be easy even to write a library from scratch. As an example, look at how tiny and simple is android-xmlrpc. SOAP is not widespread on mobile devices as XML-RPC is. Its complexity is also a barrier to write libraries and parsers.
- XML-RPC permits us to exchange quite complex objects regardless the implementation of server and clients. Automatic marshalling of data is often possible. Developers just have to look at our method signature and object structure and forget about the RPC structure and formats. Everything should be automatically handled by existing libraries
As a tiny example, look at the following code. It is a snippet of the current method call when searching for a ride. I just included the generated XML-RPC for the second parameter, as the first one is an object of the same type.
dycapo.search_trip ( Location source , Location destination )
<methodcall>
<methodname>dycapo.search_trip</methodname>
<params>
[..]
<param>
<value>
<struct>
<member>
<name>georss_point</name>
<value><string>1.0,1.0</string></value>
</member>
<member>
<name>point</name>
<value><string>dest</string></value>
</member>
<member>
<name>leaves</name>
<value><string>2010-03-12 14:36:54.772156</string></value>
</member>
<member>
<name>label</name>
<value><string>office</string></value>
</member>
</struct>
</value>
</param>
</params>
</methodcall>
See how simple and elegant it is? We are simply passing an object, represented as a struct, with 4 attributes:
- georss_point: “1.0,1.0″
- point: “dest”
- leaves: “2010-03-12 14:36:54.772156″
- label: “office”
Don’t try to reason about types, names and quality: we are still experimenting.
Recent Comments