Writing Reusable Code

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

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 Microsoft® Windows® application programming interface (API) functions.

It is not difficult to write 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.

The first consideration when you are writing reusable code is writing code that uses a consistent naming convention, that is formatted properly, and that 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 describe a procedure simply and clearly, 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.

In the first of the following two examples, you have application-specific code that provides an application, but is not reusable. In the second example, you have created a reusable component that can perform its service from within any application.

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 a Microsoft® 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 the previous code without revising it substantially. However, 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. The following procedure could be used in any application that must 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

In the previous code sample, notice that two constants were used in place of the database connection string and database path in the Microsoft® ActiveX® Data Object (ADO) Recordset object's Open method. This sample highlights another important consideration when you are writing reusable code: Avoid hard-coding 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 must 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.

Try to minimize the number of arguments in a procedure and pass in only what is actually required by the procedure. In addition, make sure 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 be only that code that is tied directly to the form itself and the code required for calling general procedures stored in standard modules.

Communicate between procedures by passing data as arguments to the procedures. Persist data by writing it to disk or to the Windows registry. Avoid using a procedure to write to a global variable so another procedure can read data from that global variable. Avoid communicating 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 another 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.

See Also

Designing Code to Be Used Again | What Is Reusable Code? | Writing Reusable Code | Source Code Sharing | Custom Classes and Objects | Using Web Technologies