Designing Client-Server Interface

Date: 16-Nov-99

Related Sites


o-< Problem: CORBA, like DCOM and RMI, is a mechanism to call objects on another computer. However, designing the interface of those remote objects can be tricky.


o-< Jacques deMolay described one way to handle this:

[About a distributed application with the GUI on the client side and the business logic on the server side, and CORBA interface in between]

The unusual design decision is that the CORBA interface implemented by the client consists of a single method called acceptRequest(). The CORBA interface implemented by the server consists only of the methods notify() and acceptReply(). Each of these methods takes a string (sometimes formatted in XML, sometimes not) as a parameter. The two frameworks are responsible for parsing this string and using factories to create the appropriate classes to handle the passed message. [...]


o-< Andy P. Langton explained the advantages:

[...] The scenario for the reason behind this kind of thinking goes something like this:

  1. You are wanting to build components using an incremental development approach.
  2. Then at each increment the components evolve which forces the logical interface models to change.
  3. The components are in use (have been delivered) and so their existing interfaces cannot physically change, therefore new interfaces are implemented for each version.
The result is a larger set of logically unrelated interfaces that may have duplicated interface methods in one interface version that supersedes an earlier version.

The difficulties highlighted in this scenario are further compounded if third-party components are involved.

Options are:

  1. A thorough analysis and design to establish a robust interface for the logical model early in the development (this undermines the purpose behind using incremental development).
  2. A complete redesign and implementation of each components physical interface at each deliverable, maintaining consistency between the logical interface model and the physical (this breaks existing 'contracts' between components thus undermining one of the purposes behind building components [re-use]).
  3. Producing a generic physical interface that is resilient enough to withstand changes to the logical interface model. (this loses compile time 'syntax checking' and additional effort is needed in implementing the interface. [I don't go for "harder to understand" - a good set of logical and physical models should clarify the design]).
So do you want a smaller set of version independent components with 'thin' component interfaces which are resilient to change, or a smaller set of components with 'thick' component interfaces covering each component version, or a large set of component versions with a 'thinner' component interfaces?

The choice is yours!


o-< Robert C. Martin pointed out the drawbacks:

Sounds like you have reduced CORBA to a pair of sockets. Why pay the overhead? If you want a pair of sockets that you pitch XML packets over, then use them.


Passing XML between communicating processes is probably the most extensible mechanism you can use. If the format of the data moving between processes is very likely to change a great deal, then the XML approach is not a bad one. It does, however, reduce all errors to runtime errors; and forces you into lots of runtime checking.

If the protocol between the intercommunicating processes is not likely to change very much, then explicit interfaces are likely to be faster and more reliable.


o-< Mark Collins-Cope put it even less mildly:

While they are at it, they could 'hide' themselves from the complexity of the GUI interface having only two methods used with the GUI: drawBitmap and getClick. They could then implement their own window system over the the existing one, and thus save themselves having to learn the interface to the GUI :-).

On a slightly more serious note, it sounds like for whatever reason they are genuinely scared of using CORBA. Perhaps they don't understand CORBA properly, and could do with some training. Something is definitely lurking behind the suggested approach - with the approach they are suggesting you might as well use Sockets directly.

I do not think what they are suggesting is a good idea. The will end up re-inventing many aspects of the CORBA wheel.


o-< H. S. Lahman suggested another approach altogether:

[...] I believe the way to think about this problem is to raise the level of abstraction by considering the business problem alone first. The 'GUI' and 'Business' applications talk directly to one another. In so doing they send one another messages. At this level of abstraction the mechanism of message transfer is not relevant; it is a low level implementation detail that depends upon the computing environment rather than business rules. Those messages define the interface between the applications in terms of the business semantic.

When you select a specific communication mechanism you effectively insert that mechanism between the 'GUI' and 'Business' applications to transship the messages. However, that should not change the interface that 'GUI' and 'Business' use. Thus I would expect the interface to the communication mechanism to expose exactly those interfaces (i.e., the business semantic).

You have chosen a specific implementation in CORBA for the communication mechanism. The applications do not care about this and should not be affected if you decide to switch to DCOM or if CORBA provides the anticipated new services. In addition, the semantic of CORBA is entirely different than the semantic of the application messages. These considerations drive the development of 'client' and 'server' wrappers around CORBA. [...]


o-< Patrick May described how such wrappers can be made:

[...] My approach was to create an abstract class that defines the interface for each potentially distributable class. From this class I derive an implementation class and a CORBA proxy class. I then create a CORBA implementation class that binds to the IDL interface. This class uses the first implementation class for its business logic.

For example, consider the class Foo that may be distributable. I first create an IDL interface for it and an abstract C++ class named Foo that defines the interface. I then create the class FooImpl that inherits from Foo and implements the interface (in standard C++, no CORBA datatypes) and the class FooCORBAProxy that inherits from Foo and implements the interface by calling a CORBA implementation.

The CORBA implemenation class is called FooCORBAImpl -- it implements the Foo IDL interface but passes all the method calls on to a private copy of FooImpl. This keeps the business logic in one and only one place.

Now, by using factories or, possibly more elegantly, some kind of registration scheme, I can present the applications with only the Foo interface. They never have to know if they're actually using a local FooImpl or a remote FooCORBAProxy. [...]


o-< More Info:

Douglas C. Schmidt, Overview of CORBA

Bert Bos, XML in 10 points

Vince Huston, The Proxy Design Pattern

Robert Orfali, Dan Harkey,
Client/Server Programming with Java and CORBA