Wiki Home

VBReuse For VFP ers


Namespace: SoftwareEng
A Wednesday Night Lecture held 2000.11.29, presented by Vin Miller
"Code Reuse in VB: a Primer for VFP Programmers."

This session will discuss techniques for code reuse in Visual Basic, from the point of view of Visual FoxPro developers. It's no secret that Visual Basic does not support inheritance, and at first glance, this can seem an insurmountable obstacle to effective code reuse (especially for those of us spoiled by VFP's quite-thorough inheritance features).

However, code reuse is possible in Visual Basic. This session will cover programming techniques that make reuse possible. Many of these techniques are also applicable in Visual FoxPro - sometimes, a slight shift in mindset is required in order to achieve high degrees of reuse even in the absence of inheritance. The pros and cons of these techniques will be discussed.

Visual Basic also includes several technical features that allow for code reuse (some of which are not available in VFP). We will discuss multicasting of control events (an underutilized technique that takes advantage of VB class modules and the WithEvents keyword); the creation of simple ActiveX controls in VB; and the use of form (and other) templates in VB development.

One last note: this is a wide topic, needless to say. We'll touch on each of the topics mentioned, and more, but my ultimate goal is to provide starting points for Visual FoxPro developers who want or need to begin developing in Visual Basic. A prior, general, understanding of VB is expected, since we won't have time to cover each and every keyword as it occurs. However, since this is intended as a Primer-session, I really don't expect it to be a tremendously code-heavy lecture (with the probable exception of the bits on multicasting and ActiveX creation).

[Irrelevant material has been trimmed.]

Session Start: Wed Nov 29 20:54:30 2000

[20:54] *** Now talking in #VisualBasic

[20:54] *** Topic is '"VB Reuse For VFPers" with Vin Miller'

[20:55] {Evan Delay} The presenter tonight is Vin Miller. Vin Miller is an independent consultant based in New York City, working in both Visual FoxPro and Visual Basic. He was a contributing author to Que's Special Edition UsingVisualFoxPro6?, and has published recent articles in both FoxPro Advisor and Access-VB-SQLServer? Advisor. A brief mid-90's foray into statistics and research resulted in co-authorship of several works on international demography and quantitative research techniques.

[20:55] {Evan Delay} Tonight's topic is "VB Reuse for VFP Developers"

[20:55] {Evan Delay} Take it away Vin!

[20:56] {VinMiller} Hi everyone. And thanks, Evan, for putting this together.

[20:56] {VinMiller} As Evan mentioned, tonight we'll ve discussing VB code re-use, froma VFP'ers perspective.

[20:56] {VinMiller} I have been working in VFP for about ten years, and in recent years, I have worked increasingly in VB as well.

[20:57] {VinMiller} I think that just about everyone who's ever checked in on the UT knows that the issue of inheritance comes up over and over, and unfortunately, at times, VB's lack of true inheritance is cited as a reason that code resuse is not possible. Well, that's not really true. So, I would like to draw on my experiences tonight as a VFP'er who has begun working cross-platform to discuss the strategies and technical issues involved in code re-use in VB.

[20:58] {VinMiller} I'd like to discuss these issues in two very general ways. First, there are object design issues, which might require a different (i.e., inheritance-less) point of view and second, there are indeed some techniques in VB that are not even available in VFP.

[21:00] {VinMiller} To be honest, in my opinion, the first category is the more important of the two. While VB allows for ActiveX control creation and some other techncniques you might not see in VFP and while these are helpful, the bulk of code re-use I have seen depends more on designing objects effectively, even without the so-called "true" inheritance.

[21:02] {VinMiller} The best VB code re-use I have seen, and the code re-use that I have been most proud of in my own work, makes effective use of the perhaps familiar concepts of delegation, composition, and aggregation.

[21:03] {VinMiller} Now, these techniques are also available to the VFP programmer, but because inheritance provides such a slick alternative, they are not always used to the fullest.

[21:04] {VinMiller} I'd like to give a few examples based on questions I have been asked recently by VFP programmers, a few on the UT, but most ooff-line (otherwise known as "in person").

[21:05] {VinMiller} I have a few sample files that I can later make available for download, but for now, given the breadth of this topic, I would like to stay a bit more general. Hope that's okay with everyone.

[21:06] {VinMiller} Example Number One is a question asked of me just a few days ago by a friend of mine. Basically, he has been working on a system in VFP that deals with monetary transactions.

[21:07] {VinMiller} The question he posed to me was very simple. In his current VFP design, he has a Transaction object, which is an abstract object. This object includes some code for extremely high level tasks, such as checking whether an account at his company is really valid, but no instance of a Transaction is ever created. Instead, he subclasses special transaction types from this object: for instance, Credit, Debit, and Transfer.

