|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。如果您注册时有任何问题请联系客服QQ: 83569622 。
您需要 登录 才可以下载或查看,没有帐号?注册
x
Technique #1: Declare Variables with the Proper Datatype
Variables declared improperly can slow execution time considerably, particularly if the affected code lines execute multiple times. Although the idea of proper variable declaration probably dates back to your first computer class, when you’re knee-deep in a programming project, it’s sometimes too easy to overlook basic rules for the sake of expediency.
Frequently, we set up simple timers to test different variations to find the fastest way to loop through a document collection. This technique is illustrated in Figure 1, which is executed from a Form Action and shows the value of declaring your variables using the proper data type. Of course, you may want to consider a more sophisticated method to test the execution times than using Timer(), and you may want to consider creating a function or subroutine in a script library, as we’ll discuss a little later.
In several tests, the undeclared variable in the first For loop took several seconds, whereas the declared variable in the second For loop took a fraction of a second. The first loop used the variable "i," which wasn’t previously declared and thus would be considered a variant for the life of the script. In the second loop, we declared the variable "j" as Long, producing significant savings in execution time. Even if your code doesn’t loop through anything a million times, this example effectively demonstrates the relative expense of not declaring your variables properly.
Technique #2: Use ColumnValues in NotesDocument
You can use the ColumnValues property of the NotesDocument class to access the values for the current document in the parent view. When you access the document via the view, this property returns an array of values representing each of the view’s columns. Obviously, if you want to use this property, you’ll need a column containing the item. The ability to access computed values in view columns is an additional advantage. Rather than doing calculations within a loop, which can slow execution time, you can do the calculation in a view column and then access the computed values using the ColumnValues property. Accessing the item or calculated value from the view using this property provides an efficient means to access values, versus accessing the item’s value directly by its name or performing a calculation within a loop.
We tested retrieving an item’s value from the field name on the underlying document (Figure 2) against using the Column Values property (Figure 3) while looping through approximately 10,000 documents in a view. The field ProductName was the second column in the view. We consistently found between 5 percent and 8 percent savings when using the ColumnValues as illustrated in Figure 3. Lotus Help indicates that this method of accessing the values in the underlying document can improve code efficiency by as much as 10 percent. This property returns no value if the document isn’t accessed through a view.
Technique #3: Use GetNextDocument and GetPrevDocument
Using GetNthDocument to walk through a document collection or view is simply not efficient. You should use GetNextDocument or GetPrevDocument instead. In testing the code in Figure 4, we found a dramatic decrease in performance using GetNthDocument. When run in an agent against a database with 3,800 documents, using GetNthDocument in a For. . .Next loop took 94 seconds, while using GetNextDocument in a While loop took just seven seconds. If you think the difference has something to do with the different types of loops used, think again. For... Next loops tested faster than While. . .Wend loops and Do Until . . .loops.
Technique #4: Use the Evaluate Function
You can use the Evaluate function to combine expressions written in the Formula Language with LotusScript. This is more efficient than using multiple lines of LotusScript. Frequently, a single @Function performs a task that would take five or more lines of LotusScript. You can use most @Functions except for those that interact with the Notes user interface (UI), such as @Prompt, @Picklist, @Dialogbox, and @Command. (Most of these @Functions have equivalent LotusScript commands anyway.)
For example, let’s say you want to calculate the average sales from a multivalued field named SalesHistory. Using LotusScript, you might try code such as that in Figure 5. That code could have been written using Evaluate in far fewer lines:
result = Evaluate("@Sum(SalesHistory)
/ @Elements(SalesHistory)", doc)
Msgbox "Average is: " & result(0)
There are many other useful @Functions that can replace multiple lines of LotusScript. For example, @Name lets you manipulate hierarchical names, and @Replace lets you change values within a list without requiring you to loop within the script. You can also use @DBLookup and @DBColumn functions in the Evaluate function. Bear in mind that including functions in scripts may make your code leaner and easier to write, but it won’t necessarily improve performance.
Technique #5: Use Global Variables
Malcolm was once asked to "fix" a database that a developer had written to handle a company expense form. Although there were many ways to do this, the developer chose to create about 300 fields on the form. A major requirement for the database was that the value in each field had to be selected when the user entered the field. In the original version, the Entering event for each of the 300 fields used the following code:
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Set uidoc = ws.CurrentDocument
uidoc.SelectAll
As users tab through the fields, this code achieves the desired effect of selecting the contents of the current field — but at the expense of performance. NotesUIWorkspace and NotesUIDocument had to be reinstantiated each time, causing a noticeable delay as the users tabbed from field to field. Malcolm’s solution was to create some global variables. The code was pulled out of each of the fields and placed in various locations. In the Form’s Global Declaration he used
Dim ws As NotesUIWorkspace
Dim uidoc As NotesUIDocument
In the form’s PostOpen event, he used
Set ws = New NotesUIWorkspace
Set uidoc = ws.CurrentDocument
In each field’s Entering event, he used
uidoc.SelectAll
The object variables "uidoc" and "ws" are now available to all fields and objects on the form except for the Entering event on the first field because it occurs before the PostOpen event for the form. The change made field tabbing smooth and delay- free. You could also extend this technique to include other object reference variables, such as NotesSession and Notes Database.
Technique #6: Use LotusScript in Form Events to Set Field Values
We’ve seen that using LotusScript in form events rather than in field events can improve performance. You can extend this technique to set field values with LotusScript in a form event rather than with conditional formulas that use @Functions such as @IsDocBeingSaved. As a rule, the back-end classes provide a quicker means to modify and update fields than front-end classes. Front-end classes are derived from the UI and provide access to a more limited object set than the back-end classes do. The back-end classes of the Object Model represent the stored value of the object and are more robust than the front-end classes. With the back-end classes, you can also use the extended class syntax for items on the document and manipulate Computed when composed fields.
Technique #7: Use the With Keyword
To make your code easier to read, we encourage you to use the With statement. Often, when developers use code to create new documents or populate the document items being sent as part of a workflow application, they find that they repeat the reference made to a particular object many times. Using the "With" keyword streamlines script by referring to the object once and giving access to the methods and properties of an object simply by prefacing them with a period to represent the declared object name. You can nest With statements up to 16 levels deep.
The code in Figure 6 creates a document and sends a document link to the users listed in the DocRecipients field. You can write this in a Form Action to let users forward the open document to a predefined list of people.
Figure 7 shows the same code rewritten using the With keyword. Notice that we’ve included the With keyword for the mailDoc and for the rtItem object reference to show how nesting works.
Technique #8: Minimize Use of @DbColumn and @DbLookup in Forms
Generally, using the Formula Language @Functions results in code that executes faster than any other language available in Notes and Domino. (For some other options, see "Choosing a Language,") But under some circumstances, it’s better to replace the @Functions with equivalent LotusScript code. For example, if your form needs several lists derived from large numbers of documents, you might experience better performance using LotusScript rather than using @DbColumn or @DbLookup.
This is not to imply that LotusScript will be faster than @DbColumn or @DbLookup in all cases and that you should begin writing 20 lines of code for each lookup instead of a single @Function. In fact, because of the 64 K limit to the return value for these two @Functions and fast machines, it was virtually impossible to benchmark any improvement using LotusScript. The point here is that the performance improvement isn’t necessarily on a field-by-field basis. Performance can be significantly degraded when multiple lookups are on the same form. If you reach that point, you can investigate techniques involving LotusScript to replace the lookups, thereby improving Form display times.
Not all techniques worth mentioning produce an increase in performance, but they still deserve mentioning. These next four techniques are mainly good programming practices.
Technique #9: Avoid Setting the "Automatically Refresh Fields" Property for Forms
Setting the Form property "Automatically refresh fields" should be used sparingly, and with a great deal of caution, because this property will severely affect performance. Why? When you set it, every field is touched when any single field changes. It’s far better — and faster — to write LotusScript in the appropriate field or form events.
Technique #10: Include Error Traps in Code Where Appropriate
This technique won’t speed up your code execution, but it pays big dividends when you’re debugging your code and keeps users from wondering what cryptic error codes and messages mean. You can also trap errors and send them to an administrator based on their severity.
Technique #11: Use Functions or Subroutines for Repetitive Code
If you repeat blocks of related code, it’s better to create a function or subroutine — especially if you can reuse the code. This technique can also help keep your script from exceeding the 64 K limit in a single event. This is basic programming practice and will make your code easier to write and maintain. It may not provide faster code, but it still pays off in the long run. In addition, you’ll be building reusable code libraries that you can use with other applications.
Technique #12: Use Script Libraries for Reusable Code
This is really a corollary to Technique #11. If the subroutine or function you write is reusable, put it in a script library where all your scripts and programs can make use of it. For example, you may want to place code to benchmark the execution of critical pieces of code in a script library. Once there, you can call it from anywhere in the database. You can also use script libraries for standard-object variable naming and instantiating. Many of the Lotus templates incorporate this technique.
|
|