"Why do they call it a Ferris wheel?"
This question was put to me by my twelve-year-old as we swayed high above the cotton candy stands at a recent summer carnival. I gave it two seconds' thought. "It was invented by a guy named Ferris."
"Amazing, Dad. What was his first name? Did he work in a carnival? When did he—"
"Eat your cotton candy," I advised. "When we get home you can look it up."
"You always say that," he grumbled. I had been pitching him this Stengelism lately—Casey [Stengel] was fond of capping his baseball stories with the tag line "You could look it up"—and he had begun to resent it. What he didn't know was that, in this particular case, I had no choice. For all I knew, Ferris was an acronym or somebody's pet piranha.
—Tad Tuleja, Marvelous Monikers1
Not long ago I was listening to a radio interview with a scientist who was asked about the most important elements in human evolution. One of the elements the scientist listed was symbolic thinking—the ability to create symbols that represent things much more complex. Symbols allow us to encapsulate a tremendous amount of meaning and intelligence in a single entity. A person raised around county fairs, for example, understands a Ferris wheel not only as a specific object but also as a term that represents a host of feelings and images associated with amusement parks, childhood, cotton candy, farm animals, and the dime toss. Symbols sometimes also become rallying points for political action, even though very few of the people involved really understand the meaning of the symbol. Witness the Information Superhighway or, for that matter, OLE. (This book is supposed to clear up misconceptions about the latter.)
Symbols are thus very powerful abstractions that encapsulate potentially very large amounts of meaning. Because languages are built with tens of thousands of symbols, they form the basis for our ability to communicate (and miscommunicate) as richly as we do. Without symbols, you could not be reading this book, right? If you think about it, a symbol in a human language is a great example of an object in terms of object-oriented programming. It encapsulates both information (meaning) and functionality (intelligence or knowledge of a process). Words are obviously reusable, and they are polymorphic: grammatically similar symbols can be interchanged with one another to radically alter the meaning of a phrase or sentence without changing the grammatical structure at all.
An object that can act like a symbol is a powerful abstraction to introduce into a computing environment—so powerful, in fact, that fully exploring the philosophical nature of such symbols is beyond the scope of this book. What we can explore, however, is the nature and utility of a naming architecture built on such interchangeable and polymorphic symbols, an architecture in which we can assign some rich symbolic unit to name an object, a set of objects, or a process involving objects.
These symbolic names for things are of practical use only when you can resolve the name into the actual thing it names. The process of resolution—which is the same as the process implied in the name itself—is called binding. If the name refers to an object, binding results in an interface pointer to that object. If the name refers to a process, binding carries out that process, and the result is also some interface pointer to some object. In this latter case, however, the object isn't as important as the process used to create or access it.
So the ability to create and manage names for things and the ability to resolve those names into interface pointers on the objects they refer to is what OLE's naming and binding architecture is all about. This is sometimes referred to as linking, as it is in OLE Documents. A linked compound document object is really a type of proxy that manages the name of some real object. It is important to understand the term link in a generic capacity: any client that holds any sort of symbolic reference to or name of something else is said to have a link to that something else. A link is just another synonym for a name.
In the same way that Local/Remote Transparency has a number of distinct architectural objects, OLE's naming and binding architecture also has a number of such objects. From the perspective of a client that uses a name to access an object, only the name itself is important. The name, which is an object, encapsulates all the necessary binding knowledge behind an interface and has to be able to store arbitrary information (perhaps persistently) and run arbitrary code when asked to bind to its named object. When such a name is finished binding, it falls out of the picture entirely, just as such portions of COM as the Service Control Manager fall out of the picture after locating a new object created in response to a client's request.
OLE calls such a name a moniker,2 which is any OLE or COM object that implements at least the interface IMoniker. Because IMoniker itself is derived from IPersistStream, a moniker also knows how to read and write its persistent state to a stream object. This persistent state is the information that the moniker needs in order to intelligently bind to the object or process that it names—monikers are also called persistent, intelligent names for this reason. In addition, monikers can provide a display name that is suitable to show in a user interface, such as in a list of links shown in a list box. Monikers also support parsing a display name into internal moniker state data, enabling an application to create a moniker from some text a user types into a dialog box.
Although the exact state data and binding process differ between different types of monikers, the way a client tells a moniker to bind is always the same: it uses IMoniker::BindToObject, a function that does whatever is necessary to access the object named by the moniker and return some interface pointer to the client. This member function, along with the closely related IMoniker::BindToStorage (which accesses the object's storage), represents the core of OLE's naming and binding architecture. All the other members of IMoniker, as well as the other architectural objects and their interfaces, are really the details of making the entire binding process work.
In examining naming and binding architecture in this chapter, we'll see the various objects and interfaces involved, such as the bind context object and its IBindCtx interface, the running object table (IRunningObjectTable), and composite monikers. In addition, we'll look at four specific types of monikers that OLE provides as well as how to create your own custom moniker when the need arises. In all of this, we'll see how monikers are just about as powerful as cultural symbols themselves. And just as symbols play an important role in human evolution, you can expect that in time monikers will be important in the evolution of computing.
The Ferris wheel, by the way, was created by a civil engineer named George Washington Gale Ferris for the 1893 World's Colombian Exposition in Chicago. It was created as a show of American ingenuity to rival the Eiffel Tower, which was built for the same exposition in Paris four years earlier by another engineer, Alexandre Gustave Eiffel. The original $385,000 wheel was several hundred feet in diameter and carried over 2000 passengers at a time in 36 cars. After the craze settled down, it was sold in 1898 as scrap iron for a mere $2,000.
1 Harmony Books 1990. |
2 Something of a symbol itself which people in the United Kingdom understand but most Americans do not. Moniker generally means nickname. |