Server Design Issues

The Instancing setting of a class module has a profound effect on what is published in your server's type library. It determines what coclasses and interfaces are seen by the outside world. The following are the available settings:

  • Private: The class can be used only in the local project. It's not exposed through the type library to the outside world.

  • PublicNotCreatable: The class module generates a noncreatable coclass that can only be instantiated from inside the server. A default dual-style interface is built from the public members.

  • MultiUse: The class module generates a creatable coclass that allows multiple instances in any process. A default dual-style interface is built from the public members.

  • SingleUse: (For out-of-process servers only.) The class module generates a creatable coclass that guarantees that each server process contains only one instance. A default dual-style interface is built from the public members.

  • GlobalSingleUse: Like SingleUse, but allow the client access to the object's methods as if the methods were global functions.

  • GlobalMultiUse: Like MultiUse, but allow the client acces to the object's methods as if the methods were global functions.

When you want a creatable class, it's most common to select MultiUse. SingleUse, however, has some interesting uses. If you create two instances from a coclass that has this setting, each instance is created in a separate server process. If you're running two applications on a user's desktop and they activate the same type of object, you can use a SingleUse class to give your objects an extra level of fault protection. Each client will activate its object in a different process. SingleUse classes also provide a simple way to achieve multithreading because each process owns its own thread. However, you will learn more efficient techniques for creating multithreaded servers later in this book.

MultiUse and SingleUse both allow you to make a coclass "global." This simply makes the class easier for the client to use. If you have a standard MultiUse class that calculates a tax rate, for example, you access the object like this:

 Dim Obj As CTaxCalculator, Tax As Currency Set Obj = New CTaxCalculator Tax = Obj.CalculateTax(28600) 

When you set the instancing property of the class to GlobalMultiUse, the client can access the method as if it were a global function, as shown here:

 Dim Tax As Currency Tax = CalculateTax(28600) 

Global classes simply save the client the trouble of instantiating an object before calling a method. They do this by marking the coclass with the AppObject attribute in the type library. On the client side, Visual Basic creates an invisible object behind the scenes. Any global call is interpreted as a call to this invisible object. As of this writing, Visual Basic is the only known developer tool that provides the convenience of transparently mapping AppObject attributes on the client side. A programmer creating a client application with C++ or Java can't tell the difference between a class marked GlobalMultiUse and a class marked MultiUse. In this case, global classes just provide a syntactic sugar for other Visual Basic programmers.

Using Enumerations

As a COM developer, you should be aggressive with the use of enumerations. Enumerations let you declare logically related sets of constants in your type library. COM and Visual Basic have borrowed the syntax for enumerations from C. Here's what it looks like:

 ' Dog Server Error Codes Enum ErrorCodesEnum     dsDogUnavailable     dsDogUnagreeable     dsDogNotFound End Enum 

You must declare enumerations in a class module in order to expose them to COM clients. If you don't do this, they will not be published in a type library. Enumerations declared in .bas modules are private to the project.

What's not very intuitive is that the enumerations you declare in a class module are scoped at the type library level, not the class level. Therefore, every enumeration value that you declare in a project must have a unique name. The class instancing property has no effect on this. If you want to create a separate class module just to hold your enumerations, you should mark it as PublicNotCreatable. Here's what an enumeration looks like in Interface Definition Language (IDL):

 typedef[uuid(FFB2C0DE-CD72-11D1-920D-E46FA4000000), version(1.0)] enum {     dsDogUnavailable = 0,     dsDogUnagreeable = 1,     dsDogNotFound = 2 } ErrorCodesEnum; 

Here's another thing to think about. If a client application uses several type libraries, each of which defines its own set of enumerations, all of the combined enumerations from every server are visible to the client application in a single projectwide scope. The enumerations from two servers will conflict if they have the same name. You can sometimes prevent this conflict by using a server-specific prefix. The enumerations in the example above have been defined with the prefix ds to comply with this convention. However, there's still a potential conflict, which can always be resolved in the client application by preceding the name of the enumeration with the project name, like this:

 DogServer.dsDogNotAvailable 

Modifying Procedure Attributes

You can influence how Visual Basic sets attributes for the methods and properties of your classes and interfaces by choosing the Procedure Attributes command from the Tools menu while the class module you want to modify is the active window. Figure 5-5 shows the dialog box that appears.

Figure 5-5. In the Procedure Attributes dialog box, you can modify the definition of the methods and properties in a public class module. All of the settings that you specify in this dialog box are written into the interface definition in the server's type library.

You use the Description setting to document the semantics of the method or property. Other Visual Basic programmers will see your descriptions when they examine your server's type library with the Object Browser. This is pretty easy to do, and it makes your server seem more polished.

You can also set the Procedure ID to a different value. For instance, if you set the Procedure ID for a property to Default (the value 0), the property will be recognized as the default property of the object. Here's what the resulting IDL looks like:

 [id(00000000),     propput,     helpstring("Name as it appears on birth certificate") ] HRESULT Name([in] BSTR Name); 

Now a client can access this property both explicitly and implicitly, like this:

 Dim Dog1 As IDog, Dog2 As IDog Set Dog1 = New CBeagle Set Dog2 = New CBeagle ' Name property is accessible explicitly. Dog1.Name = "Milli" ' Name property is also accessible implicitly. Dog2 = "Vanilli" 

As you can see, you can set many options in the Procedure Attributes dialog box. If you have a help file associated with your server, you can add context sensitivity to your methods so that programmers can jump to a certain part of the help file. You can also hide methods from other programmers. In short, you can make your server far more polished. Note that many of the settings are relevant only to programmers who are building ActiveX controls. Many of the options, such as Don't Show In Property Browser and User Interface Default, aren't useful to programmers who are creating nonvisual servers for the middle tier.

Friend Methods

Marking a method as a friend in a Visual Basic class creates an interesting effect. A friend method is accessible to any code in the server project, but it isn't exposed to the outside world. You could say that it's public on the inside and private on the outside. Or you could say that in a public class, private members provide modulewide access, friend members provide projectwide access, and public members are available to any client inside or outside the server. When you mark a method or a property as a friend, it isn't published in a type library. It has nothing to do with COM.

Use friend members with caution in Visual Basic. C++ has a similar feature, which is often used to remedy problems in the initial class design. Many programmers use this friend syntax without realizing that they are breaking encapsulation. Friend methods can be useful, but you should be sure that you're not unnecessarily exposing implementation details of a class. The encapsulation police might arrive at your door and start asking a lot of questions.



Programming Distributed Applications With Com & Microsoft Visual Basic 6.0
Programming Distributed Applications with Com and Microsoft Visual Basic 6.0 (Programming/Visual Basic)
ISBN: 1572319615
EAN: 2147483647
Year: 1998
Pages: 72
Authors: Ted Pattison

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net