Visual Basic Concepts

Levels of Binary Version Compatibility

Visual Basic defines three levels of version compatibility for the interfaces you describe in your class modules.

  • Version identical means that the interfaces are all the same, so the new version of the type library is exactly the same as the old one. The code inside methods or Property procedures may have been changed or enhanced, but this is transparent to client applications.

  • Version compatible means that objects and/or methods have been added to the type library, but no changes were made to existing properties or methods. Both old and new client applications can use the component.

  • Version incompatible means that at least one property or method that existed in the old type library has been changed or removed. Existing client applications that have references to the component cannot use the new version.

Version-Identical Interfaces

Once your component has been distributed as part of an application, there are several situations that might cause you to release an update. You might want to optimize the performance of a method that had turned out to be a bottleneck for users. You might also need to change the internal implementation of an object’s method to reflect changes in the business rule on which the method was based.

You can change the code in existing Property procedures or methods, and still have a version-identical interface, as long as you do not change the names or data types of their parameters, the order of the parameters, the name of the property or method, or the data type of the return value.

When you create the executable for a version-identical upgrade, you can use the same file name for the executable. Visual Basic uses the same version number for the type library.

Important   When you release a new version of your component with a version-identical or version-compatible interface, and retain the same file name for the executable, you should always use the Make tab of the Project Properties dialog box to increment the file version number. This ensures that the setup programs for applications that use your component will replace old versions during setup.

Version-Compatible Interfaces

When you enhance your component by adding new classes, or new properties and methods to existing classes, you can continue to use the same name for your executable. As long as you make no changes to existing properties and methods, Visual Basic updates the version number of the type library but keeps it compatible with the old version number.

Client applications that are built using the new version of your component will compile with the new version number, and can make use of all the new features. They cannot be used with earlier versions of your component, however, because type library versions are only upward-compatible.

As with version-identical releases, remember to increment the file version number of the executable.

Version-Incompatible Interfaces

Sometimes design decisions made in an earlier version of a component fail to anticipate future needs. If you want the code in the component to be useful in new development projects, you have to change the interface.

For example, the CupsPerAnnum parameter of the Coffee method might be implemented as an Integer in the first version of a component. It may become apparent, after the component has been in use for some time, that some clients need to pass a larger value than can be contained in an Integer.

Changing the declaration of a method is only one of several actions that will cause Visual Basic to make the version number of the type library incompatible, rendering the new version unusable with client applications compiled with earlier versions. The following changes will cause a version incompatibility:

  • Changing the Project Name field on the General tab of the Project Properties dialog box.

  • Changing the Name property of any class module whose Public property is True (controls), or whose Instancing property is not Private (class modules).

  • Deleting a public class module, or setting its Instancing property to Private.

  • Deleting a public variable, procedure, or Property procedure from a public class module or control, or changing it to Private or Friend.

  • Changing the name or data type of a public variable, procedure, or Property procedure in a public class module or control.

  • Changing the names, data types, or order of the parameters of a public procedure or Property procedure in a public class module or control.

  • Changing the Procedure ID (DispID) or other parameters in the Procedure Attributes dialog box.

Time to Take Stock

When you’ve identified a necessary change that will cause your component to be incompatible with earlier versions, it’s a good idea to take the time to evaluate the entire set of interfaces, before plunging ahead and creating an incompatible version of your component.

Consider Multiple Interfaces

Remember that there are alternatives to using Version Compatibility. Consider enhancing your component by adding new interfaces with the Implements statement, as described in "Providing Polymorphism by Implementing Interfaces" in "General Principles of Component Design."

Multiple interfaces, a key feature of the Component Object Model (COM) — on which the ActiveX specification is based — provide a more flexible way to enhance software components. They allow you to evolve your systems over time, without breaking existing components.

You don’t have to tackle the daunting task factoring your existing class module interfaces into small interfaces more suitable for use with Implements — one of the benefits of using multiple interfaces is that you can start small, adding new interfaces to the system only where new functionality is required.

Going Ahead with Incompatibility

If you decide to go ahead with an incompatible version, you can minimize future problems for the users of your component by concentrating in one release all the changes you can anticipate that might break compatibility again if they have to be made in later releases.

In planning for an incompatible change, treat the project as a fresh start. Devote as much care to planning as you would if you were creating a brand new component.

Creating an incompatible version requires three steps: changing the project name, changing the file name, and compiling with No Compatibility selected.

Changing the Project Name

The key change you must make, when you need to distribute an incompatible version of your component, is the project name. The project name, which is set on the General tab of the Project Properties dialog box, is the first part of the programmatic ID of each class your component provides.

For example, the SmallMechanicals component might provide a Widgets class. A client application would create a variable to contain a reference to a Widget object as follows:

Private wdgDriver As SmallMechanicals.Widget

The programmatic ID is the combination of project name and class name, and it must be unique. If you create a new version of this component, you might give it the project name SmallMechanicals200. Both versions of the Widget object could then be registered in the same Windows Registry without confusion.

Changing the File Name

You must change the file name of an incompatible component. If you use the old file name without incrementing the file version number, the incompatible component may not install on computers where the old file exists. If you increment the file version, the new file will over-write the old, and applications that used the old version will fail.

Compiling with No Compatibility

Before you compile the incompatible component for the first time, open the Project Properties dialog box (accessible from the Project menu), select the Component tab, then select No Compatibility in the Version Compatibility box.

Do not omit this step. Compiling with No Compatibility ensures that the new executable will not contain any GUIDs (for example, class IDs or interface IDs) that belong to the previous version. This is necessary for applications that use the original version to continue working correctly.

Tip   After compiling once with No Compatibility, switch to Project Compatibility to simplify your development tasks.

Alternatives to Version-Incompatible Changes

If you prefer not to make the change to multiple interfaces, as described above, you can take a similar approach with classes.

That is, you can avoid changes that cause version incompatibility by adding new objects, properties, and methods, instead of changing existing ones. Existing applications continue using the old methods and objects, while developers of new applications can use the new objects.

For example, you might discover that to take advantage of enhancements to your General Ledger system, you need to add a SubAccount parameter to several business rules in your FinanceRules component.

If each rule is implemented as a method of the GL object, you could avoid creating an incompatible version of the component by adding a new object named GL97. This object would have the same methods as the GL object, but with a SubAccount parameter where appropriate.

If you need to add new versions of existing methods to an object, you can give the new methods the same name with a version or sequence number added — for example, ‘Execute2.’

This approach is not as flexible or efficient as implementing multiple interfaces. You may end up replicating entire classes, and class interfaces may become large and unwieldy — for example, you might find yourself using a Query class with an Execute method, an Execute2 method, an Execute3 method, and so on. However, it’s a step in the right direction.

For More Information   "Providing a Reference Point for Binary Version Compatibility" describes when and how to specify a version of your component as a reference point for version compatibility. See "Version Compatibility" for a list of topics related to this feature. Software evolution using multiple interfaces is discussed in "Providing Polymorphism by Implementing Interfaces," in "General Principles of Component Design."