wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

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:
  • 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 sprinkle your (web) forms with JavaScript calls. JavaScript belongs into JS files and referenced. Also a bad habit is to hard code the form to act on document.forms[0] will break sooner or later (when you add the custom tagging or the portal integration or or or)
  • 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.
  • While it is convenient rethink the use of the shorthand doc.[FieldName]. While it has (against common believe) no measurable impact on performance it has an impact on readability (if you see doc.something you need to think every time is this a property or a field name) and your ability to switch between languages since Java and JavaScript don't entertain this notion.
  • 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.
Some code templates we looked at:
 
%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
This LotusScript was converted to HTML using the ls2html routine,
provided by Julian Robichaux at nsftools.com.
... to be continued.

Posted by on 14 August 2009 | Comments (5) | categories: Show-N-Tell Thursday

Comments

  1. posted by Theo Heselmans on Sunday 16 August 2009 AD:
    We've all been doing this for years, haven't we Emoticon wink.gif
    Thanks for sharing, and reminding.
  2. posted by Thomas Bahn on Tuesday 18 August 2009 AD:
    Hi Stephan,

    I wouldn't do something like this:
    [...]
    Exit_someFunction:
    On Error Resume Next
    Exit Function

    Err_someFunction:
    Call LogError
    Resume Exit_someFunction
    End Function

    When an error has occured, the program is in an invalid state.

    Only if you check for specific errors, for which you know, you can log and otherwise ignore, it's okay to just jump out of the routine.

    Otherwise, you cannot know, how this error affects the rest of the program and the stored data and just leaving the procedure might create wrong results and inconsistent data.

    Please have a look at this presentation, Bernd Hort held at EntwicklerCamp 2009:
    { Link }

    This is error handling, not only error logging... Emoticon wink.gif
  3. posted by Stephan H. Wissel on Tuesday 18 August 2009 AD:
    @Thomas: Of course you are correct. Just jumping out of the routine mostly doesn't do the trick (unless it is an atomic operation like updating individual documents)... More on error handling will be in future posts on "code practices", I just got started. What I do is usually have a return status, so the calling function would know if things went wrong.
    Emoticon smile.gif stw
  4. posted by Thomas Bahn on Wednesday 19 August 2009 AD:
    @Stephan: I think, returning a status code isn't optimal. In fact, I think, it's a kind of misusing functions. Functions should return the result of some kind of calculation, data look-up and such. Procedures should "do" something. By making everything a function, you loose "semantics".

    There is a very good and proven way to react on errors: catch them, if you know, what you are doing, else let them bubble up. Every Java programmer writes his code this way.

    This way, you'd get the exception "out of the way" (normally at the end of the routine), your code gets cleaner.

    We had a student write his thesis about this matter, interested?

  5. posted by Jim Fricker on Monday 01 February 2010 AD:
    [quote]I think, returning a status code isn't optimal. In fact, I think, it's a kind of misusing functions.[/quote]

    Programming using exceptions is not a universally accepted approach...

    [url]www.joelonsoftware.com/items/2003/10/13.html[/url]

    Joel Spolsky (of joelonsoftware fame) prefers returning an error value.