[21:09] {VinMiller} His question was, "How could he ever accomplish such a thing in VB without inheritance? Would he need to repeat the 'higher-level' functions in each class, since he couldn't inherit?"

[21:10] {VinMiller} The answer, as I bet you have guessed, is no. Instead, by taking advantage of delegation techniques, he could create a special Credit class, let's say, that referenced, and delegated some tasks, to a "parent" Transaction object.

[21:12] {VinMiller} This might be a good time to point you to some files to download. If you go to vinmiller.com\downloads, there is a file called UTLecture.zip. It's quite small, but if you would like, go ahead and download and unzip it.

[21:14] {VinMiller} In the meantime I will continue discussing the delegation technique with the transaction examples. Let's say, for instance, that the Transaction class has a method called "CheckAccount" which verifies that a person exists on the system.

[21:15] {VinMiller} In VFP, you might create a subclass of Transaction called Credit, which would inherit this method. If you follow a delegation technique, rather than inheritance, your strategy will be a little different. In this case, you would create an instance of the Transaction class, within the Credit class, and call its methods as needed.

[21:17] {VinMiller} In other words, by creating an instance of what might be termed the "parent" class, and using it as a helper class, you can centralize (and reuse) your code.

[21:18] {VinMiller} This turns the inheritance paradigm that you might be used to on its head a bit, at least when it comes to the insides of the object.

[21:18] {VinMiller} Rather than inheriting from a parent class, you create an internal instance of the parent class within the child class, and take advantage of its code this way.

[21:19] {VinMiller} This, in fact, is where the IMPLEMENTS keyword comes into play. You may have heard of this piece of syntax, or even worked with it... and in fact, VFP 7.0 will apparently allow for it as well.

[21:20] {VinMiller} IMPLEMENTS is used to implement a particular interface, within a class.

[21:21] {VinMiller} This is a concept that took a little while to soak in for me, but it is a crucial point in code reuse: ineterface inheritance.

[21:22] {VinMiller} We are not used to discussing interfaces in VFP. Instead, we talk about classes only, but in VB, and in other languages, the concept of an interface is crucial to code reuse.

[21:23] {VinMiller} Simply put, an interface is the "public face" of an object, while the class code behind it acts when called upon by an outside object. By implementing a particular interface (created as a class module in VB) you can guarantee, at compile-time, that a class will account for each and every method in the interface.

[21:24] {VinMiller} The closest analogy we have to an interface in VFP is an abstract class, which would include method calls but would not, itself, be a creatable object.

[21:26] {VinMiller} So, in the example I have been discussing, the Credit class Implements the Transaction class/interface, which guarantees that we will (must!) account in the Credit class for any methods specified in the Transaction class.

[21:27] {VinMiller} A common technique, and one which I use in the file examples, is to create an instance of the parent class within the child class, and then in each of the child's functions or subs, pass the call along to the function or sub of the same name in the parent class.

[21:30] {VinMiller} The project in the sample files consists of one form and several class modules. If you do not see a tree-view project window in VB, Ctrl-R will bring one up.

[21:30] {VinMiller} Go ahead and double-click on the frmSubmitTransaction form.

[21:31] {VinMiller} What I have done in this project is coded several classes (Contribution, Transaction, Transfer, Withdrawal), and I use slightly different techniques for reusing the code in the transaction class.

[21:32] {VinMiller} First of all, let me point out that in VB, a class module holds one class. You may be used to the concept of a class library in VFP, but this approach is a little different.

[21:33] {VinMiller} Double-click now on the Transaction class (under class modules).

[21:33] {VinMiller} I hve created some fake -- but somewhat realistic -- functions here: EnoughInAccount, ValidAccount, and ModifyAccount. I've also added messageboxes where you might, really, have 500 lines of code. This will let us see these classes in action when we start the form.

[21:35] {VinMiller} This is a pretty basic little class. Now, go ahead and open the Contribution class. As you can see, virtually the first step we take in defining this class is to tell VB that we are Implementing the Transaction class.

[21:35] {VinMiller} What does this do? Well, several things.

[21:36] {MichaelSchwaid} So the transaction (code) is the 'ancestor' class?

[21:36] {VinMiller} Exactly.

[21:36] {VinMiller} That is, conceptually speaking. What it really is, is the the interface of the Credit class. Remember I mentioned that even in VB, defining interfaces was a little confusing?

[21:37] {MichaelSchwaid} Understood (interface)

