Microsoft Office 2000/Visual Basic Programmer's Guide |
There are many ways to write code that performs some valuable service. Options range from recording a macro that can replay a sequence of keystrokes and menu selections to creating a class module that provides a wrapper around complicated Windows application programming interface (API) functions. In the first example, you have application-specific code that provides a solution, but is not reusable. In the second example, you have created a reusable component that can perform its service from within any solution.
It is not difficult to write reusable code. If there are two ways to code something and one of them will result in a reusable procedure, create the reusable code. It is really a matter of how you approach the problem. If you understand how to create and use class modules, then you already know a great deal about how to approach writing reusable code. For more information about using class modules in Microsoft Office, see Chapter 9, "Custom Classes and Objects."
The first consideration when you are writing reusable code is to follow all the guidelines suggested in the previous sections of this chapter. In other words, write code that uses a consistent naming convention, is formatted properly, and contains useful comments.
Examine your existing code to make sure that your procedures have a single, specific purpose. Can you describe your procedures in a short, plain sentence? For example, "This procedure accepts an SQL string as an argument and returns a Recordset object containing the records described by the string." If you are unable to simply and clearly describe a procedure, it probably does too many things. Break down complicated procedures into smaller ones that do one thing each. Procedures should contain only code that clearly belongs together.
When you write new procedures, design them to perform a single operation.
Avoid making specific reference to named application objects. For example, the following code makes a specific reference to a combo box control and a text box control on an Access form:
strEmployeeName = Forms!frmEmployees!cboEmployeeName
strSQL = "SELECT * FROM Employees WHERE LastName = '" & _
Mid(strEmployeeName, InStr(strEmployeeName, " ") + 1) & "'"
Set rstAddresses = dbs.OpenRecordset(strSQL)
Forms!frmEmployees!txtHireDate = rstAddresses!HireDate
It would not be possible to reuse this code without substantially revising it. The procedure could be rewritten as a function that accepts a table name, a field name, and the record-selection criteria and returns the matching data. This procedure could be used in any solution that needed to retrieve a value from a field in a table:
Function GetDataFromField(strTableName As String, _
strFieldName As String, _
strCriteria As String) As Variant
' Returns a value from the field specified by strFieldName
' in the table specified by strTableName according to the
' criteria specified by strCriteria.
Dim rstFieldData As New ADODB.Recordset
Dim strSQL As String
On Error Resume Next
strSQL = "SELECT " & strFieldName & " FROM " & _
strTableName & " WHERE " & strCriteria
rstFieldData.Open strSQL, DATA_CONNECTSTRING & DATA_PATH
If Err = 0 Then
GetDataFromField = rstFieldData(strFieldName)
Else
GetDataFromField = ""
End If
End Function
The GetDataFromField procedure is available in the modGetAddressCode module in FormattingExamples.doc in the ODETools\V9\Samples\OPG\Samples\CH03 subfolder on the Office 2000 Developer CD-ROM.
In the previous code sample, you'll notice that two constants were used in place of the database connection string and database path in the ActiveX Data Object (ADO) Recordset object's Open method. This sample highlights another important consideration when you are writing reusable code: Never hard-code values used in your code. If a string or number is used repeatedly, define a module-level constant and use the constant in your code. If you need to use a string or number in more than one module, declare the constant by using the Public keyword. If you have a string or number that is local to a procedure, consider rewriting the procedure to pass the value as an argument or by using a local constant.
Always try to minimize the number of arguments in a procedure and pass in only what is actually needed by the procedure. In addition, make sure that your procedures use all the arguments passed to them.
Group related procedures and the constants they use together in the same module, and where appropriate, consider grouping related procedures together in a class module with a clearly defined interface.
Keep procedures in standard modules and not in modules behind forms or documents. The code in form modules should only be that code that is tied directly to the form itself and the code required for calling general procedures stored in standard modules.
Clearly distinguish between persisting data and communicating it between procedures. Communicate between procedures by passing data as arguments to the procedures. Persist data by writing it to disk or to the Windows registry. Don't use a procedure to write to a global variable so that some other procedure can read data from that global variable. Don't communicate with another procedure by passing data out of the application; for example, using one procedure to write data to a disk file, .ini file, or the registry so that some other procedure can read that data.
The same considerations that go into writing reusable code also apply to writing reusable script. The easiest way to reuse script is to group related procedures together in a scriptlet and then link the scriptlet to the HTML page in which you want to use the script. To see an example of an HTML page that links to reusable code in a scriptlet, copy ScriptGoodFormatting.htm and Scriptlet.htm from the ODETools\V9\Samples\OPG\Samples\CH03 subfolder on the Office 2000 Developer CD-ROM and open ScriptGoodFormatting.htm in your Web browser. To view the scriptlet code, open Scriptlet.htm in Windows Notepad. For more information about scriptlets, see Chapter 12, "Using Web Technologies."