View Single Post
 
Old 06-01-2002, 04:04 PM
loquin's Avatar
loquin loquin is offline
Google Hound

Retired Moderator
* Guru *
 
Join Date: Nov 2001
Location: Arizona, USA
Posts: 12,400
Post Abracadabra. Alakazam!

A 'Magic Number' is a number (other than 0 or 1) that is used in your code. As a programmer, you should avoid their use. There are several reasons for not using magic numbers in your code. First, and probably foremost, is that using them will make your code harder to understand and more difficult to maintain and troubleshoot.

Consider the following example: You will be printing a report directly to the printer on 8.5 x 11 inch paper, and you want to ensure that there are half-inch margins on your report. You know that like the form units, the printer units are in Twips, which are scaled such that 1 inch = 1440 Twips. So, you write a subroutine to print the header of your report. The Sub will accept a Title line (String) a user name (String), a page number (Integer) and a label. (The label is used to provide font formatting for your report; it is not visible during runtime.)
Code:
Private Sub PrintHeader (strTitle as String, strUserName as String, _ intPageNumber as Integer, lblFormat as Label) ' This sub will print the header for the report. ' First, set the Printer Font Printer.Font = lblFormat.Font ' Set initial X and Y positions Printer.CurrentY = 0.5 * 1440 ' Inch Margin, in Twips Printer.CurrentX = 0.5 * 1440 Printer.Print strUserName; ' Set Title Position in the Middle of the page Printer.CurrentX = ((8.5 / 2 ) * 1440) – _ Printer.TextWidth(strTitle) / 2 Printer.Print strTitle; ' Now Set the position of the Page Number Printer.CurrentX = ((8.5 - 0.5) * 1440) – _ Printer.TextWidth(“Page “ & cStr(intPageNumber)) Printer.Print “Page “ & cStr(intPageNumber) End Sub
Looking at this subroutine, you can see that there are several magic numbers in it. First, there is the 0.5 inch margin, the Number of Twips per inch, and the paper width itself. This Sub will work just fine. But, only for the conditions that you have defined. If you change any of these conditions, you will have to go into the code and change them. In several locations, each. A better approach, in this instance, would be to add constants to your code, and refer to these constants in your Sub. This way, when you change the Margin, or you get a ream of A4 paper, you will only have to change the constant in one location. Take a look at the following changes:
Code:
Const sngMargin as Single = 0.5 ' Report Margin, in Inches Const intTwipsPerInch as Integer = 1440 ' Twips conversion constant Const sngPaperWidth as Single = 8.5 ' Width of Paper, in Inches Const sngTwipsMargin as Single = sngMargin * intTwipsPerInch Const sngPWidthTwips as single = sngPaperWidth * intTwipsPerInch Private Sub PrintHeader (strTitle as String, strUserName as String, _ intPageNumber as Integer, lblFormat as Label) ' This sub will print the header for the report. ' First, set the Printer Font Printer.Font = lblFormat.Font ' Set initial X and Y positions Printer.CurrentY = sngTwipsMargin Printer.CurrentX = sngTwipsMargin Printer.Print strUserName; ' Set Title Position in the Middle of the page Printer.CurrentX = (sngPWidthTwips – Printer.TextWidth(strTitle) / 2 Printer.Print strTitle; ' Now Set the position of the Page Number Printer.CurrentX = sngPWidthTwips – sngTwipsMargin - _ Printer.TextWidth(“Page “ & cStr(intPageNumber)) Printer.Print “Page “ & cStr(intPageNumber) End Sub
Now, if you need to change the margins or paper width, you only need to do so in ONE spot in the code. No muss, No fuss. And, although it's easy to spot all the locations in this simple example, it is still possible to miss one, or to mistype it. When the code gets larger, it just gets easier and easier to screw up and miss one. (And I speak from experience here... ) Note that when you when you add a constant, you only need to comment it well in just one location also. This approach will make your code both easier to read AND easier to maintain.

Also, look at the 4th and 5th constants: They are calculated constants, derived from the earlier constants.

Of course, the instance above is somewhat contrived. You can eliminate one of the dependencies, above, by removing all the references to the Paper Size (In Twips OR inches) and, instead, use the object property Printer.Width. The Printer.Width property contains the current printer width. It automatically changes if the printer is set to Landscape mode, or if you change the paper size. Also, in this case, you could combine the use of the title and the label into one parameter. I kept them separate for clarity.

In addition, please note the placement of the constants. They were placed outside the Sub. Since this tutorial is focused on the use of constants rather than the scope of constants and variables (a topic for a later tutorial,) I won't go into any real detail here, but the reasoning in this is to allow other subs or functions on this form to use these same constants as well.
__________________
Lou
"I have my standards. They may be low, but I have them!" ~ Bette Middler
"It's a book about a Spanish guy called Manual. You should read it." ~ Dilbert
"To understand recursion, you must first understand recursion." ~ unknown

Last edited by Squirm; 05-01-2003 at 07:36 AM.
Reply With Quote