Multimedia Group System and API Design GuidelinesLast reviewed: November 2, 1995Article ID: Q67692 |
The information in this article applies to:
SUMMARYThe Microsoft Multimedia Systems Group is doing a large amount of system design and implementation. This article comments on the areas of system design.
MORE INFORMATION
Definitions
Term Definition ---- ---------- Module A module provides a set of functions and the interface to access those functions. The interface is called the API. Client A client uses a module. A client might be an application or a dynamic-link library (DLL). Prefix The initialization portion of the module that must be called before any of the other functions can be accessed. Postfix The closing portion of the module that must be called after the client has finished using the functions of the module. Channel A channel is created by calling a module's prefix function. It is used by the rest of the functions of the module (including the postfix function). Two notes about a channel: 1. A module can allocate resources to a channel. For example, a handle to a window is a channel, which has memory, a window procedure, and many other resources associated with it. 2. The channel uniquely identifies the user of the interface to the module. This allows the module to perform functions uniquely on each open channel. For example, each file handle represents a different file that has been opened. Each file handle may have different attributes (read, write, read/write, binary, and so forth). Separate Driver Interface from Module InterfaceSeparating the application from the hardware is one of the major tasks of system software. Layers within the operating system are separated from the hardware through the use of drivers. The system interface to the application should hide the mechanisms of the drivers as much as possible. This allows changing the mechanics of a driver in a later version of the system software. This also preserves the formality of the interface; applications are prevented from directly accessing the hardware. Each application should also be separated from the drivers within the system. The driver API should not depend on where the driver is located, what it is named, or what form it takes (DLL, VxD, and so forth). A driver should shield the application writer from its internal workings to enforce the principle of information hiding. If too much information is available, the application writer may choose to directly access the hardware, which jeopardizes the separation of functionality provided by the driver mechanism and system API. Every Module Should Have an Initialization Function Requiring the application to call a prefix function before using a system module and a postfix function after using a system module provides three major benefits, as follows:
Interface NamingDuring the process of designing a new module, use the interface naming conventions from an existing module with similar functionality. For example, an interface that deals with files would have a prefix interface containing the word "open," and a postfix interface containing the word "close." Extend naming conventions to similar functional areas. A stream interface would also have an "open" and a "close" function. If the module has new functionality, then the functions can have unique names, such as the MIDI driver's midiOutStop function. If the module is similar to but not the same as another module, then use the function name to distinguish between modules. For example, the CreateWindow and CreateWindowEx functions in Windows create windows but CreateWindowEx also allows an application to specify other attributes. The goal is to provide programmers familiar with existing modules a basis by which to quickly learn the new interface. Prefix function names with the module name (abbreviated, if necessary). This allows the documentation to sort function names alphabetically, while keeping related functions together. More importantly, it allows easy identification of the module to which a function belongs.
Definition NamingPrefix the names of constants and data structures with the module name (abbreviated, if necessary). For example, STRM_SEEK is a constant in the STRM group. This allows easy identification of the module to which a definition or data structure belongs. As another example, MIDIOUTCAPS is the Device Capabilities structure for the MIDI output module. Using the naming convention developed here and symmetry (discussed in depth in the second part of this article), the MIDI Input module Device Capabilities structure should be called MIDIINCAPS. Use additional prefixes as appropriate to identify the use of the definition. For example, MOERR_NODRIVER is a definition in the MIDI Output module to describe an error, that of no driver present.
Registering Drivers with ModuleMost of the systems designed by the Multimedia group allow device drivers to be installed by the original equipment manufacturer (OEM) or even by the end user (given an appropriate setup program). There are two main ways for these drivers to communicate with the main module. The first is to place an entry in the SYSTEM.INI file. When the parent module loads, it loads the child driver and initiates communication with the child. The other method is for the child driver to call the parent to register itself as a client. This second method presumes that there is a suitable method available to load the child. Windows provides such a mechanism. Requiring a driver to register itself with the handler module provides four benefits:
Symmetry of Function Names
Symmetry in Naming Conventions
Design for Implementation in StepsMost implementations of any size must be done in incremental steps of functionality. More and more features are added to the modules until the entire design is completely implemented. For large or complex modules, this process may occur over several years. However, the original design must anticipate the complete, final functionality, not just the short-term goals. For example, even if allowing multiple users of a module will not be implemented in the first phase, this capability should be designed into the API. That way, the impact on users of the module will be minimal once implementation is complete. Avoid placing arbitrary limits on functionality due to details of the current implementation. For example, even if only one user can have a resource allocated today, this may not always be true. Specifically, the Open function should return a handle to the resource that is then passed to functions that manipulate the resource. In the future, when multiple users of the resource is implemented, it will not be necessary to change other functions or applications. In a message-based system, functions should return a "message not recognized" code for unexpected messages that is distinct from the "an error occurred" code. Then, when a future version of the driver contains extended functionality, an application can determine if the installed version of the driver supports the new features. If not, the application can take appropriate alternative action. A project designed to be built in phases has well defined progress milestones. This makes it much easier to track progress while the module is under construction. Building a module in phases also makes it easier to verify that the module is built correctly. Testing receives increments of functionality instead of the entire product toward the end of the development cycle.
Error ReportingAn function call can fail for many reasons. It is best if the call can return the specific cause of the error in addition to noting that the call failed. Functions that return a handle, structure, or other data cause particular problems because there is a limited set of values that are always invalid. Three approaches to error reporting are:
Client-Supplied BuffersIt is desirable for the client application to provide all buffers that it will access. If a system module allocates and maintains buffers, many implementation problems can arise when a buffer is made visible to the client application. Three advantages of client-supplied buffers are:
complete control over how much memory the system module uses.
|
Additional reference words: 3.00 3.10 3.50 4.00 95
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |