[AccessD] Frameworks

John W. Colby jwcolby at ColbyConsulting.com
Fri Jun 23 20:41:09 CDT 2006


Michael,

>What was a 'framework', again?

A framework means different things to different people but I think of them
as a prewritten skeleton (and more) for an application.  If you think about
a building as a metaphor, what kinds of things do all buildings have in
common?  They all need electricity, plumbing, a phone system, elevators if
more than a single floor, heating and AC, etc.  These things, as well as the
load bearing skeleton are the "framework" of the building.  The rest is just
walls and windows.

Modern programs can use similar concepts.  I started using frameworks in the
late 80s with Borland's Turbo Pascal.  From there I learned about but never
really got into frameworks for VFP.  The seed was planted however and in
1997 I started developing my first framework for Microsoft Access.  It was
extremely crude and did not use classes.  The second version however did use
classes and withevents, thanks to Shamil's prodding me to learn them. 

My third generation (as I call it) framework is what I use in my new
projects and AFAICT it is probably unique in the breadth and scope of
functionality offered.  I initialize the framework with a single function
call.  The framework then provides me with numerous services such as:

Sysvars - (System Variables) both for controlling the initial state /
operation of the framework itself, but also for controlling the initial
state / operation of the application using the framework. In fact, system
variables are a key concept in my framework because they allow me to
dynamically control the operation of my framework as well as the
application.  System variables are often used by developers.  Most
developers need to store a "single value" such as (for example) their
company name and email in order to place it on the splash screen.  Since the
email address may change they might build a little one record table with two
fields - their company name and email address.  Then they later decide to
add their mail address so they go back in to design view and add a few more
fields, again though just a single record.  

Any database person will tell you that this is the wrong way to do this, we
need a table with a couple of fields, a variable name and a variable value
(at a minimum).

CompanyName		Colby Consulting
Email			jwcolby@
Addr			71 reder rd
Etc			etc.

These then are System Variables, and this is exactly the way that I do it.
What may be less obvious is that you can use these same system variables for
different purposes.  For example, suppose you wanted to use Just In Time
subforms in your projects.  You write code that allows the click event of a
tab to load a subform control with a form.  But do you ALWAYS use JIT?
Perhaps in your framework you default to NOT using JIT subforms and allow
the framework to be modified by using SysVars to control whether the default
is to use the JIT subforms.

So you create a SysVar table specifically for your framework.  Then you have
a SysVar named UseJITSubforms.  You set the default to false.  Now, when you
create a new project and you create subforms on tabs, the code that decides
whether to load the subforms at the main form's LOAD event or on the tab's
click event checks the SysVar UseJITSubforms.  If it is True, then the
subform will be loaded in the click event, else in the Main Form's Open
event.  Now, if you use JIT subforms, do you UNLOAD the subform when you
click off the tab with the form?  You can determine that with another SysVar
called JITSubformUnload.  Default to false and the subform stays loaded once
it is loaded, else it unloads when the user clicks on another tab.

So SysVars are one of the things that ALL of my applications use.  My main
framework class loads the sysvars for itself (the framework) as one of the
first things that it does (it also loads an Application SysVar table).  

Other services that my framework provides to my applications include:

* I can log to one file or a hundred.  My application simply calls the
framework and asks for a file logging class (with a name).  The framework
loads an instance of the logging class and stores a pointer in a collection
keyed on the provided name.  Now my application can simply call the
framework to log data to that file.  What data is logged is up to the
application, but the actual logging is up to the framework.
* Error logging 
* ZIP/Unzip 
* Email using MS Outlook 
* "LightWeight Security" allowing login / logout of users, then classes for
the users and groups that they belong to etc (not MDW based) which I use for
enabling / disabling forms and controls on forms. 
* Log date/time users open / close the FE. 
* Force logoff of the database (close the FE) at a given time. 
* Interclass messaging using a dedicated message class 
* Clipboard read/write 
* FTP read / write 
* MD5 Encryption

In addition to these "application" services, the framework provides me with
form and control classes which are wrappers to those Access objects, which
provides a host of additional functionality and the ability to "extend" the
functionality of a given object.  Examples include:

