Domain-Specific Frameworks for Distributed Computing

David L. Shang


INDEX


Frustration

These past few years you've seen the rapid growth of new technologies in distributed computing systems: CORBA, DCE, DCOM, PDO, JavaBeans,.. and you're supposed to adopt them in your applications to catch up the market demands. The growth of the Internet and the World-Wide Web, the demand for high performance information server, the boost of enterprise intranet applications, and the requirement of dynamic configurable systems have added the complexity into the development process.

Developing distributed application is not easy. People have got tired of using different network protocols and languages in a distributed environment, and found communications among heterogeneous objects too complicated to be convenient.

Developing distributed application based on CORBA, DCOM, or DCE is not that straightforward. Though they are language-independent and you can develop applications in your favorite languages such as C++, Ada, SmallTalk, or Visual Basic, you are still required to learn more because these languages are not specifically designed for the CORBA or DCOM architecture. You have to learn additional interface definition language (IDL) and understand their functions. You have to learn the distributed objects and their interfaces within the CORBA or DCOM system. When you program in C++, you must keep in mind that the object you designed in C++ is not the object in CORBA or DCOM. For each C++ object, you have to create a representative object within the underlying system and learn how to communicate with the representative. To establish such communication is usually not easy. If you have experience with DCOM in C++, you'll know how complex the communication between the client and the server is.

Some distributed systems provides their domain specific languages. For example, JavaBeans has Java and PDO has Objective C. They make distributed application development easier if the domain specific language is used. Using Java in JavaBeans, you are not necessary to learn the second language. The object in Java is exactly the object in JavaBeans. Communications among distributed objects are just method calls as usual. However, such convenience can only be obtained by using the specific language in the specific domain. Using Java for CORBA or DCOM, you'll lose this benefit. The object in the language cannot always be identical to the distributed object in the system if there is a difference between concepts. You have to either sacrifice the functionality in the system or take the trouble to dig into the underlying system. Besides, the language provided for distributed computing usually has a built-in model. The distributed application requirements may vary greatly. A single built-in model is too rigid to suit diverse application demands.

Transframe's Solution

The design philosophy of Transframe is to provide a diversity in terms of a simple, transformable framework that can be adapted to various specific problem domains. The framework provided by Transframe that can be transformed into high-level models for different requirements in various distributed applications.

In my July column, I have discussed why and how Transframe can support domain-specific computations. The diversity is obtained by unification. Unification not only provides a wider coverage, but also simplifies the concept as well as the language implementation. The fixed and built-in part (the hard part) of the language framework becomes smaller while the user-definable part (the soft part) becomes larger so that the frameworks are flexible enough to build various high-level application models.

In this column, I'll focus on distributed applications. Transframe makes distributed programming fun and easy. It delivers high level models that shapes distributed architectures required by various applications and the underlying systems.

The Beautiful Wrapper

You don't have to dig the underlying system. Transframe enables to developers to develop domain-specific frameworks that wraps the underlying distributed systems beautifully. With these frameworks, what you have to know is just the object your designed in the concept, it hides all the complicated communication/synchronization protocols. You don't have to design your distributed objects in one language (for example, in C++) and then have this object to communicate with a counterpart object in the operating system. Here is the contrast of using C++ and Transframe (suppose the underlying distributed system is DCOM).
Transframe
// module for clients
use DistributedInterface;
class Dictionary is
	   DistributedInterface
{
    method lookup(ItemName): Item;
    method addItem(Item);
    method deleteItem(ItemName);
}


