What's a factory? For the purposes of this article: it is code within in a Class Module that creates an instance of that Class, assigns any necessary Class member values and returns the newly created instance to the calling code.
Eh?
This is a Class Module with a factory
The factory is made up of the 'Create' Procedure and it's supporting 'Self' Property. Together these allow you to create an instance of the Class like this
Instead of the more 'traditional'
Yes, this is the nearest you're gonna get to a (parameterised) constructor in VBA. Still, it only saved 2 lines of code when creating the instance at a cost of 10 lines in the Class Module so why bother? This is why:
If you create the same objects in multiple places in your code then you save 2 lines each time!
If the class has many properties that must be set when an instance is created (more than the 2 in the example above) then suddenly you're saving many more lines in each place in your code.
The code using the factory to create the instance of the Class is much clearer in its intent.
You have some validation at design time that you have correctly created an instance of the Class (e.g. the VBE will refuse to compile the line that calls the 'Create' Procedure if you omit a parameter) instead of potential runtime bugs.
It's a lot of typing though isn't it? The factory. All those Properties. Well, what if I told you that the only code in the Class Module I manually typed out were the two lines declaring the module-level variables, i.e.
... and everything else in the Class Module that you see above was automatically added by VBE_Extras? I selected the menu option Extras then Add Factory , I checked I was happy with the values in this dialog
Then clicked Add. Simple as that.
And if your preferred coding style is to use a Type with one or more Type elements (instead of the module-level variables used in the above example) then VBE_Extras will happily add a factory for that instead (adding a module-level variable for the Type at the same time)
Similar to the first example, the only code I manually typed in this example was the Type definition ... everything else was automatically added.
If you want to add multiple factories (perhaps with parameters for different combinations of module-level variables / Type elements) then you can do so, and VBE_Extras is intelligent enough to know not to add Properties that already exist (and to add Properties that don't).
And if I didn't like some of the other options (the default name used for the factory and parameters for the Property Lets/Sets; the number of blank lines between each member; the number of spaces used for indentation; behaviour around removing prefixes from Property names) then I can configure those in advance …
I know that some reading this article will look at the line ...
... and think: that's not valid VBA code! And the answers is that 'normally' it isn't. However, by setting the value for the Attribute 'VB_PredeclaredId' to True, it is valid VBA code. This Attribute (along with a number of others) is hidden in the Module header for all Class Modules. It has a False value by default, however, along with adding the code for the factory and Properties, VBE_Extras also sets the value of this Attribute to True, so enabling the factory. For more information on Attributes, see my VBA Attributes blog post.
One more thing. This is relevant only if you want to create an instance of the Class (that you have added the factory to) from an 'other' VBA Project that has a reference to 'this' VBA Project. Now that you have added a factory (so long as it has Public access), you have a way to create instances of this Class from that 'other' VBA Project.
As you would anyway when accessing instances of a Class from an 'other' VBA Project, you will first need to set the VB_Exposed Attribute to True - this Attribute you can update using the VBE UI: select the Class in the Project Explorer window then in the Properties window adjust the value for Instancing to '2 - PublicNotCreatable' (or you can use VBE_Extras to update the Attribute).
Then the same line of code ...
... can be used from your 'other' VBA Project.
Comments