'Making Reuse Fun' instead of 'Making Fun of Reuse' : Page 3

OK, so the COM team enabled us to develop great binary reusable components in DLLs and OCXs. Using all this functionality you develop this amazing component and now you're waiting for the developers to snap it up and start raving. You discover, however, that having a component that can be reused does not guarantee that it will in fact be reused. Amazing capabilities are overshadowed by ease of use and other trivial issues.

WEBINAR:

On-Demand

Easy Access to the System Class
When using Client from within another project in Visual Basic,
Intellisense helps to create and set the properties in your system class.
It is also easy to maintain the state for the duration of the application as
explained above. When using Client from an ASP application, this
becomes slightly more problematic. Firstly, depending on the amount of
hits you expect, it may or may not be a good idea to maintain an instance of
ClientCO.clsSystem for the duration of the session. Let's assume you
want to keep your connection information in an Application Variable on IIS.
This works quite well, as you only need to fetch the connection information once
at application startup. Using the functionality provided by clsSystem,
it is relatively easy as well, as you only need to instantiate an instance of
clsSystem and copy the content of the ConnectionString property into
an application variable. (Note that there are some limitations on the kind
of repository you can use, but more about that later)

When writing your ASP page, you need to instantiate an instance of
ClientCO.clsSystem in order to set the connection string property, then you
need to instantiate ClientCO.clsClient to load and work with your
Client object. While this may sound pretty straightforward, using
"CreateObject"
and having to create two classes in order to work with only one does get
silly after a while, especially if you want to use four different components and
now have to instantiate four system classes as well. This prompted a change to
classes such as clsClient that
proved to be very useful for much more than just ASP development. Every
class in my CO project (except for clsSystem) gets a modular instance of
clsSystem which is exposed as the property System, and loads
itself on first reference. This means that I add the following code to
ClientCO.clsClient

Private mobjSystem as ClientCO.clsSystem

Public Property Get System() as ClientCO.clsSystem
If mobjSystem Is Nothing Then Set mobjSystem = New ClientCO.clsSystem
Set System = mobjSystem
End Property

In my ASP application I can now instantiate only an instance of clsClient,
set the connectionstring and start using the functionality of clsClient.
VBScript code for this would typically look as follows:

CO classes that needs access to information variables now also has easy OO
access to these variables.

The System Class on BO Level
True to the nature of our 3 Tier design, clsSystem has it's BO
counterpart called clsSystemSVR. On BO level private
modular variables is used to store configuration information. As is the case on CO
level, every object on BO level has a System property, which returns an
instance of clsSystemSVR. So, in a typical call from ClientCO to
ClientBO, the state of clsSystem is packed into XML and unpacked into
clsSystemSVR.
ClientBO uses the configuration information to connect to the database etc. A
typical call from CO to BO uses the system class as follows:

Note that the state of the system class is passed ByVal, as the BO level does
not change information in the system class. In some instances it is necessary
to update information in the system class from BO to CO level. Limit this
as far as possible, as ByRef parameters adds an additional network roundtrip every time
it is used.

On BO level no global variables are used, plus no functionality exists to
automatically fetch values as they are needed. When you use (or reuse) a
component on BO level, you must supply it with the necessary configuration
information. You have seen how the CO level supplies the BO level with
this info. An example of the BO supplying another BO level component is when
you
expose a class B as a
property of class A. In the following code snippet, clsContractClientSVR
exposes clsClientSVR as a property that will be loaded on first
reference:

Public Property Get Client () as
ClientBO.clsClientSVR

if mobjClient is Nothing Then
set mobjClient =
CreateObject("ClientBO.clsClientSVR")
Call mobjClient.System.Unpack (Me.System.Pack)
mobjClient.Load Me.ClientID
End If
Set Client = mobjClient

End Function

After creating an instance of mobjClient, the configuration information is
passed on to it using the XML pack and unpack functions. When the two
objects are in the same project however, it is a much better option to simply
execute

Set mobjClient.System = Me.System

A note on why I choose to pass all the configuration
information between BO and CO level with every call (and
taking up bandwidth), as opposed to maintaining it centrally on the BO
side:

The aim of the components is to be reusable, and I have
no guarantee as to which system is using it, or to which database they it
will be connecting. Most of our clients run these components from
multiple apps to
multiple databases while using one COM+ box, making a central store
difficult to maintain. Fetching this information on a call by call basis
on BO level also imposes an overhead on the BO classes, while the CO
classes can maintain state and thus only has to fetch this information
once. Passing this information into the SPM and managing it using
some kind of key per CO instance can be used as an alternative to the way
I use it.

Objects developed in VB lives inside a
Single Threaded Apartment (STA). Global variables are scoped at STA
level rather than process level, so they are available to all objects
sharing an STA. In a normal VB client application using DLLs, only one STA
normally exists, so synchronization of global etc. is easy to manage and
debug. On a COM+ box each server package process maintains a pool of
STA threads. COM+ matches objects with STA threads in an arbitrary
way, so you have no guarantee as to which clients will be sharing threads
and thus sharing globals. This means that you should approach
global variables on BO level with caution. As far as Read/Write
properties go, you cannot rely on a global variable to share data. For
Read/Write data that needs to be shared, use the Shared Property Manager
(SPM).

Advertiser Disclosure:
Some of the products that appear on this site are from companies from which QuinStreet receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. QuinStreet does not include all companies or all types of products available in the marketplace.

Thanks for your registration, follow us on our social networks to keep up-to-date