// module for Server
use DistributedSever;
class Dictionary is
           DistributedServer
{
    method lookup(ItemName): Item;
    method addItem(Item);
    method deleteItem(ItemName);
  private:
    item_list: list of Item;
}
			
     
C++
[  uuid
   (E478374848-F23D-2984-9FBB-0457590A),
   ...
]
library Dictionary
{
   [ uuid
     (E478374848-F23D-2984-9FBB-04343435A),
     ...
   ]
   interface _IDictionary: IUnkonwn
   {
     Item lookup(ItemName);
     void addItem(Item);
     void deleteItem(ItemName);
   }
   ...
}
class DictionaryPro:
	public _IDictionary
{
  public:
    STDMETHOD(QueryInterface)
	   (REFIID riid, void **ppv);
    STDMETHOD_(ULONG,AddRef)  (void);
    STDMETHOD_(ULONG,Release) (void);
    STDMETHOD_(Item,lookup) (ItemName);
    STDMETHOD_(void,addItem) (Item);
    STDMETHOD_(void,deleteItem)(ItemName);
  private:
    Dictionary* m_pDictionary;
};	
class Dictionary :
	public IUnknown
{
   private:
    item_list: list<Item>
    IUknown * m_disp_interface;
    DictionaryPro * m_prog_interface;
   public:
    static Create()
    {
	Dictionary* pDic;
	IUnknown* pStdDisp;
	pDic = new Dictionary();
	pStdDisp =
	     CreateDispInterface(...); 
    }
    STDMETHOD(QueryInterface)
	    (REFIID riid, void **ppv);
    STDMETHOD_(ULONG, AddRef)  (void);
    STDMETHOD_(ULONG, Release) (void);
    Dictionary()
    {
	m_prog_interface =
	      new DictionaryPro;
	m_prog_interface->m_pDictionary
		= this;
	...
    }
    ~Dictionary()
    {
	delete DictionaryPro;
	...
    }
};
CLASS DictionaryCF:
	public IClassFactory
{
   public:
    static IClassFactory* Create()
    {
	return new DictionaryCF(); 
    }
    STDMETHOD(QueryInterface)
	    (REFIID riid, void **ppv);
    STDMETHOD_(ULONG, AddRef)  (void);
    STDMETHOD_(ULONG, Release) (void);
}

Without the help of tools, developing distributed server by using C++ is overwhelmingly complicated. In addition to C++, you have to understand interface definition language and all the concepts beyond, such as globally unique identifier(GUID), automation, dispatch interface, class factory, etc. You have take care of all the detail steps to register a class, to establish a method dispatch table, to create a distributed object, to answer a query interface request, etc. You must understand many kinds of auxiliary objects created for just one object in concept. You have to use handles or references to get the connections explicitly, and you should always to remember to release these handles to prevent memory leak.

The available tools such as AppWizard or ClassWizard in OLE Automation may alleviate such difficulty by generating all the DCOM related code in C++ automatically. You can follow the the wizard guide to create distributed applications without knowing the how and why. But the automation only simplifies the process, not the concept. You still need to understand the underlying concepts if you want to know what's really going on. You still have a hard row to hoe.

With Transframe's domain-specific wrapper, designing a distributed object is no harder than designing an ordinary object. The complicated concepts in the underlying system is wrapped by a very simple high-level concept: you simply write a distributed server with a number of methods in the same way you write a C++ class with a number of member functions. You focus only on the attributes and the functionalities of your own object. To design a distributed dictionary server, you just write the methods such as lookup, addItem and deleteItem. You no longer need a different language. Transframe itself is a better IDL that can deliver domain-specific frameworks to applications. All the complexity and difficulty for distributed programming are hidden within the domain-specific frameworks, namely, DistributeInterface and DistributedObject. For how this could happen, refer to The Beauty and the Power of Unification.

Domain-Specific Wrappers

To use languages that support distributed computing such as Java in JavaBeans, what you sacrifice is the flexibility. These languages have a built-in mechanism for distributed computing. They provide only a single fixed computation model. If there is a conflict between the application requirement and the built-in mechanism, if you want to create a distributed system in a heterogeneous environment, you can do nothing but hack hard as you were using languages that do not support distributed computing at all.

Though all communication needs could be modeled by using a single mechanism, it is much better to have a domain-specific solution. Transframe supports all of the common styles of solutions such as client-sever, peer-to-peer, and master-slave.

Here are some more examples.


Active Object


class NetServer is ActiveObject
{
   public:
	port ftpReuest(...);
	port telnetRequest(...);
	port serviceRequest(...);
}
			
     

Distributed Database


class Account is DistrubitedDatabase
{
   public:
	transaction deposit(int);
	transaction withdraw(int);
}

Peer-to-peer


class FighterPlane is
	Composite3DGraphic,
	MultiplayerObject
{
   public: // methods support multicast
	multi_method join(FighterPlane);
	multi_method quit(FighterPlane);
	multi_method newGeo(FighterPlane);
	...		
}
     

Parallel Computing


class MyComputation is ParalleNode
	#( InputType = T;
	   OutputType = S
	 )
{
	enter (x: T): S
	{
	   // my computation
	}	
}

With Transframe's solution, it is possible to build a technology shelf that contains various domain-specific application frameworks based on heterogeneous distributed systems.

With domain-specific architecture, application developers can map their solution into the frameworks without extra effort in learning a different concept. The complicated distributed systems are hidden under the friendly framework.