PDA

View Full Version : Public object variable or pass as argument?



gmaxey
08-06-2012, 03:13 PM
I realize that I am asking a question where the answer could depend on what camp the responder hangs out in. I am working of a farly large project where access to the userform is required in many auxilary procedures.

I can use something like this in the form module:

Call modAuxFunctions.DoThis Me

and in the the modAuxFunctions module:

Sub DoThis(ByRef oFrm as UserForm)
With oFrm.
.blah, blah
End With
End Sub

or I can just create a public userform object p_oFrm

and then just

Call modAuxFunctions.DoThis

Sub DoThis()
With p_oFrm.
.blah, blah
End With
End Sub

What are the advantages and disadvantages? Thanks.

fumei
08-06-2012, 09:07 PM
Or both, depending on requirements. I am not convinced of the superiority of either case. Assuming of course that the public userform is appropriately released via Unload. If it is there is little to be said for memory issues.

gmaxey
08-07-2012, 02:24 AM
Gerry,

Thanks. Actually I had been using both (not exactly intentional). I've been scrubbing the code and realized that I was using both a public varialbe in some places and passing the form in others. I just wanted to do one or the other and was looking for some guidance.

fumei
08-07-2012, 03:11 PM
So you want to ONLY use one (or the other)?

Forced to choose, I vote for the public userform.

Frosty
08-08-2012, 09:21 AM
When are you instantiating the user form? That would be my question over the unloading of it. I wouldn't go with...
Public p_oFrm As New myUserFormName

but rather
Public p_oFrm As myUserFormName

It's certainly easier to have a public variable rather than pass the object around to a lot of routines... but I would probably question the overall structure if you need to pass a userform (rather than the values of a user form) around to so many sub-routines.

However, for anyone else reading this-- I advocate the public variable over the use of the parameter *only* because I know Greg already understands the concept of scope pretty well. For most of the people who come looking for answers, I would advocate something along the lines of this...

Public Sub MyMainRoutine
Dim oMyForm As myUserForm1

Set oMyForm = New myUserForm1

oMyForm.Show

SubProc oMyForm.cmbControl.Value
End Sub
Sub SubProc (myStringValFromThatComboControl As String)
'do stuff with the combo control value passed in
End Sub

gmaxey
08-08-2012, 04:06 PM
Gerry, Jason,

Thanks.

Knowing zilch about VB and the tools for creating real applications, I depend on my limited knowledge of userforms. Sometimes the projects get rather involved and to help me keep track of my code I will ofter take sections, for example a lenghty section of code use to configure lables, captions, ect. out of the form module and put it in a standard module, hence;

blah, blah
auxMod.ConfigureForDelete Me
blah, blah

and in auxMod have

Sub ConfigureForDelte(oFrm as UserForm)
With oFrm
.label1.Caption = "XX"
and so on.

Again realizing I was using a public variable in other places in the project, I just wondered which was best to user overall.

Thanks again.

Frosty
08-08-2012, 04:44 PM
I definitely agree with breaking "doing stuff" code out of user forms when possible. But my preference is to have code which actually deals with the form stay in the form. I often have centralized private procedures within user forms to handle adjusting captions (and .Visible and .Top and .Left etc etc), because I often find that I need to use that same code from multiple events in the same form.

But for me, everything that has to do with displaying information and capturing information from the user I leave in the form. Everything that does something with that information I keep out of the user form. There are lots of ways to organize, that's just my way.

I've seen the kind of structure you're describing (a module which handles "core functions" for a variety of userforms), but it has ended up being a big pain to troubleshoot issues (while you bounce around between multiple spots), and over the life-cycle of development, the project often ended up with a single procedure in this external module which was only in use by a single userform (so why not just have it be a single procedure in the userform?).

So I guess my recommendation would be to not do it either way, in terms of public variable vs. passed parameter :)

That said, there are times when it makes sense to create two or more userforms which have similar functionality and do similar things, rather than having a single userform and needing to do all kinds of movement of controls in order to present something relatively simple to the end-user.

In those cases, I typically create some kind of intermediary "data holder" type class, which I then use in both forms (or, if I need a bigger data holder "bucket" than I can reasonably present to the end-user in a single userform, I would employ that strategy as well). And the class doesn't have to be really complex.. it could simply be a class module with a whole bunch of Public variable declarations right at the top. No Let/Get pairs... just a "simple" class so that I can pass a bunch of data around.

But you and I have had this conversation before. My "style" of programming is to utilize the immediate window *a lot* while developing my routines. This forces me to modularize my code while I develop, and if I'm needing to pass more than a few parameters, I tend re-think my structure. And obviously, passing entire userforms as parameters doesn't really fit into my style of programming... so my opinion on the subject may be a round-peg/square-hole problem. I'm curious to hear what others would say.

But, in terms of the public object vs. passed parameter argument... for me, it doesn't have much to do with end-user experience, just your programming preference. In the occasions when the public object falls out of scope, you'll probably start your troubleshooting in the wrong procedure (since it will probably have been something in the calling routine which caused the object to fall out of scope, rather than an issue in your sub procedure where you wanted to use some control on the form). But this is probably a theoretical problem.

The reality is probably that if you use a public variable, it's probably going to stick around as long as you want it to in normal usage... and then it's just a question of whether you like to set watches in the watches window (public variable is fine), have them automatically set for you in the Locals window (passed parameter would be useful), or don't use that stuff at all (doesn't really matter what you do -- you'll still be stepping through code trying to identify any problems anyway). At which point-- the "best" way to do it is the way in which you feel the most efficient.