[21:37] {VinMiller} That's because there's no special Interface designer. Instead, you create a class module, define the interface, save it as a class, but use it as an interface. Yuck.

[21:38] {MichaelSchwaid} Polymorphism in action.

[21:38] {VinMiller} On the other hand, while some VB programmers I know define their interfaces with absolutely NO code, others do in fact include common methods within this "Ancestor" class.

[21:39] {VinMiller} Take a look at the combo box on the top left of this window -- the one that probably says "Class". You'll notice that in the pulldown, you now also have a Transaction option. VB knows you have Implemented the Transaction class/interface, and is allowing you to access its methods.

[21:40] {VinMiller} This is similar to subclassing a parent, in VFP, and "inheriting" those methods. In VFP, you can see the methods you have inherited.

[21:41] {MalcolmDonald} Which window?

[21:41] {VinMiller} Double-click on the Class Modules | Contribution class, under the project window. Do you see the one I am talking about?

[21:42] {MichaelSchwaid} In the transaction window the functions are listed under (general) why not under class?

[21:42] {VinMiller} You should see a code window, with two combo boxes above it. This is the same code window you see in VB when you design a form or BAS module as well.

[21:43] {MalcolmDonald} Drop down (General) to get class

[21:43] {VinMiller} The "Class" group includes only those actions intrinsic to a class... Initialize and Terminate.

[21:43] {MichaelSchwaid} Terminate as in destroy?

[21:44] {VinMiller} Exactly. And, any items that I define -- whether they be functions/methods, or child objects (as we'll see in a moment), belong in the General categoy.

[21:44] {VinMiller} So, we have the intrinsic class behaviors, we have my definied behaviors for this particular class (Contribution), and we have all of the defined behaviors for any Implemented class/interface.

[21:45] {VinMiller} It's similar, in VFP terms, to having the base class methods; the parent class methods; and the specific class methods that you add.

[21:45] {VinMiller} Remember, a class module consists of one class -- it's not quite like a VFP class library, which can hold many. Does that make sense?

[21:47] {VinMiller} Right, we are sitting right now in the code that defines the Contribution class. We have told VB to make this Contribution class implement ("look like") a Transaction.

[21:48] {VinMiller} Picture this entire file sitting inside a DEFINE CLASS... END DEFINE construct in a VFP prg file or in the code the class browser would generate.

[21:48] {VinMiller} That make sense, Tom?

[21:49] {TomAvery} Yes

[21:49] {VinMiller} Okay, let's continue. Here's the difference in VB: in VFP, you can select that parent class method, and see absolutely nothing in there, right? In which case, it means that, when that method is called, the parent class behavior will kick in.

[21:50] {Evan Delay} Yup

[21:50] {MichaelSchwaid} As in subclass method is empty parent code is used...

[21:51] {VinMiller} Yes.

[21:51] {VinMiller} Well, that doesn't happen in VB. While we have inherited the Interface (by saying "IMPLEMENTS Transaction"), we have not (YET!) inherited the code from the Transaction class.

[21:51] {VinMiller} An instance of this Contribution (uh.. "credit"!) class could have that method available, but when it was called, nothing would happen. It's as if, in VFP, you put an asterisk in the child class method structure, to denote "don't do anything."

[21:53] {VinMiller} In other words, we have Interface Inheritance in VB, but not Implementation Inheritance.

[21:53] {VinMiller} I don't know if those buzz-phrases are familiar, but pick up any VB mag that's talking about DotNetOffsite link to http://gotdotnet.com these days and you'll see them a lot.

[21:53] {VinMiller} So, that brings us right back to where we started. How do we inherit the code? As you can see, we create an instance of the parent class, right inside of the Child class, and use it as a helper object or sorts.

[21:54] {VinMiller} ... "of sorts"

[21:54] {VinMiller} Let me take a walk through this with ya. We have implemented the transaction class....

[21:55] {Evan Delay} Q: why do you use "m_" instead of "o" for the transaction class?

[21:55] {VinMiller} ... and as soon as the child instantiates, we create an instance of that class, as well (set m_transaction as transaction)

[21:56] {VinMiller} Just a naming convention, really. In VB, "m_" frequently denotes a module level (i.e., Private) variable.

[21:56] {MichaelSchwaid} For example, implements create an instance w/o handle which is assigned to m_transaction.

[21:56] {VinMiller} I could have (often do) use "o" -- but many VB coders I know use "o" when it's an exposed object, and "M_" when it is private.

[21:57] {VinMiller} Almost Michael. Actually, I am really doing two things here with Transaction.

[21:57] {VinMiller} First, I Implement it, which tells VB, make sure I use this interface -- that is, make sure that I have these methods available and account for them. Second, I create an instance of transaction, as a private child object of this class.

[21:58] {VinMiller} Then, in each of the Transaction Interface's methods, I simply pass control to the same method of that parent instance.

[21:58] {VinMiller} Take a look again. Do you see what I mean?

[21:58] {VinMiller} Keep in mind that when I type things like "Transaction_Valid = " it's like saying "RETURN" in VFP.

[21:59] {VinMiller} So what I am doing in this class is the following --

[21:59] {VinMiller} 1) You, Mr. Contribution, are a Transaction as well.

