Sponsored Link •
A third disadvantage of the object approach involves testing. My last C++ contract, before I switched to Java, was with a company that provided a distributed system that enabled servers at insurance companies to exchange data with clients at general agents. Over the years, this company had switched technologies several times. Given that customers are naturally hesitant to upgrade a system that is already working, especially if they would have to pay for the upgrade, this company was still supporting just about every client or server incarnation it had ever shipped. When it came time to test a new software release candidate, the software quality assurance (SQA) department would pull out its test matrix, a two-by-two matrix with clients on one axis and servers on the other, to plan the test. If the release candidate was a client, for example, SQA would want to test that client with all possible servers with which it might be used. How could SQA know if this client was going to work with every possible server if it didn't test the client with every one? (OK, to be honest, this SQA department didn't usually get to test the whole matrix. They just wanted to -- but that's a different story.)
One of the challenges of the mobile object approach to distributed computing is that, given that objects can glide so effortlessly across networks, it is almost impossible to know where an object you expect to send might land or where one you expect to receive might originate. The problem is not that the test matrix is too big, but that it is undefined. So how will you ever achieve robust, reliable distributed systems based on mobile objects if you can't test the performance of those mobile objects in all possible environments?
In the world of mobile objects, you simply can't test every possible client-server combination. You can, however, build a test matrix out of some known, and hopefully representative, subset of combinations, and test those. You can also do standalone tests for compliance with the contract to which the client or service is supposed to adhere.
I think that one key to achieving robust, reliable distributed systems, whether they're based on documents or objects, is a well-defined contract between the parties. Just as with mobile objects, you often won't be able to test a protocol-based server against every kind of client that will connect with it, but you can test the server's compliance to the protocol specification. To have meaningful compliance tests in either the object or protocol approach, the specification of the contract against which you are testing compliance needs to be detailed and complete.
In addition to having well-defined written specifications, it will also be important to have good compatibility test suites. Whether you are writing an implementation of a service API, or a client, a test suite that identifies areas where your client or service depart from the specification will be an invaluable tool. If a compatibility test suite isn't included along with the specification and javadoc documentation for an API, then everyone will likely interpret the documentation in slightly different ways, resulting in distributed systems that are slightly unreliable.
A fourth disadvantage of the object approach is that it doesn't scale well on the server side. To be certain a server will be able to handle large numbers of client requests concurrently, the programmer of a server needs to be able to control how and when finite resources such as threads, sockets and file handles are allocated to service client requests. If each client were to send the server a mobile object through which that server would interact with the client, then the server can't be certain how many threads, sockets, and file handles each of those client objects would consume, or when they would consume them. This is why in the standard Jini approach, the client receives a mobile object from the server, not vice versa. The client interacts with the service via the object interface. The server, by contrast, interacts with its service object (which is running in the client) via a network protocol.
The trouble with the standard approach is that, sometimes, we will want servers to act as Jini clients. I recently developed a Jini chat service for Sun Microsystems that, had a laptop not been stolen the night before, would have been demonstrated during the Friday keynote at JavaOne. To participate in the chat service, a client looked up the chat service in a Jini lookup service. The chat service objects of all clients exchanged messages and other information by writing entries to a JavaSpace. Once the client received and started using the chat service object, the object contacted a lookup service to retrieve proxies to a JavaSpace and a transaction manager. The chat service object then fired off several threads to renew leases and to monitor messages being posted into the chat room, and people entering and leaving the room.
While working on the chat service, I at one point had a phone conversation with John Whetherill, a Jini evangelist at Sun. Whetherill had implemented a chat program on the wireless RIM pager that was sold at JavaOne, and we needed to discuss how to integrate Whetherill's functionality with the Jini chat service on which I had been working. The only way to interact across the network from the RIM was via HTTP, so Whetherill had written a servlet that accepted HTTP messages from the RIM, which allowed RIM users to chat with each other. On the phone, Whetherill and I brainstormed about how he could enhance his servlet so that RIM users could participate in the Jini chat service.
My first inclination was to recommend to Whetherill that he simply turn his servlet into a client of the Jini chat service. Given that the chat service functionality was already implemented in the bowels of the chat service object, I figured the easiest thing for Whetherill to do would be to have his servlet grab a chat service object for each RIM user, and just invoke the methods of the object like any Jini client. The trouble, of course, was that each service object fired off several threads and opened several sockets, and we were expecting that upwards of 500 RIM users could potentially end up trying to chat at the same time. We talked about many different ideas, but we couldn't figure out how to get the servlet as Jini client approach to scale. In the end, Whetherill had his servlet simply interact directly with the JavaSpace, replicating in his servlet much of the code that made up the chat service object.
Ultimately, I think the way to deal with server-side scaling when servers want to act as Jini clients is to have multiple servers available and some way to distribute the incoming mobile objects among those servers based on their available resources. But I also suspect that the general case will be that servers will be speaking protocols to clients, or to proxy objects injected into clients.
One final potential disadvantage of mobile objects over mobile documents is download time. An early complaint about Java applets, for example, was that they took too long to download compared to Web pages. Of course, you can have huge Web pages filled with lots of gratuitous graphics. Such pages could easily take longer to download than a svelte Java applet. Download time has to do with bandwidth and the amount of data being transmitted, irrespective of whether the data is HTML text or bytecodes.
One of the reasons Web pages are perceived to be faster is because entire services are split up among many different pages, each of which is downloaded individually. For example, when using the Yahoo email service, you may end up downloading tens to hundreds of individual pages each session. Users have been trained to accept a certain amount of wait time for each Web page. When an applet comes down, however, the entire service is typically downloaded at once. After an applet arrives, the users will usually not have to wait anymore. But even if the wait time to download an applet is less than the cumulative wait time to download each individual page of a service, the users still perceive the applet is slower because the wait time is all up front.
I think the extra time cost of downloading large objects can be managed in three ways. First, objects, like Web documents, should be kept to the minimum size possible. Second, there is no reason objects can't download other pieces of a service on demand, much like web pages are requested one at a time, so long as users are trained to expect this kind of behavior. Third, you can use caching to reduce the distance objects must travel across the network, and hence the time the client (and user, if present) must wait for them. (Of course, increases in bandwidth will also help address this problem.) I believe download time is something that needs to be, and can be, managed, regardless of whether you are downloading objects or documents.