Académique Documents
Professionnel Documents
Culture Documents
This chapter provides an overview of current software development and describes why some of these techniques may be useful, but fall short of providing the necessary component communication, version maintenance, and location transparency. The Component Object Model (COM) addresses some of these constraints. At the end of this chapter, you will better understand how to use COM to develop component software. Although this material is presented from a C++ and Microsoft Windows perspective, the basic principles are true for the design of large, distributed, object-oriented systems.
Objectives
After completing this chapter, you will be able to: List and explain the problems that confront component software developers today. List and explain attempted solutions to traditional component software development. Explain the drawbacks of various solutions to component software development. List the solutions that COM provides for component software development problems.
An example of a standardized API is the Microsoft Open Database Connectivity (ODBC) API. Many software vendors have implemented the ODBC API in their database drivers. Even with fairly widespread adoption of the ODBC API, interoperability is still challenging because implementation differences can occur from one vendor to another.
Notes
Versioning
Advertising and maintaining different versions of the API can also be problematic. As an API creator, how can you force a developer to check for the correct version?
Component Communication
Enabling components to communicate with each other is challenging, especially if different developers have created the components.
Implementation Language
The programming language you use for creating components greatly impacts how the components will communicate through an API. For example, if you create components in C++ and export classes from a library, it can be challenging to use C or Visual Basic to create the client of the component.
Notes
Object-Oriented Techniques
One of the first attempts of developing components was to apply object-oriented techniques. Object-oriented analysis and design enables application designers to approach software development from a higher level of abstraction. Viewing an application as a collection of objects (which have attributes and behaviors) that interact with each other enables a software developer to more effectively model the problem and create a correct solution. An object design is also more comprehensible than a series of algorithms. Object-oriented design, on its own, is not sufficient to handle the complexity of modern software development.
Notes
Notes
This version of the class is much better; however, it still gives clients an object with a specific size. With this version, you are close to providing a string class with only functions. In a final attempt at improving the string class, you make all functions pure virtual. You are simply publishing an interface for a string class that looks like this: class String { public: virtual String Translate(short localeID) = 0; virtual short getLength() = 0; } ; All of the virtual functions from our string class example are pure, making the class abstract. Currently, clients are not dependent on the size of an object or layout. A client will have only an interface pointer; the data representation is completely hidden. The creation of objects in this manner is a major concept of COM.
Component Implementation
To create an instance of an abstract class, you define a private implementation hierarchy whose classes are derived from the published abstract classes.
Notes
A client obtains a pointer to a String object by calling the CreateString function, as shown in the following example code: void ClientFunction() { String * pString; pString = CreateString(); short length = pString->getLength(); ... } The client never sees the StringImp class, nor does the client call the new operator. The client is aware only of the VTBL of the String interface.
Interface Evolution
This model for deriving from abstract classes can be used for multiple levels of derivation to change an interface without changing the base class. To add new functionality to an interface, you derive new classes from the abstract hierarchy. You can then use dynamic_cast to allow for safe casting up and down the derivation tree. The following example code shows how the String2 class can change an interface: class String2 : public String { public: virtual String Translate(short localeID) = 0; virtual short getLength() = 0; virtual void ConvertToUpperCase() = 0; }; class StringImp : public String2 { public: virtual String Translate(short localeID) {} virtual short getLength() {} virtual void ConvertToUpperCase() {} };
Notes
An existing client can continue to use this new object because the client only knows about the methods of the String class, which are still supported. Using the dynamic_cast operator, a new client can determine if a method is supported, as shown in the following example code: void NewClientFunction() { String * pString; pString = CreateString(); short length = pString->getLength(); // Everything is the same as older client up to this point // Verify new server capabilities String2 *pString2; pString2 = dynamic_cast<String2 *> pString; if (NULL != pString2) pString2->ConvertToUpperCase(); ... } The new client also works with an older server. The new client determines whether the server supports the added interface before calling a method of that new interface. Ultimately, what you are doing is exporting tables of pointers to functions, or VTBLs.
COM Defined
COM is a standard (or model) for the interaction of binary objects. An important feature of COM is that objects are precompiled, which means that the implementation language is irrelevant. If you include tokenized code (for example, the P-Code in Microsoft Visual Basic or the bytecode in Java), objects will not necessarily be tied to a specific hardware platform or operating system. COM is also an integration technology. Components can be developed independently, and COM provides the standard model for integrating these components. One can think of COM as an enabling technology, rather than a solution in itself.
Notes
Language Independence
When developing components, you should not need to choose a specific language. In COM, any language can be used if it allows for calling functions through function pointers. Even interpreted languages are not excluded if the interpretive environment can provide these services on behalf of the application. You can therefore develop COM component software by using languages such as C++, Java, Visual Basic, and Visual Basic Scripting Edition (VBScript).
Location Transparency
In addition, you should not have to know in which module and location the file system provides a service. This becomes increasingly important when specific services cannot be provided locally, if services are late-bound, or if the process that provides these services changes location. Just as hard-coded paths are problematic in applications, hard-coded dependence on the location of services can also cause errors. COM separates clients from servers, which allows servers to be moved without impacting clients.
Vendor Independence
Consider an example of what happens frequently in the current model for software development. A new vendor provides an ODBC driver for your database that is better than the driver provided by your current vendor. It would be a lot of effort to port all existing code to use the new driver. The effort involved might tempt you to keep the existing, less effective driver. Because COM objects export only interfaces, any new object that exposes the same interfaces as an existing object can transparently replace the existing object. Vendor independence extends not just to external vendors, but also internally to objects that can be easily upgraded without recompiling.
Notes
10
OLE 2.0 was the first technology from Microsoft to be based on COM, as shown in the following illustration:
Since OLE was introduced, Microsoft has released a number of additional technologies based on COM. These technologies include OLE Automation and OLE Controls, as shown in this illustration:
However, the use of the term OLE in the names OLE Automation and OLE Controls was not quite accurate because these technologies had nothing to do with linking and embedding. In an attempt to resolve this confusion, Microsoft replaced the term OLE with the new term ActiveX. The only technologies that kept the name OLE were those that actually related to linking and embedding.
Notes
11
The following illustration shows the difference between ActiveX and OLE, each of which is built on COM:
Notes
12
Self-Check Questions
1. Which one of the following is a goal of COM? A. B. C. D. Enforcing development consistency by requiring all components to be developed in the same language. Enabling clients to be uncoupled from servers by not requiring components to know the physical location of other components. Tracking the version of each component so that only the correct and most recent version is used. Enabling component developers to choose either C++ or Visual Basic as their development language.
2. One of the problems with the traditional API-based approach to developing component software is the continuing evolution of the API. Which one of the following best describes this problem? A. B. C. D. The API cannot be extended to provide additional functionality. As the API evolves, the implementation language must not change. Any changes made in the API by its creator can potentially break existing applications that use the API. There are no problems with the traditional API-based approach to component software development.
Notes