[22:00] {VinMiller} 2) You, Mr. Contribution, have a little helper object which holds a reference to Transaction.

[22:00] {MichaelSchwaid} So you can 'implement' 2 interfaces with same method names the prefix designates which interface?

[22:00] {VinMiller} 3) At each of the exposed methods, I will pass along whatever you ask of me, right to the helper object, and return the result.

[22:01] {VinMiller} Michael -- yes. In fact, it's important to point out that Multiple Interface Inheritance is available in VB.

[22:01] {MichaelSchwaid} Well explained.

[22:01] {VinMiller} And this leads to the next important point. Most of what I am doing here would be possible, if you think about it, without IMPLEMENTS.

[22:02] {VinMiller} In fact, think it through -- you could do this right now in VFP, couldn't you?

[22:02] {Evan Delay} Yup

[22:02] {VinMiller} You could define method names that are the same as some other object, and pass along control to a hidden reference to that object.

[22:02] {MichaelSchwaid} In other words w/o interface to control methods available?

[22:02] {VinMiller} So, what does Implements buy us?

[22:02] {VinMiller} Michael -- not sure I got yer meaning there.

[22:03] {MichaelSchwaid} Keeps us within defined implementaion (known methods, standard interface)

[22:03] {VinMiller} Yes, that's one thing that Implements buys us -- it guarantees that the developer will account for all of the Implemented Interface's methods.

[22:04] {VinMiller} Also, though, it really does define the Contribution class as a transaction.

[22:04] {VinMiller} We don't have hard-typing/early-binding in VFP (yet!) so this may take a moment to set in, but in VB, when you take an action against an object you can, if you want, make certain assumptions. For instance, you might demand that a parameter in a certain function be an instance of the Transaction class!

[22:05] {VinMiller} In that case, a parameter list might include "oTransaction as Transaction", and if you pass an instance of the Contribution class we have designed to that method, you will be just fine.

[22:06] {MichaelSchwaid} Strong typing?

[22:06] {VinMiller} Without IMPLEMENTS you couldn't do that. I don't want to get bogged down in this point, but I just want to make it clear -- by using Implements you have forced developers to account for all pieces of the interface, and you have also strong-typed the subclass as a TypeOf the parent class.

[22:07] {MichaelSchwaid} 'Forced' meaning a developer can't add a new method?

[22:08] {VinMiller} No, a new method is fine. But, each and every parent class method needs to be accounted for. Even if it is left empty, you at least need to go up to the combo box on the right, grab it, and therefore place a reference to it in the code.

[22:08] {MichaelSchwaid} Ok

[22:08] {VinMiller} Of course, you don't need to do this in VFP. It inherits it automatically.

[22:09] {VinMiller} This may all seem a pain -- and it is! -- but, if you consider that the Transaction class might have ten methods with a total of 900 lines of code adding ten method declarations in Contribution (or even "Credit") that look like what I have here... well, it's not so bad.

[22:10] {MichaelSchwaid} The 'implements' keyword is what adds functions to combobox?

[22:10] {VinMiller} Michael - Yes.

[22:10] {VinMiller} Again, though, if this prompts you to think "I have to do all that!" you are not alone! VB'ers have been comlaining for years about this, too. But, again, we are talking about a few lines of code per method to inherit the functionality of a parent class. That's not unworkable, in a lot of cases.

[22:11] {VinMiller} But I'd like to point out again, that Delegation doesn't necessarily require the Implements keyword.

[22:12] {VinMiller} The example project includes several techniques for creating, calling, and manipulating conceptual children of the parent transaction class.

[22:12] {MichaelSchwaid} Looks like code is added automatically as selected from combobox.

[22:12] {MalcolmDonald} How is it done w/o the IMPLEMENTS keyword?

[22:13] {VinMiller} Michael -- only because I had already typed it. It is just pointing you to the code I already had there.

[22:13] {VinMiller} Malcolm -- good question. Click on the Transfer class module.

