3

I want to follow the MVP Userform architecture described in this excellent answer by Mathieu Guindon. However, I don't understand why in the FilterModel Class Module, and also the FilterForm Userform module, new Types are created within the Class whose elements are then redeclared as Properties of the Class. Why is this necessary? Why not just declare SelectedFilter as a property of type string? Am I missing something?

lamantin
  • 31
  • 1
  • 1
    It is not necessary, but can be considered a good practice. Clients should never be allowed to directly mess-up with internal variables. Using properties instead of public member variable will allow for parameter check, for example. – Vincent G Jul 23 '19 at 12:08
  • 2
    See [this answer](https://stackoverflow.com/a/45570268/1188513) – Mathieu Guindon Jul 23 '19 at 12:49
  • 1
    They call me the match maker. Well actually they don't, but they *could* – Marcucciboy2 Jul 23 '19 at 12:50

1 Answers1

6

Most properties need a backing field. Typically it would look like this:

Option Explicit
Private mFoo As String

Public Property Get Foo() As String
    Foo = mFoo
End Property

Public Property Let Foo(ByVal value As String)
    mFoo = value
End Property

When you look at an instance of this class in the locals toolwindow, you'll see both the mFoo private backing field and the public Foo property - and when the class has more than a handful of members, it quickly gets noisy.

Plus I really don't like this m prefixing scheme, but since VBA is case-insensitive, you can't have a foo backing field for a Foo property.

By declaring a Private Type to hold the encapsulated instance state...

Private Type InternalState
    Foo As String
End Type
Private this As InternalState

Public Property Get Foo() As String
    Foo = this.Foo
End Property

Public Property Let Foo(ByVal value As String)
    this.Foo = value
End Property

...now the property and its backing field can use the same identifier, there's no need for any prefix, we get an autocompletion list for all members of this, and the locals toolwindow is now grouping the instance state values under this, the only private field in the class, which makes the debugging tool much cleaner.

It's not a necessity, but I can't find a good reason not to do it. It's really a style/preference thing more than a best practice, but it has clear benefits.


Why not just declare SelectedFilter as a property of type string?

If that meant to say "why not just declare a public field of type string", then it's a different question, with a different answer.

Every class defines a default interface, whose members are the class' Public members. But interfaces don't expose fields, so if you have a public field on a class, its default interface will have Property Get and Property Let/Set accessors for it: by defining explicit Property members instead of just a public field, you are making the class definition consistent with its default interface. ..and you're encapsulating the internal state - encapsulation being one of the 4 pillars of OOP: things that have no business being public, shouldn't be public. With a property, you get to control how the backing private field is assigned: no one outside the class can access it. Maybe you need to run some validation logic and raise an error if external code attempts to assign Foo to an empty string, or to a string that doesn't match some regex pattern, for example.

The advantages of using properties vs public fields is beyond the scope of this question (and already answered elsewhere) though, but the topic is very much language-agnostic, so don't necessarily confine your research to VBA: the reasons to use (or not) properties vs public fields are the same in VBA as they are in Java or C#.

Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235