Implements vs Binary Compatibility - vba

I have one VB6 ActiveX DLL that exposes a class INewReport. I added some new methods to this class and I was able to rebuild it and keep binary compatibility.
I have a second DLL that exposes a class clsNewReport, which implements the first class using:
Implements RSInterfaces.INewReport
Since I added new methods to INewReport, I had to also add those new methods to clsNewReport.
However, when I try to compile the second DLL, I get the binary-compatibility error "...class implemented an interface in the version-compatible component, but not in the current project".
I'm not sure what is happening here. Since I'm only adding to the class, why can't I maintain binary compatibility with the second DLL? Is there any way around this?

I think this is a correct explanation of what is happening, and some potential workarounds.
I made up a test case which reproduced the problem in the description and then dumped the IDL using OLEView from the old & new DLL which contained the interface.
Here is a diff of the old (left) and new IDL from INewReport:
Important differences:
The UUID of interface _INewReport has changed
A typedef called INewReport___v0 has been added which refers to the original UUID of the interface
(I assume that this is also what is happening to the code referred to in the question.)
So now in the client project the bincomp DLL refers to the original interface UUID; but that UUID only matches against a different name (INewReport___v0 instead of INewReport) than it did originally. I think this is the reason VB6 thinks there is a bincomp mismatch.
How to fix this problem? I've not been able to do anything in VB6 that would allow you to use the updated interface DLL with the client code without having to break bincomp of the client code.
A (bad) option could be to just change the client DLL to use project compatibility... but that may or may not be acceptable in your circumstances. It could cause whatever uses the client DLL to break unless all the consumers were also recompiled. (And this could potentially cause a cascade of broken bincomp).
A better but more complex option would be to define the interface in IDL itself, use the MIDL compiler to generate a typelib (TLB file), and reference that directly. Then you would have full control over the interface naming, etc. You could use the IDL generated from OLEView as a starting point for doing this.
This second option assumes that the interface class is really truly an interface only and has no functional code in it.
Here's how I setup a case to reproduce this:
Step 1. Original interface definition - class called INewReport set to binary compatible:
Sub ProcA()
End Sub
Sub ProcB()
End Sub
Step 2. Create a test client DLL which implements INewReport, also set to binary compatible:
Implements INewReport
Sub INewReport_ProcA()
End Sub
Sub INewReport_ProcB()
End Sub
Step 3: Add ProcC to INewReport and recompile (which also registers the newly built DLL):
(above code, plus:)
Sub ProcC()
End Sub
Step 4: Try to run or compile the test client DLL - instantly get the OP's error. No need to change any references or anything at all.

I was able to recreate your problem, using something similar to DaveInCaz's code. I tried a number of things to fix it, probably repeating things you've already tried. I came up with a possible hypothesis as to why this is happening. It doesn't fix the problem, but it may throw some additional light on it.
Quoting from This doc page:
To ensure compatibility, Visual Basic places certain restrictions on changes you make to default interfaces. Visual Basic allows you to add new classes, and to enhance the default interface of any existing class by adding properties and methods. Removing classes, properties, or methods, or changing the arguments of existing properties or methods, will cause Visual Basic to issue incompatibility warnings.
Another quote:
The ActiveX rule you must follow to ensure compatibility with multiple interfaces is simple: once an interface is in use, it can never be changed. The interface ID of a standard interface is fixed by the type library that defines the interface.
So, here's a hypothesis. The first quote mentions the default interface, which suggests that it may not be possible to alter custom interfaces in any way. That's suggested by the second quote as well. You're able to alter the interface class, because you are essentially altering its default interface. However, when you attempt to alter the implementing class in kind, to reflect the changes in your interface, your implementation reference is pointing to the older version of the interface, which no longer exists. Of course, the error message doesn't hint at this at all, because it appears to be based on the idea that you didn't attempt to implement the interface.
I haven't been able to prove this, but looking at DaveInCaz's answer, the fact that the UUID has changed seems to bear this idea out.

Related

Class versioning