[22:13] {MichaelSchwaid} (I erased and selected it gave me prototype)

[22:14] {MalcolmDonald} Done

[22:14] {VinMiller} Michael -- right, the protoype it gives you. But that's all. Now, though, try to erase and then "Start" (F5)

[22:14] {VinMiller} You get an eror -- "Hey, you didn't account for something that's required!"

[22:14] {VinMiller} Lte's move now to the transfer class.

[22:15] {MichaelSchwaid} Thanks!

[22:15] {VinMiller} Here's a case where I am still using Contribution... but without Implements. I need to enforce polymorphism myself here. For instance, I create a method called "ValidAccount" with the same requirements as the parent class.

[22:17] {VinMiller} Then I pass control. The problem is that without Implements, we lose some of those benefits discussed above. The Contribution delegates to its parent (every teenager's dream, I bet). That's what I meant when I said that this model turned inheritance on its head a bit.

[22:17] {VinMiller} The class has an object within it, and that object is an instance of its parent, which it makes do its work.

[22:18] {VinMiller} And that's also the case without Implements (in the Transfer class module).

Public Function Transaction_ModifyAccount(ByVal strAccount As String, ByVal lngAmount As Long) As Boolean
	' by calling this method, you delegate the task to the
	' "parent" class, an instance of which exists as the
	' m_Transaction object variable
	'
	' Any additional custom code could go below or above this
	' line -- in effect, this line is the same as VFP's DoDefault()
	Transaction_ModifyAccount = m_Transaction.ModifyAccount(strAccount, lngAmount)
End Function

[22:19] {MichaelSchwaid} Missed beginning - Delegation is a VB term (as in pattern)

[22:19] {VinMiller} It's not a VB term per se, but rather a design strategy. I see it used more in VB than in VFP.

[22:21] {VinMiller} Many VB programmers rely more on Delegation, I think, because there is no inheritance. But it can be used in VFP too. In fact, the more I work in VB, the more I end up, back in VFP, using delegation, and liking it.

[22:21] {VinMiller} So in the transfer object, we do not Implement the interface, but we still use helper objects and delegation, and as a result, we are still able to reuse code. An important point.

[22:22] {VinMiller} But Implements buys us some strong-typing/early-binding advantages, and enforces some rules for the developer.

[22:24] {VinMiller} We've covered an awful lot, and it may be time to begin wrapping up. The sample files can help demostrate some of the various techniques that I use to delegate to parent classes but they are probably best covered off-line. Feel free to email me any questions.

[22:25] {Evan Delay} Fantastic presentation Vin

[22:25] {VinMiller} Also, there are still other techniques for reuse that we haven't yet gotten to! Don't be thrown off by the Multicasting project -- we didn't get to that yet. Maybe that'll be the first followup.

[22:27] {VinMiller} By the way, I really encourage web searches on this stuff. There's some great sample code out there, and seeing how other people do this might really help.

[22:27] {MichaelSchwaid} Someone, how was delegation handled, calling parent's method? What keywrd should I look at for delegation?

[22:28] {VinMiller} I would search on "VB" "delegation" "Implements"

[22:28] {MichaelSchwaid} Is implements required for delegation?

[22:29] {VinMiller} Also, check out any VB books that list Delegation in the index. This can easily be done in the aisle of a Barnes and Noble rather than buying it!

[22:29] {TomAvery} My favorite personal library!

[22:29] {VinMiller} Michael -- no. Take a look above. Implements helps on some points, but is not required.

[22:30] {VinMiller} Posting on the VB side of UT is the best way. This way, everyone can learn!

[22:30] {DaveNaylor} Vin, which do you recommend - implements or delegation for a newbie VBer?

[22:31] {VinMiller} Try it out first without Implements. In fact, try it in VFP! You can do virtually everything I do with the Transaction, Transfer relationship right in VFP. That will give you a great start. A slight mindset-change, away from inheritance.

[22:32] {DaveNaylor} Haven't done much with inheritance so there is no mindset change for me :)

[22:32] {MichaelSchwaid} It looks like delegating is the process of creating implementation inheritance - if we use an interface aren't we forced to use delegation? What's the alternative?

[22:33] {VinMiller} Michael -- yes, if you want to inherit the parent's behavior.

[22:33] {MichaelSchwaid} You pointed out each method must be accounted for, is there an alternative? Thanks for the head start... back to the books!
Session Close: Wed Nov 29 22:33:47 2000


Contributors: Vin Miller, Evan Delay, Cindy Winegarden
Category Wednesday Night Lectures
( Topic last updated: 2000.12.04 10:18:01 AM )