[AccessD] Naming Conventions

JWColby jwcolby at colbyconsulting.com
Thu Mar 15 13:18:23 CDT 2007


>..I am currently learning about classes from the information on your
website :-)

Uh oh.

;-)

Welcome to the next level of programming.  Classes really solve a host of
"container" problems that simply can't be done any other way.

Back in about 2000, before Shamil opened my eyes to classes (and withevents)
I used collections and collections of collections to hold objects.  It
worked but was sooooooo clumsy.  Now I start with a base class (or sometimes
a module) and that class holds collections which hold class instances.  

For example as everyone knows by now I have a framework.  One of the base
units of the framework is a dclsFrm which wraps the form object.  BTW, in
THIS CASE, the d is not a type prefix at all, it an homage to Shamil who
called his Withevent programming "DEEP" programming.  So a dclsXXXX is a
class which will sink (and possibly source) events inside the class.  IOW it
is a DEEP class.  Just a way of paying my respects to Shamil.  Sinking and
sourcing events in classes is so incredibly powerful that I simply can't
imagine not doing so now.

So I have a dclsFrm class which is dimensioned in the form's
"code-behind-form's" class module header and initialized in the OnOpen of
the form.  The form passes in a reference to itself to the dclsFrm that it
just instantiated.  The dclsFrm then sets the pointer passed in ("its" form)
into a module level global at the top of the class, declared WithEvents.
Declaring the form variable WithEvents tells VB that this class expects to
sink events from the form.  I then create event sinks for all of the form's
events.

One of the KEY constructs of dclsFrm is a control scanner which is called
from the Init().  That scanner looks for every single control on the form
(iterates the controls() collection of the form).  Each time it finds a
control, a huge case statement asks "what kind of control is this" and loads
a wrapper class for each control.  So my framework also has a dclsCbo,
dclsTxt, dclsCmd etc.  As the scanner finds a textbox, it instantiates a
dclsTxt and initializes it, passing in a pointer to that text box control.
Now that it has a dclsTxt for that text box, it needs a place to store the
class pointer.  For this I use a collection up in the dclsFrm's header.
Every control class wrapper gets stored in this collection, keyed on the
control's name.  Since the control name is always unique, the form itself
(or dclsFrm) can always look into this collection using the control's name
to find the wrapper class for that control.

I also have a few special purpose collections which hold specific types of
controls but the point here is that the dclsFrm can use collections to hold
entire collections of other classes.  In fact those "child" classes can also
have collections which store things.  For example I have a dctlTab which has
a collection which holds... dclsTabPage instances.  

Each class sinks the events of its "wrapped" control and implements generic
behaviors that I find so common that I want it always available.  

When you read this, the biggest thing to take away is that I did not write
all of this stuff in a week or even a month.  I add functionality to my
framework as I run into a need for it.  One day I decided that I really
needed some basic "form wrapper" functionality.  I found myself writing a
TON of similar code in every form - stuff to find specific records etc.
What better place to put it than in a class which wraps the form and
provides that functionality to ANY form that wants that kind of
functionality.  Dimension my dclsFrm, initialize it and voila, all of that
code is now "locked and loaded", ready to be used by the form, in fact it
can happen completely automatically in many cases.

One day I decided that it would be nice to have my combo's just
automatically handle NotInList (and dbl-click) events and either open a form
for adding / editing the table behind the form (dbl-click), or for simple
tables, just add a new entry when the user typed in something not already in
the list (NotInList).  Sure, I could dbl click each and every combo's
NotInList property and call a function that does that but why?  A combo
wrapper class can do all that for me.  Now that I have a combo wrapper class
(dclsCbo) how do I get it to load automatically?  Hmmm... My dclsFrm needs a
control scanner...  

Now my dclsFrm loads an instance of dclsCbo for every combo.  Hmmm... How
about my text boxes?  I want the text boxes to change background color as it
gets the focus and revert back to the old color when it loses the focus.
Easy in a dclsTxt.  Sink the OnEnter and OnExit of the text box and cause it
to change the background color.  Hmm... Now go back to my dclsCbo and make
it do the same thing...  Edit my control scanner in dclsFrm to load the text
box classes.  Hmmm... I want the combo control to change the label back
color if it handles the NotInList so that there is a visual cue to the user
to expect this.  Have the dclsCbo grab a pointer to its label and then set
the label's back color as the combo initializes IF it is going to handle the
not-in-list.

And over time you can build up a really nifty framework that just automates
all of that lowly programming stuff that you used to have to do manually.
Load dclsFrm, it loads all the dclsXXX control wrappers, they handle the
details.  Just that easy!  I can literally have about 20-30 lines of code in
a form (in the OnOpen) and have it doing all kinds of stuff that I want it
to do.  It would look like magic to the non class programmer but it is just
plain old programming, just tied to events in the object wrapper class
instead of in each form.

How would you like to be able to apply a uniform format to dates in all
forms, and be able to change them by changing a record in a table?  If you
use bound forms and wrapper classes it is almost trivial.  The form's
recordset clone can be manipulated as a dao.recordset object.  Each control
is bound to a specific field and thus "knows" it's field name in the
recordset.  So any control can get the properties collection for its field
from the dclsFrm (its parent), find out what the data type is, and if the
data type is a date, apply a specific date format to it.  If you use my
SysVars method, you load the date format as a sysvar (a record in a table)
and the control simply looks up the required date format in the SysVar
class.  All done by the dclsTxt class as it loads, automatically (to the
application) because the dclsFrm has a control scanner in it.

Now imagine trying to do this kind of stuff without classes.  It ain't easy
and it ain't fun, and in fact it is so hard you just don't do it.  With
classes / WithEvents it is easier and lots of fun.

John W. Colby
Colby Consulting
www.ColbyConsulting.com

-----Original Message-----
From: accessd-bounces at databaseadvisors.com
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Barbara Ryan
Sent: Thursday, March 15, 2007 12:10 PM
To: Access Developers discussion and problem solving
Subject: Re: [AccessD] Naming Conventions

Thanks for all the info.  I have always used the "standard" tags and
prefixes (i.e., "tbl", "frm", cbo, etc.) but figured it was time to become
more descriptive!

John C. --- thanks for your explanation of prefixes....I am currently
learning about classes from the information on your website :-)

Thanks!
Barb Ryan




More information about the AccessD mailing list