I'm looking for a clean way to make incremental updates to my code library, without breaking backwards compatibility. This could mean adding new members to classes, or changing existing members to provide additional functionality. Sometimes I am required to change a member in such a way that it would break existing code (e.g. renaming a method or changing its return type), so I'd rather not touch any of my existing types once they are shipped.
The way I currently set this up is through inheritance and polymorphism by creating a new class that extends the previous "version" of that class.
The way this works is by creating the appropriate version of StatusResult (e.g. StatusResultVersion3), based on the actual value of the ProtocolVersion property, and returning it as an instance of CommandResult.
Because .NET does not seem to have a concept of class versioning, I had to come up with my own: appending the version number to the end of the class name. This will no doubt make you cringe. I could easily imagine yourself scratching your eyes out after zooming in on the diagram. But it works. I can add new members and override existing members, without introducing any code breaking changes.
Is there a better way to version my classes?
There are typically two approaches when considering existing code and assembly updates:
Regression Testing
This is a great approach for non-breaking changes, where you can simply overload functions to provide new parameters, etc. Visual Studio has some very advanced unit testing capabilities to make your regression testing relatively easy and automated.
Assembly Versions
If your changes are going to start breaking things, like rewriting the way some utility works, then it's time for a new assembly version. .NET is very good about working with assembly versions. You can deploy the versioned assemblies to different folders so that existing code can continue to reference the old version while new code can take advantage of the features in the new version.
The problem with interfaces is that once published they're largely set in stone. To quote Anders Hejlsburg:
... It's like adding a method to an interface. After you publish an interface, it is for all practical purposes immutable, because any implementation of it might have the methods that you want to add in the next version. So you've got to create a new interface instead.
So you can never just update an interface, you need to create a completely new one. Of course, you can have a single class implement both interfaces so your maintainability effort is fairly low compared with (say) polymorphic classes where your code will become spread out between multiple classes over time.
Multiple Interfaces also allows you to remove methods in a way that classes do not (Sure, you can Deprecate them but that can result in very noisy intellisense after a few iterations)
I personally lean towards having entirely stand-alone versions of the interface in each assembly version.
That is to say...
v 0.1.0.0
interface IExample
{
String DoSomething();
}
v 0.2.0.0
interface IExample
{
void DoSomethingElse();
}
How you implement them behind the scenes is up to you, but most likely it'll be the same classes with slightly different methods doing similar jobs (otherwise, why use the same interface?)
All the old code should be referencing 0.1.x.x and new code will reference 0.2.x.x. About the only issue is when you find (say) a security flaw and the fix needs to be back-ported to an earlier version. This is where a decent VCS comes in (Personal preference is TFS but SVN or anything else which supports branching/merging will do).
Merge the fixes from the 0.2 branch back into the 0.1 branch and then do a recompile to result in (say) 0.1.1.0.
As long as you stick to a process like this:
Major or Minor build will increment if there are any breaking changes (aka signatures will not change on Build/Revision increments)
Use publisher policies if the new Major/Minor version should be used by older programs (equivalent to guaranteeing nothing broke so use the new version anyway)
References in client apps should point at a Major/Minor version but not specify revision/build
This gives you:
A clean codebase without legacy clutter
Allows clients to use the latest version with no code changes if nothing has broken
Prevents clients using newer versions of an assembly which do have breaking changes until they recompile (and, one hopes, update their code as appropriate to take advantage of the new features.)
Allows you to release security patches for previous versions
The OP solved his problem as indicated by this comment:
In the end, I went with the interfaces idea because it allows me to keep multiple versions of a class member in a single class file. When I need to update the class, I'll just add the new interface, shadowing the member that has been changed, and change the return type on some of my methods. This works without breaking backwards compatibility because of polymorphism.
If this is mainly for serialization, This can be achieved in .Net using DataContractSerializers and DataAnnotations. They can deserialize different versions an object into the same object to allow for different versions of the same class to be deserialized, leaving any properties it can't map blank.

System.Data.Function is not available in this context because it is 'Friend'

I'm currently trying to create a NEWID() function in my DataContext in LINQ using the solution here, however, when adding the partial class to my DataContext.vb or a separate DataContextPartial.vb, I get the error System.Data.Function is not available in this context because it is 'Friend'.
I've come across this when accessing data types before and that was in easy fix of setting it to Public, but I'm not sure where the properties for function could be or how to change them.
The code I have is converted to VB.NET from the C# in the linked answer above:
Partial Public Class CMSModelDataContext
<[Function](Name:="NEWID", IsComposable:=True)> _
Public Function Random() As Guid
Throw New NotImplementedException()
End Function
End Class
Thanks for any help in advance.
I can't remember offhand whether VB applies the "Attribute" suffix automatically. Try this instead:
<FunctionAttribute(Name:="NEWID", IsComposable:=True)>
... and make sure you have an import for System.Data.Linq.Mapping.
EDIT: It looks like VB does apply the Attribute suffix, so I suspect you were missing an import or a reference. However, specifying FunctionAttribute explicitly will at least help you to verify this by removing the "false positive" of System.Data.Function.
I believe you should
Import System.Data.Linq.Mapping
because FunctionAttribute resides there.
You didn't import the namespace, and compiler went to look for the class in the wrong direction. Trying its best and seeing that you have imported System.Data, compiler assumed you want to use System.Data.Function which is an internal (Friend) class in System.Data.dll assembly, hence the error.
One can wonder what exactly is the purpose of this error message. If the class isn't accessible anyway, why even bothering to tell about it? I think the reason is you could've referenced your own assembly forgetting to make some of types Public. It makes sense that compiler warns you that it sees the class but you just can't use it. It also makes sense applying same rules to all references, including framework libraries, although obviously you can't modify anything in there.
I would argue that FunctionAttribute is not a particularly good choice of name because it's begging for wrong namespace imports and related confusion.

