Another example is Visual Basic. The external and internal representations of an application are laid out visually, as objects in (Microsoft's version of) Basic. The components are edited in-place, not just by setting parameters but also by attaching scripts, e.g. the response to a button press.
Finally, we have the Web page. The components of a page can be arbitrary data objects; the browser just has to have external or internal utilities for viewing them. The user can set preferences for which data types get which viewers. The markup language and the browser take care of the layout. With new standards like LiveConnect and JavaBeans, components can also talk to each other and form a complete application. Of course, OpenDoc and OLE also want to get in on the act. Web pages will be a crucial battlefield for component software, especially with the advent of Network Computers (NCs).
However, previous frameworks stopped there. When it came to implementing your Document class, you were on your own. Many applications, such as word processors, are naturally composed of different kinds of components like text, rulers, and figures. Such applications had to come up with their own data structure for representing the Document and the components, their own data transfer mechanism between components, their own linking and constraint mechanism, and their own scripting protocol. Third-party components were rare, because they had to conform to the application's proprietary component interface.
The new frameworks have all of this functionality built-in. Now you can build up your internal Document representation hierarchically, just like you can for the visual representation. Compound documents provide a standard interface for components, a data structure for a dynamic collection of components, a data transfer mechanism, a linking mechanism, and a scripting protocol. Because of this open standard, third-party support is automatic. And thanks to the distributed object foundation, components can come from and link to anywhere on the network.
Automatic support for compound documents essentially reduces application programming to component design. Since the component interface is standard, components don't have to come from one manufacturer. Rather than applications, companies can provide component suites which users can assemble however they wish. This significantly lowers the entry cost into the software market.
There must be some way for the compound document to choose the appropriate View or DataService for each component. Here are three possibilities, all of which can be tried in succession:
OpenDoc also has an intermediate LinkSource object which holds the list of subscribers. If some of the subscribers are remote, the distributed shared memory would normally create Proxies for them. However, this is wasteful, so the LinkSource records subscribers by their global names and uses the ORB to look them up. This is a common pattern for avoiding Proxies.
The solution taken in OpenDoc is for the sender and recipient to negotiate. What is sent is not simply a bare number or string, but rather data held in a "carrier" object called a StorageUnit. The carrier describes which formats are available, e.g. as an icon, as a floating-point number, in French, or in monochrome. The receiver examines the formats and picks one it understands. The sender may have provided copies of the data in these other formats, the carrier may automatically convert the data into another format, or the carrier may request the sender for the specific format.
The receiver can also request a link back to the carrier. This is the "Paste With Link" option. Thus drag-and-drop can be used to establish dependencies.
The carrier system works, but uniform data transfer still requires elaborate and standardized systems for describing and converting data, not just at a representational level but at a semantic level. It will be interesting to watch further developments in this area.
OpenDoc provides a standard infrastructure for handling events. At the most basic level, events can dynamically inspect and modify component properties. This is useful for application builders and debuggers. Events can also contain complex queries involving named parts, ranges, and conditions. For example, "delete seconds 5 through 30 of the first movie of paragraph 3 of my document." By handling such events, OpenDoc essentially provides a higher-level naming scheme beyond what the shared memory provides.
Incidentally, OLE also uses such complex names, called monikers, pervasively. For example, a link can have a moniker, rather than a specific object, as its source. This is the analogue of a symbolic link in Unix. A spreadsheet can link to a range of cells in another spreedsheet, no matter what values they contain.
Apple's Open Scripting Architecture (OSA) is essentially a standard set of events that components should respond to. Thus any scripting language which generates OSA events can control OpenDoc applications. OpenDoc provides a class which encapsulates a batch of OSA events; you can think of it as "OSA bytecode". Components can store and execute this bytecode, e.g. as the binding of an event handler.
Scripting isn't the only way to make application-dependent requests. OpenDoc and OLE both allow additional application-dependent interfaces to be attached to components. These interfaces will presumably be standardized for popular domains.
For more information on OpenDoc and ActiveX, chase the links on the main page.