Link to home
Start Free TrialLog in
Avatar of aeklund
aeklund

asked on

ActiveX DLL - Best Practices

I have an activex dll that performs internet functions and use it in many projects (internet.dll)

I create many custom activex dlls for different projects and include a reference to this (internet.dll) within that dll.

Whenever I need to make a change to (internet.dll), my references inside my other activex dlls that reference it get "screwed" up.  I have to edit each one, and recompile.  This is a headache!!!

1) Is it because the functions change and that breaks the binary or project compatablity, thus giving the dll a new guid?

2) Is it not good practice to have one activex dll reference another activex dll?

3) What is the best way to accompish this so that I don't lose compatiblity and have to recompile all these activex dlls all the time?

I will award the points to the person who can answer each question in detail and what might be the best practice and standard.
Avatar of PaulHews
PaulHews
Flag of Canada image

To avoid references being mismanaged, you have to use binary compatibility on your compiled DLL.  This will ensure that all client applications and DLLs will use the same reference even if you add a method or property.

Here's the idea.  You get the general interface of your Active X object hammered out.  You write code that declares all public method and props.  Now you will open the project properties dialog from the project menu.  Go to the component tab.  At this stage, you set Project Compatibility, because you are still developing your interface.  This will prevent test clients having references being broken as you change and develop the interface.  You will develop a test client that uses a reference to your new project.  When you are ready for a first release, compile your DLL.  Browse to your newly compiled component in the dialog and change compatibility to Binary Compatibility.  From now on, you can add methods and properties without breaking compatibility with existing clients, but you cannot change or delete existing public properties and methods.
Avatar of cpcode
cpcode

My company has been developing ActiveX controls and DLLs for a while now, and we have run into these issues often.
Based on that painful experience, here are my answers:

1) From the way you pose your question, it seems you are already using binary or project compatibility. This is good.
Binary compatibility is broken whenever you change the interface of your object. This includes adding, removing, and changing the parameters of any public method, as well as changing any public variables or events.

If you are only changing the contents of functions, you should NOT be braking compatibility. If you do, let me know and we can go through your files/settings.

In select cases (if you only add new methods) you can preserve compatibility, which means that the new DLL will have the same GUID as the old, even though the interface is different. I have done this in the past, but it is not a good practice, and I don't recommend it (sorry PaulHews, I have had bad luck with it...).

If you were wondering why the GUIDs have to change: an interface for a DLL contains the memory addresses of all its methods. Using a wrong interface can lead to memory leaks. because the system tries to access a memory address that is not the start of a method.

2) It is definitely good practice to reference dlls as you are doing - it is one of the pillars of ActiveX. You just have to be careful about your processes, and keep in mind the drawbacks of the approach.
FYI, you can eliminate references altogether by late-binding to your internet.dll: instead of having a reference to it in your project and writing

   Dim myObj as new InternetDLL.SomeObj

you write:

   Dim myObj as Object
   Set myObj = CreateObject("InternetDLL.SomeObj")

Once again, I do not recommend this - I consider it a last-resort solution, or sometimes a poor solution to a design problem. Fortunately, you don't seem to need this.

3) Best practices depend on where you are in the lifetime of your project, and the product scope/intent. Here's my general approach:

If Internet.dll is still in early stages of development, then I agree with PaulHews - you can use project compatibility, or just make a project group and open everyone together.

However, I gather from your post that your Internet.dll is actually pretty mature - you have used it for a while for various projects, - and changes to it are due to new needs or discovered bugs. If this is so:

If your Internet DLL changes due to a bug fix, and the change is only in the internals (no interface changes), you have no problem - you can maintain compatibility. Once again, if you can't now it's probably a bad setting.

If the change is a bug fix that requires an interface change (e.g. change the type of a method parameter), or the change is due to a new feature (e.g. add a method, or event), then you have a choice:
- You can bite the bullet and break compatibility, as you are doing now. I suggest that you do this once in a while, just to get every control up to date with everyone else.

- You can implement interfaces. This is a more sophisticated solution, and requires a bit more work, but it is by far the most elegant and robust. In essence, you treat Internet.dll as your product, and the other DLLs as clients: if one client (e.g. your last custom activeX) requires more functionality, your goal is to make it so that the new client gets it, and your other clients don't even notice.
In essence, this last custom ActiveX would use InternetDLL.someObj version 1.1, while everyone else is using InternetDLL.someObj version 1.0. The two share the DLL and most of the code, they just have different entry points.

You can see how powerful this approach can be as your Internet DLL develops over many custom controls, many new features, etc.

There are 2 ways (at least) to implement interfaces: you can use the Implements keyword for true interfaces (the MSDN documentation is good), or you can do it manually, by separating the interface from the content in your object.
I would recommend using Implements (if you want to go down this road), it is the VB answer to polymorphism.

Microsoft uses polymorphism extensively, they really love the concept - as do many computer science professors teaching Object Oriented programming in college.

If you are interested in this approach and want to know more, let me know. I am not writing how to implement this in this post because your problem may turn out to be a bad setting...

A note:
- If your Internet DLL public interface has to change often, you may consider the 'generic method' approach: for example, if you keep adding new properties to your object for new functionality, such as
   public property let Foo(strFoo as string)

you can add a method called
   public sub setProperty(strName as string, strValue as string)

Then, the calling method would read
   myObj.setProperty("Foo","some value")
instead of
   myObj.Foo = "some value"

If you then have to add a property 'FooBar', you don't have to change your interface. Microsoft uses this trick a lot too.

Good luck.

Avatar of aeklund

ASKER

Thank you both Paul and cpcode for your posts...

cpcode-
Your explaination is very well and in depth, exactly what I was looking for.  I am interested in more details about polymorphism and about creating interfaces in VB.  Any information you can provide would be helpfull.

In the meantime I will search MSDN and leave the question open for a few more days.
ASKER CERTIFIED SOLUTION
Avatar of cpcode
cpcode

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of aeklund

ASKER

cpcode-
Thanks for the information... I still need to do some more homework on polymorphism to fully understand it, or perhaps I can't think of any example of where I would use it besides as an "add-in" type.

In the meantime, I'm going to give you the points and close the question.  Thanks!