How to find and remove unused class files from a project

My XCode project has grown somewhat, and I know that there are class files in there which are no longer being used. Is there an easy way to find all of these and remove them?
If the class files just sit in your project without being part of a target, just click on the project itself in the tree view, so you see all files in the table. Make sure you see the "Target" column in the table view, iterate through your targets and find the files that don't have a check anywhere -> they are no longer compiled.
But if you still compile the classes and they are no longer used, that case is a bit more difficult. Check out this project
http://www.karppinen.fi/analysistool/#dependency-graphs
You could create a dependency graph and try to find orphaned classes that way.
Edit: Link went dead, but there still seem to be projects of Objective-C dependency graphs around, for example https://github.com/nst/objc_dep
if they are C or C++ symbols, then you can just let the linker do the work for you.
if you're looking to remove objc symbols, then try to refactor the class name (e.g. to rename the class), and preview the dependencies that it turns up. if you reference classes/selectors/etc. by strings then... it may not be so effective. unfortunately, you often have to also test manually, to verify that removing a class does not break anything. remember that resources (like xibs) may reference/load objc classes as well.
This is a tricky question due to how dynamic objective-c is as you can never guarantee that a class is not going to be used.
Consider if you generate a class name and a selector at run time and then look up that class, instantiate that class and then call a method on that newly created object using that newly created selector. No where in your code do you explicitly name and instantiate that object but you are able to use it anyways. You could get that class name and selector name from anywhere outside of your code, even from some data from a server some where. How would you ever know which class is not going to be used? Because of this there are no tools that are able to perform what you are requesting.
Searching the project with the class name might be an option, thought it may not be the best solution. Specially it might be time consuming when you have many classes.

Why are public fields and properties interchangeably binary compatible?

In the day job, I work on a VB6 (I know, but don't mock the afflicted...) application that uses a number of libraries we have written (also in the ever illustrious VB6). One of these supporting libraries had a load of private members exposed via public properties, and I was asked to remove the properties, and promote the private member variables into public fields with the same name as the original properties.
Now, I'm no COM expert, but I was under the impression that each and every exposed item on a class gets it's own GUID. Since we would be going from a situation where each value went from 2 Guids (Property Get and Property Let) to one where they only used the one (the public field), I was expecting this to break binary compatibility - but it seems it hasn't done that.
Can anyone explain why?
No, it hasn't broken compatibility because it hasn't removed the property get and property let methods. It's just that the compiler is now writing them for you.
Isn't this one of the few areas where VB6 is arguably better than .Net?
In .Net public fields behave differently to public properties, and this makes some refactorings difficult and causes confusion.
In VB6 public fields behave exactly like public properties, which is why it's possible to switch without affecting binary compatibility. Behind the scenes, the compiler generates property get and set routines for public fields. In a sense VB6 has automatically implemented properties (now advertised as a "new feature" in VB10)...
I think it's a bit more subtle than that. You get a GUID for the COM interface (not each individual field/method). As I understand it the binary compatibility attempts to work out if the interface your currently compiling is backwards compatible with a reference version of your DLL (assuming you have one) and only changes the GUID if they are not compatible.
I'm therefore also surprised that it has decided removing all the get/set methods is compatible :/

Is it good practice to call module functions directly in VB.NET?

I have a Util module in my VB.NET program that has project-wide methods such as logging and property parsing. The general practice where I work seems to be to call these methods directly without prefixing them with Util. When I was new to VB, it took me a while to figure out where these methods/functions were coming from. As I use my own Util methods now, I can't help thinking that it's a lot clearer and more understandable to add Util. before each method call (you know immediately that it's user-defined but not within the current class, and where to find it), and is hardly even longer. What's the general practice when calling procedures/functions of VB modules? Should we prefix them with the module name or not?
Intellisense (and "Goto Definition") should make it trivial to find where things are located, but I always preface the calls with a better namespace, just for clarity of reading. Then it's clear that it's a custom function, and not something built in or local to the class you're working with.
Maybe there's a subtle difference I'm missing, but I tend to use shared classes instead of modules for any code that's common and self-contained - it just seems easier to keep track of for me, and it would also enforce your rule of prefacing it, since you can't just call it from everywhere without giving a namespace to call it from.
I usually put the complete namespace for a shared function, for readibility.
Call MyNameSpace.Utils.MySharedFunction()
Util is such a generic name.
Example from the .Net framework. You have System.Web.HttpUtility.UrlEncode(...). Usually you refer to this as HttpUtility.UrlEncode since you have an import statement at the top.
The name of the class which has the static utility methods should be readable and explainable. That is good practice. If you have good class names they might just as well reside in a Utils namespace, but the class name should not be Utils.
Put all your logging in a Logger class. All your string handing in a StringUtils class etc. And try to keep the class names as specific as possible, and I'd rather have more classes with fewer functions than the other way around.