[Previous] [Contents] [Next]
Interface Design Recommendations
To help you define custom interfaces, this section provides several
guidelines for improved designs. Although no design guidelines can be
considered recipes for creating a useful interface specification, we
hope that these suggestions will provide you with ideas. If you have
found techniques of your own that have proved successful, let us know;
perhaps we will be able to include them in a future edition of this
book.
First, you should study the standard interfaces that are defined by
Microsoft as part of COM+ and its fundamental services, such as
structured storage, monikers, connection points, type libraries,
automation, and apartments. While not always perfect, Microsoft's
designs reflect the goals and objectives of COM+ itself. This knowledge
will be invaluable when you define a set of custom interfaces. In
addition to this general recommendation, we offer the following more
specific guidelines:
- Make interfaces as simple as possible, but no simpler A
successful interface can be grasped as a whole entity in a single
sitting. As a general rule, most interfaces have between five and seven
methods. Again, this is only a general rule—and very good reasons
exist to break it. For example, the IClassActivator interface
has only 1 method, but the IMoniker interface has 15. An
interface with too many methods is probably trying to cover too much
ground and will result in implementations of the interface that return
E_NOTIMPL for many methods.
- Be exact when you specify semantics Although an interface
is a contract, we all know that some contracts are more restrictive
than others. When you define a custom interface, you must specify the
exact semantics of the interface. If you explicitly permit some methods
to return E_NOTIMPL, the resulting interface definition is
relatively fluid. We've learned from experience that strict
interface definitions that do not permit methods to return
E_NOTIMPL tend to work better in the long run. This fact raises the
issue of interface factoring. It is probably better to factor an
interface into two or more interfaces instead of designing one
interface that permits certain methods to go unimplemented. Factoring
allows a more rigid interface definition but doesn't require you to
implement undesired functionality.
- Avoid the one-interface-per-object design Sometimes you
might design an object for use in a single project. "Since I will
be the only one to use this object," you might reason,
"it's OK if I design it so that the object has only one
interface with 100 methods." (Developers who work for large
corporations whose main business is not software development are often
guilty of this shortsightedness.) This type of one-interface-per-object
design is particularly poor because it overlooks a major design goal of
COM+: the ability of an object to implement multiple interfaces and for
the client to use the QueryInterface method to navigate among
them. Your reasoning might be correct now, but you never know when
someone else might want to implement your interface in a different
project. Of course, the one-interface-per-object design is a
self-fulfilling prophecy; no one in his or her right mind would ever
voluntarily implement an interface with 100 methods.
- Evaluate different methods of passing information The
number of parameters passed with each method of a given interface is
another design concern. In most cases, it is obvious what information
the method requires to do its job, but there are different ways to
provide this information. For example, if a method might be called
repeatedly, it makes sense for that method to pass the minimum amount
of data possible, thus reducing the network bandwidth used when making
remote calls. In such cases, it might make sense to define an
"initialization" method that is called once with the required
information, in advance of the worker method calls. Also, because all
the standard interfaces that deal with strings use Unicode characters,
we strongly recommend that you do likewise when you design your own
interfaces.
- Obey the versioning rules When new versions of COM+
interfaces are created, it is customary to place a revision number at
the end of the interface name. For example, the IHello interface
becomes IHello2. This numbering technique has made COM+ the
subject of some derision, especially since COM+ is supposed to resolve
many of the versioning issues facing applications. The truth is that
COM+ does help solve these versioning problems by introducing the
notion of a binary contract (otherwise known as an interface) to
which both clients and implementers must adhere. Once it is published,
an interface can never be changed because doing so would break the
binary compatibility promised by COM+.