LotusScript Coding Style
I have currently the pleasure of introducing new developers to Lotus Domino. While it is old new to the Yellow Bubble our new members wonder about code style and code smell for LotusScript programming. Looking at a lot of the existing code base they rather get a wrong impression. So we went through a few guidelines. Of course sticking to them becomes a lot easier with the new LotusScript editor in 8.5.1:
This LotusScript was converted to HTML using the ls2html routine,
... to be continued.
provided by Julian Robichaux at nsftools.com.
- Every time you skip OPTION DECLARE an angel must die. So for the love of [insert-what-is-holy-to-you] configure your preferences to automatically insert it. I've submitted a request to parliament to cane serial DECLARE offenders <vbg>
- Keep them short. Functions that carry on over hundreds of lines are a maintenance nightmare. A function does one thing at a time. So the routine that loops through your document collection doesn't process the individual documents, but calls a function with the document as parameter
- Names need to have a meaning. So variables a, b, c are a bad idea. Same applies to sub1, sub2 etc. There are very few exceptions like s for the current session, db for the database, dc for the document collection, v for the view and doc for the document to work on. Read Joel's write-up on naming conventions.
- Decompose your applications well. If you think that is a process of biological decay, take a free Stanford University course in computer science
- Global variables are a lazy programmers sign post (of course no rule without exceptions)
- Call MsgBox(Err$) is not error handling. It is pure laziness. Use an error handling framework like Julian's OpenLog or Devin's enhanced log, both available on openNTF. Name your error handlers like the function: ON Error goto Err_[NameOfYourFunction]. Use a Exit_[NameOfYourFunction] label as common exit point and have your error handlers at the end of the function (see the code templates below)
- Comments don't hurt anyone. Missing comments do. Comment the WHY not the WHAT. Use lsDoc to extract your comments into your documentation
- While commonly associated with Java only know your Software Design Patterns. Know them well. Read a book. Also know your Anti-Pattern (like this one)
- Make good use of the LIST keyword. LIST are fast and can replace repeated lookups. A list can't contain a second list, but an object with a list as public property, which can contain object with a list as public property ... you get the idea.
- I like the factory pattern. While the factory implementation is not in line with the pure teachings it makes the code much more readable (see code below)
- Don't use document.all.[NameOfSomeButtonYouAddedHiddenly].click() to execute special functions. If you have back-end functions to call use a hidden field [NextAction] and a custom submit button (passthru HTML): <input type="submit" value="Do something special" name="NextAction"> The field NextAction will contain the value of the button. If you are smart you read the label from a config document, so you can change it without breaking your code.
- ViewEntries beat documents in speed any time. If you have to run through a long list of entries and only need to update a few, pack the criteria you need into view columns and run through the ViewEntries opening only the documents you need to change.
%REM Library ErrorhandlingDemo Created Aug 14, 2009 by Stephan H Wissel/Singapore/IBM Description: Demo Library to show common coding patterns %END REM Option Public Option Declare Use "OpenLogFunctions" %REM Function someFunction Description: A sample function doing nothing, shows errorhandling function %END REM Function someFunction On Error GoTo Err_someFunction Exit_someFunction : 'Cleanup code if needed somethink like 'finally in JAVA goes here: On Error Resume Next Exit Function Err_someFunction : Call LogError Resume Exit_someFunction End Function %REM Sub howWeDoLooping Description: Sample function take a NotesDocumentCollection as agument and loops over all document calling a worker function per document. Must abort if one document wasn't processed properly %END REM Sub howWeDoLooping (dc As NotesDocumentCollection ) Dim doc As NotesDocument Dim nextDoc As NotesDocument Set doc = dc .Getfirstdocument ( ) Do Until doc Is Nothing Set nextDoc = dc .Getnextdocument (doc ) 'IF you need to stop when one document fails use this If Not workOnThisDocument (doc ) Then Exit Do End If Set doc = nextDoc Loop End Sub %REM Function workOnThisDocument Description: Sample function to report failure or success as return value %END REM Function workOnThisDocument (doc As NotesDocument ) As Boolean On Error GoTo Err_workOnThisDocument Call LogEvent ( "Approval successful" ,SEVERITY_LOW ,doc ) 'If we got here everything worked workOnThisDocument = true Exit_workOnThisDocument : Exit Function Err_workOnThisDocument : Call LogErrorEx ( Error$ ,SEVERITY_HIGH ,doc ) workOnThisDocument = false Resume Exit_workOnThisDocument End Function
provided by Julian Robichaux at nsftools.com.