* Classes to automatically load and parse form Openargs and make the
openargs available to the form 
* Automatically scan for controls which have classes (wrappers) and load the
control classes 
* Just-In-Time subforms loaded as a tab page is clicked on in order to speed
up loading of complex forms. 
* Provide NotInList processing for combos 
* Open "list" forms (using the combo's dbl-click or notInListevent) and seek
to specific records for a selected data object in a given combo. 
* "Telling" objects what other objects (wrapper classes) are "dependent" on
that object such that if that object is edited, dependent objects are
automatically requeried / refreshed.  Combos / forms requery when some other
combo (or any data aware object) is modified / edited.  I can even do this
across forms, i.e. requery another open form when a value in a combo on this
form is selected. 
* Allow specific users or (more commonly) specific groups to override the
Visible, Enabled and Locked properties for any specific control so that
certain groups of users can see but not edit data in a control, others can
edit it, others can't even see it etc. 
* Prevent loading, or override the AllowEdit, AllowDelete, AllowAdd and
DataEntry properties for a given form based on group membership. 
* Allow OpenArgs to be passed in to an opening form which automatically sets
these and other properties of a form - makes a general purpose form
read-only to one group of users, editable to another, allows one group to
delete records but not others etc. 
* The ability to drill down to the field that a text box is bound to to
discover what data type it is, and apply consistent formatting across the
app (all dates in mm/dd/yyyy etc.). 
* Logging what forms are opened, by what users / workstations. 
I could (but never have) log what individual controls users visit (click in
/ edit) as they use a specific form.  This kind of stuff is trivial once you
have wrappers for controls and automatically load them as forms load.
Sysvars can turn on / off this kind of functionality, even down to a form by
form basis.

I have already done ALL of this stuff in my framework.  Most of it I wrote,
with the exception of public domain classes such as zip/unzip, FTP and
encryption classes/modules.  Having written it, all of this functionality is
available to me when I need it. 

Someone mentioned "lean and mean" programming, implying that having a
framework that "just does this stuff" for you causes your program to be
bloated and slow.  In fact that may or may not be an issue.  If your clients
are using old machines with sub ghz processors and 128 mb ram then it should
be a concern.  If your clients are using modern machines with lots of ram
then is it really a concern?  How big is Windows XP or 2003?  How big is
Office / Access XP / 2003?  My entire framework with all of this
functionality is currently 3.6 mbytes, and that includes the source code (it
is an MDA). How much overhead would it be if it loaded every single piece of
code in the framework?  Is that too much to ask for having all of the
Electricity, plumbing, AC/heat, elevators and such already in place with a
single function call to initialize it?

Not for me.  I use my framework on every project.  

Today I needed a form to open and pull openargs out.  I have a template form
with something like:

Dim mclsFrm as clsFrm

Sub MyFrm_Open()
	set mclsFrm = new clsFrm
	mclsfrm.Init [Param], [Param]
End sub

In fact, for many of my simple forms that is all that is in the form's
module.  My framework handles everything else.

So I copy my class template and rename it, then it was a single (additional)
call to the form class to load each openarg:

Sub MyFrm_Open()
	set mclsFrm = new clsFrm
	mclsfrm.Init [Param], [Param]
	MyVar1=mclsFrm.Openarg("MyArgName1")	
	MyVar2=mclsFrm.Openarg("MyArgName2")
End sub

Different strokes for different folks but I believe in writing things once
and using it forever.  That is what a framework is about.

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 Michael R Mattys
Sent: Friday, June 23, 2006 6:36 PM
To: Access Developers discussion and problem solving
Subject: Re: [AccessD] Frameworks

----- Original Message -----
From: "Colby, John" <JColby at dispec.com>

> Let me take another poll.  Of those of you who do not use a framework, 
> how many have read my ramblings and said
>
> 1) "I'd like to know more about this stuff".
> 2) "What a nut case"
> 3) "I sure wish he'd knock off the ravings"
>
> John W. Colby


What was a 'framework', again?

Michael R. Mattys
MapPoint & Access Developer
www.mattysconsulting.com 

--
AccessD mailing list
AccessD at databaseadvisors.com
http://databaseadvisors.com/mailman/listinfo/accessd
Website: http://www.databaseadvisors.com





More information about the AccessD mailing list