The only real requirement is commenting and good naming, so that others can follow what you did... but then, you already know all this, so I'm mostly talking for someone else who comes along and reads this thread ;)

Frosty
08-08-2012, 04:53 PM
Oh, and as an additional aside... userforms aren't that friendly in watch windows anyway (since you have to wade through a whole mess of controls and properties to get to what you want to look at)... which is probably the reason why I don't use them much as parameters.

The majority of the time I spend dealing with userforms is making user forms really really intuitive, and making sure all the events in use are the appropriate ones (i.e., don't necessarily use the "change" event for a checkbox control when you can use the "click" and "keydown" events to capture the actual user-interaction, and still give yourself to flexibility to change the value of the checkbox via code without triggering an event that you only want to have fire because the user did something).

But I don't think there is necessarily a "right" answer to your real question.

fumei
08-08-2012, 06:04 PM
OK. I agree (of course) with Jason's comments. And yes, having a rhetorical discussion read by moderately experiencedf people needs be carefully discussed within the confines of Scope. If someone, as Greg does, fully understands Scope then the relative merits of public variable vs passed arguments narrows the discussion to a style of programming.

I agree that there is no "right" answer, especially if - as seems to be the case - you are talking about massively complex structures with multitudinal interations of userforms.

While I understand the desire to have ONE method (for neatness sake I suppose), I am not sure it is a great idea (although maybe a good idea) to be dogmatic.


Jason: if I'm needing to pass more than a few parameters, I tend re-think my structure. I would strongly agree with this.

Jason:
That said, there are times when it makes sense to create two or more userforms which have similar functionality and do similar things, rather than having a single userform and needing to do all kinds of movement of controls in order to present something relatively simple to the end-user.How often has this come up? I suppose it happens, but I personally lean towards having more complicated display requirements (altered through resizing and visibility) on a single userform. It does happen, but it takes a LOT before I bring in multiple userforms. After all, you can only interact with ONE userform at a time. True (very true) it takes quite a bit more development to achieve everything on one userform. I have found that all that work tends to actually enhance my logical understanding of what is needed/desired to make a viable user interface. Which is, IMO the main point of having userforms. To get input from the user with the primary purpose of making it easier for the user...not me as the programmer.

Frosty
08-08-2012, 07:34 PM
I try to stick to a single userform when possible and when simple, but I believe it's ultimately easier to use design-time to do the bulk of my "designing" and run-time to do very limited designing (and by that I mean a lot of adjusting the positions of controls for the purposes of multiple uses of the same form).

Of course, it's a feel thing for each project and what's appropriate when... but my general approach would be to avoid setting .Top and .Left of too many controls during the Initialize or Activate events. If I'm doing that, I'm probably going to regret it later when the client comes back with a new design spec (couple extra controls, a few deleted, different tab order, etc etc).

It's so much easier (for me) to just move stuff around using the GUI during design-time, than to figure out the right position programmatically during run-time (although I've used my share of "More >>" and "<< Less" command buttons). And it's certainly easy enough to copy controls and chunks of code between userforms.

But then, my userforms tend to be very very light on code-- sticking pretty strictly to events for the controls and then using the data from the userform elsewhere, outside of the form.

In terms of concrete examples...
1. Repurposing a form for multi-use:
I've repurposed a single userform for two separate uses in the following scenario: Letter creation and updating an existing letter (just changing letterhead/author info). This was in the context of a mature userform (in terms of development life cycle), thoroughly tested by end-users, which I knew was not going to change much.

2. Multiple forms with similar functionality:
A base code project which gets highly adapted for different clients. While the engine may be the same (gather info, use info to create a document), the way it is presented can be dramatically different. And in addition, there may be more or less info needed depending on the client.

So basically, I'm describing an "immature" userform where I need flexibility for my designing. That same scenario (letter creation vs letter updating) might be better to have as two separate forms for the purposes of design flexibility, even though some elements are shared.

I guess, if I had to sum up-- if I'm likely to be making adjustments to the form during development , I'd rather do it with the GUI than via VBA.

I find that this allows me to tweak forms endlessly until they have a nice flow and visual appeal... whereas the ones I spend an exorbitant amount of time tweaking the positions of various controls via VBA tend to end up looking (to me) more clunky, but not so clunky that it's worth my time to keep tweaking.

fumei
08-08-2012, 07:40 PM
All good points. And reinforces the there-is-no-right solution. It depends. I do agree with the majority of work should in principle be at design time.

gmaxey
08-11-2012, 08:44 AM
Jason, Gerry,

Thanks for the discussion. Jason, I'm sure you've heard the adage"you can't educate a mule." I really wish I was more comfortable with and had a better grasp of employing classes.

In those cases, I typically create some kind of intermediary "data holder" type class, which I then use in both forms (or, if I need a bigger data holder "bucket" than I can reasonably present to the end-user in a single userform, I would employ that strategy as well). And the class doesn't have to be really complex.. it could simply be a class module with a whole bunch of Public variable declarations right at the top. No Let/Get pairs... just a "simple" class so that I can pass a bunch of data around.

Despite our exercise last year with the DeducedSentences, I still only see general fog whenever subject of classes comes up :-(