Heenan, Lambert
Lambert.Heenan at AIG.com
Mon Jun 12 16:16:20 CDT 2006
Hello Drew (and anyone else following along in the discussion - feel free to chime in), 'Next, "but globals are bad news in any context", not this again. Public variables are not BUGGY, nor are they 'bad news'. They have a purpose, that is why they are there in the first place' . Sorry , can't agree with that either. Public variables are there so that code written for ancient systems, running languages that had only one kind of variable - public ones - can continue to be run. It's a backward compatibility feature. I know that may seem like a bold, overarching statement, but look at the history of programming languages. Why was the concept of 'local variables' dreamt up? Because having all global variables was a nightmare The fact that lots people (myself included!) have a tendency to cut corners and use them as a quick and dirty way to get data moving from one module to another does not mean that it's a good idea. There's really no excuse for using a global, as rewriting the code to use local variables requires very little effort. Likewise, writing a few lines of code to implement a very simple Let/Get pair of properties is not difficult. But the benefits are that you know exactly how and where your class' data is being changed. If you pepper your classes with public members fields then you have simply throws away 50% of the reasons for using classes. If you think that code is better because it uses less lines, or characters or pixels on screen, dots on paper or electrons moving though wires, then you are simply mistaken. I'd rather spend my time writing the few extra lines of code that the extra time needed to debug it when it behaves oddly. My argument against the use of globals is not based on the peculiarities of VB ("they lose their values" [if a runtime error is not trapped]) it's based on the idea that a global, by its very nature can be modified from almost anywhere at all in code, and that makes for a debug/maintenance problem. So if I were teaching someone some VERY basic code, like how to calculate the cube of an integer I COULD write this... Dim nNumber as Long Sub TryItOut nNumber = 7 Debug.Print "The cube of " & nNumber & " is " & nNumber^3 End Sub .. Which illustrates how variables are assigned values, how to use the 'power' operator and the concept of outputting results for debugging. However I would probably write... Function nCube(nNumber as Long) as Long nCube = nNumber^3 End Function Sub TryItOut Dim nLocalNumber as Long nLocalNumber = 7 Debug.Print "The cube of " & nLocalNumber & " is " & nCube(nLocalNumber ) End Sub Both examples do the job, but the latter version, at the cost of writing some more code, illustrates the concepts of local variables, parameter passing, functions calling and function return values. All essential to ordinary day-to-day programming. Regarding your error class example. "Both routines cause the same error, and stop at the same point. The SecondValue error NEVER reaches the ErrorHandler!!! If a property of a class is going to do NOTHING but hold a value, the only error you can get involving the use of that value is going to fall into the domain of the calling code. If you are setting an invalid value, i.e., wrong type, too big, etc, the error is going to occur in the code trying to set the value. Quite frankly, putting error handling in a property get/let combo above is pointless, it will never be used (unless it was just simply written wrong)." What you say here is perfectly valid for the example given, but it is also language specific. VB behaves just as you say, but a less strongly typed language will not. But even keeping the discussion within the domain of VB, sure you get a type error when you try to pass a string to a routine that wants an integer, so the class property error handler is not involved, but what about passing an integer that's outside the acceptable range to a routine that wants an integer? If MyValue is only allowed to take on values in one (or more) specific ranges, then you'd better be sure that it keeps within those bounds, and that's exactly what a property Let method can take care of. I guess what my point of view boils down to is that it's perfectly ok to teach programming concepts in itty bitty pieces, but the examples used should be sufficiently complex to illustrate why the technique being used *is being used*. That little bit of complexity can make the example seem more realistic. By building your first class with Let and Get properties the concepts of data hiding and access control methods are introduced early on, which is a good thing. After the beginner has "learned the rules" the notion of what might be gained and lost by bending the rules will make more sense. Lambert -----Original Message----- From: accessd-bounces at databaseadvisors.com [mailto:accessd-bounces at databaseadvisors.com] On Behalf Of DWUTKA at marlow.com Sent: Monday, June 12, 2006 3:11 PM To: accessd at databaseadvisors.com Subject: [AccessD] Class Rebuttal was: Basic Unbound Form ... Well Lambert, I'm glad you didn't write the MSDN, because if I had to wade through this kind of logic to learn what I have, I would probably go back to being a mechanic. First of all, "But not as much of a waste of time as the process of explaining later on why public members fields have drawbacks.", they don't have drawbacks, they have limitations, which I explained. I made it very obvious that a Public declaration is the same as a BASIC Get/Let statement. BASIC!!!! You can't put logic into a Public declaration, but you can with a Get/Let statement, which would no longer be a 'BASIC' Get/Let statement. Next, "but globals are bad news in any context", not this again. Public variables are not BUGGY, nor are they 'bad news'. They have a purpose, that is why they are there in the first place. The are things that you can do with a public variable that are simply nightmares to try and do without. In the advanced demo, I will show a method of public declaration which I'd LOVE to see you duplicate in another manner. As far as data encapsulation, look, if you build every class to go far beyond what you need it for, you're wasting time. I have a pretty flexible job, but even I don't over-program that much. If all you need is a place holder for a value, then just put a place holder for the value. Not a lot of lines, eh? Let's look at that. Public MyValue as Long That's one line. Dim lngMyValue as Long Property Get MyValue() as Long MyValue=lngMyValue End Property Property Let MyValue(lngEnter As Long) lngMyValue=lngEnter End Property That would be 7 lines. Seven times the amount of code. It's also 22 characters compared to 151 characters, which is still roughly 7 times more. For one property, great, you spend 21 seconds to create a property rather then 3 seconds. But now create a class that has 50 properties, non of which require any extra work done to them. Now instead of spending 2 and half minutes creating your class, you are going to spend 17 and a half minutes. It adds up. Now for this one: "It's a "property" of sorts, but more than that it's a gaping hole in a class definition that invites unintended side-effect, aka 'bugs'." Would you like to clarify that one for me? I'd just love to see what 'unintended side-effect that you get from my above example. Both will do the EXACT same thing. Even in an error situation. Here's a 'TestError' class. Property Let SecondValue(intEnter As Long) On Error GoTo Errorhandler intSecond = intEnter Exit Property Errorhandler: Err.Clear MsgBox "We got an error!" End Property Now let's test that out: Private Sub Command0_Click() Dim te As testerror Set te = New testerror te.FirstValue = "One" End Sub Private Sub Command1_Click() Dim te As testerror Set te = New testerror te.SecondValue = "One" End Sub Both routines cause the same error, and stop at the same point. The SecondValue error NEVER reaches the ErrorHandler!!! If a property of a class is going to do NOTHING but hold a value, the only error you can get involving the use of that value is going to fall into the domain of the calling code. If you are setting an invalid value, ie, wrong type, too big, etc, the error is going to occur in the code trying to set the value. Quite frankly, putting errorhandling in a property get/let combo above is pointless, it will never be used (unless it was just simply written wrong). So if you would like to argue this more, show me one SOLID difference between the two dealing with performance or operability. Saying that it's 'bad practice' is bull pucky, and saying that it 'leads to bugs' is even MORE bull pucky! I know a lot of this sounds like a rant, and some of it is. But I was asked to demonstrate how to create an unbound form using classes. I have taught before, and when you are teaching a complex subject, you take it one step at a time. You also put into what you teach what you have discovered on your own, and you try VERY hard to not prejudice your material too much. If you include a prejudice, you explain the facts, but let the student make their own decisions. That is why I defend a few things on this list that several members disagree with. I defend them because they are prejudices. Several list members have presented 'bad practice' items which are based on personal and prejudiced experience or tribal knowledge. THAT is bad practice. You have to keep in mind that the list is a mix of members. We would NEVER have had this particular thread offshoot if the list was made up of only expert programmers, because no one would have asked for such a demonstration. For example, the 'global variables are bad practice' thing. They are not bad practice. The arguments thrown up for them are either false, or misrepresented. For example the 'they can lose their value'. That is a mix of both. That particular argument is based on a trait of VBA, which any serious developer whould be well aware off, and that is that an unhandled error can provide a prompt to the user which will STOP the currently running code, which not only stops the current process, but it will release all memory resident values (including Global Variables). In Visual Basic, End closes everything up. In Access (or Word/Excel/etc.), End simply stops the VBA process, but the parent program is still running. Drew -----Original Message----- From: Heenan, Lambert [mailto:Lambert.Heenan at aig.com] Sent: Monday, June 12, 2006 12:48 PM To: 'Access Developers discussion and problem solving' Subject: Re: [AccessD] Basic Unbound Form with Classes and Collections Par t1. " Putting in Get and Let statements, with a class level module dimensioned would actually just be wasted lines of code in this demo project." ... But not as much of a waste of time as the process of explaining later on why public members fields have drawbacks. That they cause problems that the whole OOP methodology was designed to eliminate. In short, why try to teach the use of classes by beginning with an example which is bad programming. I'm sorry to have to contradict you there, but globals are bad news in any context, and they are especially bad when they negate the major advantage of using a class - data encapsulation, one of the two main reasons to use classes, the other being simplified code reuse. Especially in VB/VBA, a public member declaration looks exactly the same as a public variable declaration in a standard module. By using this as an example of a class the newbie is then faces with the puzzle of why there are different syntaxes for accessing the data. The answer is "because it's a class member", but little is learned from this fact. If instead you go to the trouble of declaring a couple of Get and Let properties, which will only take a couple of lines each, not thousands of them, then a much clearer idea of what a property is can be conveyed. "But you do agree that using Public in a class is essentially a property", well no. It's a "property" of sorts, but more than that it's a gaping hole in a class definition that invites unintended side-effect, aka 'bugs'. Lambert