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