Suppose you are creating a new container control to encapsulate some functionality onto this new control. You’re already thinking about “encapsulation” which is a good thing.
Why, when you create this new container, would you then make all the controls on it public so code outside the container can change it ? That seems like it would be a good way to ruin the encapsulation you’re trying to achieve.
And, if you do this, any changes to your nicely set up container then may require broader changes in your application if, or when, you make changes to your container.
Lets walk through a quick and simple example that illustrates the issue.
Start a new desktop project.
Add a container control to the project – it will cleverly be named ContainerControl1.
Add a Generic Button to this container. It will be called “PushButton1”.
Make sure its scope is “Public”
Now add an instance of this container to Window1.
Add the Open Event to Window1.
In there put
ContainerControl11.Pushbutton1.enabled = false
And when you run the pushbutton on the container will indeed show up as disabled.
Now imagine you add a lot of other functionality to your application and there are several places where your code enables or disables this button under various conditions. And perhaps you reuse this container on several other windows.
And then you decide to make some changes to the container. And one of those changes is to rename the button to something more meaningful.
In the project we’ve built so far this isnt so bad. If we rename PushButton1 to “ContainerButton” and try to run again we’ll get an error saying
Window1.Open, line 1
Type "ContainerControl1.ContainerControl1" has no member named "PushButton1"
ContainerControl11.PushButton1.Enabled = false
Now in a small application this is manageable. You simply hunt for and change the names and off you go.
But, you may have to do this many times depending on how many times you set the enabled state of the button. And you have to update them all.
And none of this was necessary.
If instead of letting code outside the container reach in and manipulate the control directly we provided an API to do this and hid the innards then we could be sure we have fewer places to fix and that no code outside the container isnt somehow changing the setup in some way that will cause other issues.
In the example lets do this.
In ContainerControl1 add a method
SetButtonEnabled(assigns isEnabled as boolean) ContainerButton.enabled = isEnabled End Sub
Make the container buttons scope Private.
Now if you run you will get an error in the Window1.Open event saying
Window1.Open, line 1
Type "ContainerControl1.ContainerControl1" has no member named "Pushbutton1"
ContainerControl11.Pushbutton1.enabled = False
This is because the push button is now private and hidden to code outside the container control.
So we’ll fix this one line to
ContainerControl11.SetButtonEnabled = False
Now if you run the button is once more disabled. But now when we make changes to the ContainerControl we can focus on the container control and the methods it exposes to the rest of our code and not have to worry that we will have to fix a lot of other code elsewhere in our application.
Lets try this out.
Open the container and change the buttons name to “foobar”. And change our method we had for setting the enabled state to
foobar.enabled = isEnabled
And run the sample again.
We made two small changes and no other code had to change. If we had used this container many many times the time savings could have been significant. And the chance for odd bugs caused by code outside the container altering the containers contents significantly reduced.
Make your controls private and expose an API for them and save yourself a lot of grief.