INF: Multimedia Group System and API Design Guidelines #1

ID Number: Q67692

1.00

WINDOWS

Summary:

The Microsoft Multimedia Systems Group is doing a large amount of

system design and implementation. This is the first of two articles to

comment on the areas of system design and to share the knowledge of

our past experience.

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 Interface

-----------------------------------------------

Separating 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:

1. Later versions of the driver can easily virtualize resources

because the driver defies a channel for all communication. The

driver can maintain separate resources for each communication

channel, which is required for virtualization.

Note that the complete virtualization does not need to be done in

the first implementation of the module. As long as the interface

requires the prefix and postfix calls, subsequent prefix calls can

fail with an appropriate error message. Future versions of the

system can properly handle multiple requests for the system

resource.

2. The system module can allocate resources when the channel is

allocated (when the prefix function is called), rather than when

the system is initialized. Modules that are not called consume no

resources. Resource allocation for all modules is postponed as long

as possible.

3. The system can resolve conflicts between clients through the

identification provided by the channels.

Interface Naming

----------------

During 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 instance, 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 Naming

-----------------

Prefix 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.

Additional reference words: 1.00