SlideShare una empresa de Scribd logo
1 de 72
Descargar para leer sin conexión
LotusScript Coding
Best Practices


Bill Buchan
HADSL
          © 2006 Wellesley Information Services. All rights reserved.
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            2
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            3
What is this About?

•   This talk aims to demonstrate LotusScript coding Best
    Practices, showing:
      Why Best Practices are useful
      How to save time and effort
•   Best Practices?
      Guidelines adopted by the marketplace to help increase
      quality
      General assumption about custom business code:
         It's developed for maintainability




                                                               4
Who am I?

•   Bill Buchan
      Dual PCLP in v3, v4, v5, v6, v7
      10+ years senior development consultancy for Enterprise
      customers
         Learn from my pain!
      5+ Years code auditing
      CEO of HADSL – developing Best Practice tools




                                                                5
Introduction to Best Practices:

•   The first rule of Best Practices is:
       There is no Best Practice!
•   Seriously
       Don’t use this as a prescriptive list!
       Examine each one and decide whether it makes sense in your
       current context
       Be open to new ideas all the time
•   Attitude is better than prescriptive coding
       No “Not invented here”
       Collaborative programming:
          Discuss ideas and approaches There will always be an
          improvement
       The Humble Programmer
       The Lazy Programmer
                                                                    6
How to Code

•   Architect well
      Get the data model right
•   Code for maintainability
      Code updates cost more than new code!
      Remember – the next person to maintain code might be you!
      Keep it simple. Over-architecting is bad, too!
•   Example:
      A Scottish Insurance Company: In the 60's, decided to only
      use two digits for dates, full in the knowledge that this would
      have to change in Y2k
      Assumed that the code would not last 40 years
      The manager who made that decision was yanked back from
      retirement to be the Y2K manager
      It rarely works out this well
                                                                        7
How to Test

•   Test soon, test often, test completely
      Look at test-driven development
         Write the specification
         Write the structure
         Write the tests
         Write the code
      Automatic testing means:
         Far easier to regression test all the time
      Minimise run-time errors by:
         Always assuming that data operations outside the current
         database may fail
         Trapping all run-time errors and providing an execution
         path that fails safely

                                                                    8
How to Test (cont.)

•   Why test early ?
      Costs rise as the tests fail further away from development
      Cheapest to most expensive are:
         Unit tests – by the developer
         User acceptance tests (UAT) – by the tester
         End-user failure – by the user
      The more tests you perform in unit testing:
         The cheaper your development will be
         The more professional your colleagues will think you are
         The more your boss will like you



                                                                    9
Where to Test

•   Developers should work in a development environment
•   User acceptance testing (UAT) should occur in a test
    environment
•   Administrators should deploy templates
         Developer        manager        Dev
                          Edito
                               r
                           us
                             er         UAT

                               er
                          manag
       Administrator      manager         Production



                                                           10
Where to Test (cont.)

•   Why?
      It's a basic change control environment
      You insulate developers from the production environment
      No changing applications on the production environment
•   Does this create more work?
      Yes. The Administrator now has to deploy templates
•   Does this help testing?
      Absolutely. It shakes out any hard-coded errors
        These account for 15%-20% of all errors!
•   Does this help developers?
      Yes. It means that someone else tests the application before
      it's promoted to production
•   Does this save money?
      Yes. It increases testing in non-user facing areas
                                                                     11
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            12
Structure – Code Structure

•   Try to structure code so that it is composed of short
    logic functions
      This encourages re-use
      Shorter code is far easier to maintain.
      Do not put 1,600 lines of code in a single function!
•   Advanced Best Practices: use “Classes”
      This binds a data structure and the code associated with the
      data in one place
      Can extend this code structure to increase functionality
      Encourages code re-use



                                                                     13
Structure – Code Structure (cont.)

•   Try to avoid building functions and subs with lots of
    parameters
       An example of tight binding
       Brittle
       Always changing
       You might find that two or three functions are more
       appropriate
       Try passing a type or class instead
•   Few parameters
       More re-use
       Simpler
•   Hint:
       If you have to use “_” —the continuation character—in a
       function declaration, stop yourself and re-evaluate!
       If you always have to change functions, then re-evaluate!   14
Code Structure – Defensive Programming
                                                           Solution

•   Defensive Programming is:
       Assuming that the consumers (in most cases, you!) of your
       code will pass bad data
       Checking all dependencies before making changes
•   Example:
Function test(param1 as String, param2 as String) as integer
 Function test(param1 as String, param2 as String) as integer
   Test == false
    Test    false
   if param1=”” then exit function
    if param1=”” then exit function
   if param2=”” then exit function
    if param2=”” then exit function
    ... '' Do some work
     ...    Do some work
   Test == true
    Test    true
end function
 end function



                                                                   15
Code Structure – Defensive Programming (cont.)

•   Pros:
      Far more robust code
      Far better at dealing with and failing gracefully when things
      change
      Better at dealing with transactions
         All dependencies are checked before a transaction
         commit. Consistency is maintained
•   Cons:
      More code!
      Redundant code?
      Performance hit? Perhaps not. In our world, only a few
      operations actually take a long time:
             Opening a NotesView
             Opening a NotesDocument
                                                                      16
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            17
Variable Naming

•   Should I adopt a variable naming methodology?
      If it helps!
      For instance:
           docCurrent, viewDocuments, sSession indicates that this
           variable is a document, a view or a session
           However, it falls down because there are over 70 notes
           classes in v7!
      I tend to prefix:
           Strings with “str”
           Integers with “i”
           Variants with “v”
•   Do not use variable names that are not meaningful
      EG: “elephant”, “donut”, “apple”
        Unless you work in a zoo
                                                                     18
Variable Naming (cont.)

•   Variables that only exist for a short period of time
    should have short names:
       For example; Loop counters - “i”
       But only if they are easily viewable on a screen
•   Complex variables – such as NotesDocument, etc.
       Longer names – but less than 15-20 characters
       Make them “CamelCase” (humped)
          For example: docPersonOldDir, instead of
          DOCPERSONOLDDIR
•   Use UPPERCASE for 'Consts‘
       An old “C” habit where UPPERCASE indicated preprocessor
       variables
•   Beware the accidental “rude” variable name
       Especially in multi-lingual environments
                                                                 19
Variable Existence

•   A big part of “Code Complete” is:
       Variables only exist as long as they are useful
•   Within a large function, therefore:
       Don’t declare all variables at the top
       Declare the variables as you need them
       The goal is to have the meaningful parts of a sub-section of
       code visible in one screen
•   Why?
       This cuts down the time required to understand & debug
          A large part of debugging is looking at each variable and
          understanding where it's being changed and where it's
          being used. If it's all visible in one screen, this is far
          simpler.
       Which in turn cuts maintenance costs
                                                                       20
Variable Declarations

•   Always use Option Declare. Why?
      If you don't declare the variable in advance then it will default
      to a variant
      This gives you a 10x performance overhead as the variant is
      data-converted on each operation
      If you mistype the variable – easy to do – you end up with an
      implicit variable declaration – and two separate variables
•   Always put code in Script Libraries instead of forms and
    shared actions
      Because Option Declare is switched off for these
•   Remember:
      Declaring your variables in advance means that the
      LotusScript compiler is ensuring type correctness
      It's better to shake out syntax errors in unit testing than
      during user testing                                                 21
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            22
What to Put in Comments

•   Comments should be inserted into code to aid
    understanding
      Document the why, not the what
         Especially if you have to introduce a non-intuitive fix –
         such as an edge condition
      A competent programmer can read your code
      But don’t over-comment!
•   Author/Age/Last Change comments:
      Rarely get updated
      Mistrust them
•   Comments such as the following help no one
      “This should never get executed”
      “Here there be dragons”
                                                                     23
Meta Code in Comments

•    A good use of comments is to write meta-code
         For instance, when first writing a function, write the code-
         branches as a series of comments
         Leave them in once the code is complete


    Function test (param1 as String, param2 as String) as integer
     Function test (param1 as String, param2 as String) as integer
       ' check the parameters and bail out if incorrect.
        ' check the parameters and bail out if incorrect.
       ' Add Param 1 to param 2
        ' Add Param 1 to param 2
       ' Check it’s valid. If so – update...
        ' Check it’s valid. If so – update...
       ' Errorhandler
        ' Errorhandler
    end function
     end function




                                                                        24
Comments Tricks

•   Remember:
      Comments consume code-space in LotusScript
      There's a 64k – about 1,400 line – limit for each code-
      sequence
         This should not normally be an issue
         Classes, of course, are all declared in Declarations
         In terms of classes, you can “subclass” to break up large
         class declarations
•   Check out LotusScript Doc:
      http://www.lsdoc.org/
      It's a “JavaDoc for LotusScript”
      You can annotate code to make the comments clearer


                                                                     25
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            26
Introduction to Cut 'n' Paste Code

•   Code re-use is a good thing
      However it should be treated with caution
      The code should be examined to determine
          Whether it's complete
          Whether it's appropriate for this situation
          Whether it requires context
          Whether it's legal to use in this context
      If you don't understand it
          It will bite you later on
      Remember:
          You will be responsible for the application


                                                        27
How to use Cut 'n' Paste Code:

•   Try to isolate new complex functions in separate script
    libraries
      Aids debugging, isolation, etc.
      Try to understand the context of the function
      Isolate the impact of the function
•   With all those caveats in mind, check out:
      http://www.openNTF.org.
      http://www.keysolutions.com/NotesFAQ.
•   Remember:
      To leave in accreditations
      To thank the original developers
      To check back to see if there have been updates/fixes

                                                              28
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            29
Error Handling Introduction

•   An Error is thrown at run-time when:
      A resource is unavailable: database, server, memory
      File I/O breaks
      Etc., etc.
•   Execution stops at the point of error
•   Sets error information:
      Error$ - a textual description
      Err – a numeric error code
      Erl – the line number of the error
•   Jumps to the error handling routine
      If there is no error handling routine in the current code-
      sequence, jumps to calling function
      If top-level function has no error handler, then default error
      handling is used
                                                                       30
Error Handling Effects

•   If an error occurs in the middle of a critical sequence of
    updates, possibly some updates will happen, and some
    will not
       Serious data consistency errors
       Get all your validation done before committing transactions
       Perform all the transaction “commits” at the same time
          In our case, all the “saves”
       Defensive coding minimises this effect
       Do not use “on error goto next”
•   You must deal with errors


                                                                     31
How to Handle Errors

•   Two approaches:
      Error trap in almost every routine
         Very granular
         Lots of information
         Minimal chance of breaking transactions
         However, lots of code
      Error trap at the top
         Very simple
         Minimal code
         You will lose context – you might not be able to get valid
         data on how the error happened
         You might break transactions – and therefore compromise
         data integrity
•   I recommend:
      Error trap in most routines!
                                                                      32
Writing a Minimal Error Trapping Routine

•   If you are going to write error trapping in most routines:
       Keep it simple
       Keep it cut'n'paste friendly
•   This means that:
       It might be difficult obtaining the name of the function that the
       error occurred in
       Check out getThreadInfo() or lsi_info()




                                                                           33
Example Function with Error Trapping

Function test(param1 as String) as integer
 Function test(param1 as String) as integer
   Test == false
    Test    false
   on error goto errorhandler
    on error goto errorhandler
   '' do something here!
       do something here!
   Test == true
    Test    true
exitFunction:
 exitFunction:
   exit function
    exit function
errorhandler:
 errorhandler:
   call raiseError()
    call raiseError()
   resume exitfunction
    resume exitfunction
end function
 end function




                                              34
Example 'RaiseError()' Routine
Functiondoes not tell us the name of the
   This raiseError() as integer
•Function raiseError() as integer            calling function
   raiseError == false
    raiseError     false
       Remember. script library, etc.
       Nor which No error trapping here!
   '' Remember. No error trapping here!

   Print “Run time error: (“ && cstr(err) && __
    Print “Run time error: (“       cstr(err)
      “: ““ && Error$ && ““ at line: ““ && cstr(erl)
       “:       Error$       at line:       cstr(erl)


   raiseError == true
    raiseError    true
exit function
 exit function




                                                                35
Better 'RaiseError()' Routine
Functionnow tells us: as integer
   This raiseError()
•Function raiseError() as integer
   raiseError == false
    raiseError    false
      Which library
   Print “Run time error: (“ ++ cstr(err) && __
    Print “Run time error: (“       cstr(err)
      Which function
      “: ““ && Error$ && ““ at line: ““ && cstr(erl) && __
       “:       Error$       at line:       cstr(erl)
      “called from: ““ && getThreadInfo(11) && __
      Thein module: ““ && getThreadInfo(10)
           error text
       “called from:
      ““ in module:
                             getThreadInfo(11)
                           getThreadInfo(10)
   raiseError number
      The line
    raiseError == true
                   true
exit function
 exit function




                                                             36
Example: OpenLog

•    OpenLog is an OpenNtf Project:
         http://www.openntf.org
•    It provides a simple framework for collecting error
     logging
         To use in your database:
            Copy the Script libraries from the OpenLog database
            Update the code:
    Function test(param1 as String) as integer
     Function test(param1 as String) as integer
       Test = false
       on errorfalse errorhandler
        Test = goto
       'on error goto errorhandler
         ...
        ' ... true
       Test =
        Test = true
    exitFunction:
     exitFunction:
       exit function
        exit function
    errorhandler:
     errorhandler:
       call logError()
       resumelogError()
        call exitfunction
        resume exitfunction
    end function                                                  37
     end function
OpenNtf.org

•   Example Log output:




                          38
Other Logging

•   So far we have discussed logging run-time errors
      You may wish to log other levels of event. For instance:
         Verbose: All variables values plus
         Normal:       Code events plus
         Minimal: Errors
•   Why?
      You may wish to record non-error events
      You may wish to produce performance information
•   The OpenLog solution may not scale to this level
      It creates a new document for each error raised
      If you were to introduce verbose logging
          The log database would become huge              Solution
          You may see performance issues keeping up with logging 39
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            40
Functions and Subs: Introduction

•   A function or subroutine:
      Is a good way of decomposing problems
      Is a good way of packaging up a common solution
      Should carry as little context as possible to maximize re-use
          Always assume someone will cut'n'paste
      Try and minimise the number of calling parameters
      Decide what your error handling strategy will be
      Beware short Function/Sub names:
          You might “collide” with functions in newer versions of
          LotusScript in the future, e.g., ArraySplit
          Not a bad idea to prefix all functions or Subs with a name-
          space prefix such as “MyCompany_.”


                                                                        41
Functions and Subs: Overview

•   Functions return a value
      For very simple functions:
         It's fine that the return value is a value
         Make sure those values are consistent in your problem-
         space
      For more complex functions:
         It's best to return whether the function itself has worked
         properly
         Pass back return values via the calling parameters
•   Subs:
      Difficult to see how they can be useful in a defensive coding
      world
          How do you know they have worked ?

                                                                      42
Functions and Subs: Approach

•   Try to minimize the size of the function
      Consider splitting up anything over 100 lines
•   Don’t be afraid to create a low-level function and a
    number of higher-level exploitation functions
•   Code Hiding:
      Explicitly document your externally visible functions by
      prefixing them with Public
      Don't be afraid to hide helper functions in your script library
      by prefixing them with Private
•   If you find you are passing a lot of contextual
    information between functions, investigate types or
    classes to bundle information:
      You can then pass a single object between functions
      Simpler to add another item of data in future
      Consider wrapping the code into a class                           43
Functions and Subs: Approach (cont.)

•   Place all functions and subs into script libraries
       Better grouping of functions
       Easier to debug
       Easier to code – full syntax checking
          You don't get full syntax checking on form events or
          shared actions!
       Easier to reuse




                                                          GOTCHA!
                                                                    44
Functions and Subs: Tricks

•    Use Variants to “loosely bind” parameters
        Then you can pass in containers such as arrays or lists into
        the same function



    Function test(param as variant) as integer
     Function test(param as variant) as integer
       test == false
        test     false
       if (isContainer(param)) then
        if forall thisThing in Param
            (isContainer(param)) then
            forall thisThing in Param
              call test(thisThing)
           end call test(thisThing)
            end forall
                 forall
       else
        else
           Print “I've been passed: ““ ++ param
           test ==“I've been passed:
            Print true                     param
       end test
            if
        end if
                    true

    end function
     end function

                                                                       45
Functions and Subs: Tricks (cont.)

  •    Use Variants to “loosely bind” parameters
          To make the function more useful
    Function ListCollection(p as variant) as integer
     Function ListCollection(p as variant) as integer
       test == false
        test    false
       if (typeName(p) == “NOTESVIEW”) or __
        if (typeName(p)     “NOTESVIEW”) or
       (typeName(p) == “NOTESDOCUMENTCOLLECTION”) then
        (typeName(p) this collection into a number of
                        “NOTESDOCUMENTCOLLECTION”) then
          '' decompose this collection into a number of
              decompose
          '' single document calls to myself
          dimsingleas NotesDocument to myself
               doc asdocument calls
           dim doc     NotesDocument
Note      set doc == P.getFirstDocument
          whiledoc
           set (not P.getFirstDocument
           while (not doc is nothing)
                       doc is nothing)
              call listCollection(doc)
               call listCollection(doc)
              set doc == p.getNextDocument(doc)
          wendset doc     p.getNextDocument(doc)
       elsewend
        else We've been passed a single document.
          '' We've been passed a single document.
          '' Process it.
              Process it.
          Print “I have been passed doc: ““ ++ doc.Title(0)
          test ==“I have been passed doc:
           Print true                            doc.Title(0)
       end test
           if
        end if
                   true

      end function
       end function
                                                                46
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            47
Memory Structures: Introduction

•   Use memory structures to store collections of
    temporary information
      Design your data structure correctly and save effort
•   Arrays
      Store multiple values of the same type in an array
•   Lists
      Associate a terminal value with a lookup value
•   Types
      Bundle a number of different types of data into one structure
•   Classes
      Bundle a number of different types of data into one structure
      Associate the code for that structure

                                                                      48
Memory Structures: Arrays

  •   Arrays:
          Are non-ordered
             That is, they retain their insertion order, but are not sorted
             by value
          Can be of fixed or dynamic size Dim myFixedArray(1) as String
                                                Dim myFixedArray(1) as String
          Store any other variable type        myFixedArray(0) ==“First”
                                                myFixedArray(0) “First”
                                               myFixedArray(1) ==“Second”
  •   Example:                                  myFixedArray(1) “Second”
                                               Print myFixedarray(0)
                                                Print myFixedarray(0)
Dim myDynamicArray() as String                 Print myFixedarray(1)
redimmyDynamicArray() as String
 Dim myDynamicArray(0)
 redim myDynamicArray(0)
                                                Print myFixedarray(1)

myDynamicArray(0) ==“First”
 myDynamicArray(0) “First”
redim preserve myDynamicArray(ubound(myDynamicArray)+1)
 redim preserve myDynamicArray(ubound(myDynamicArray)+1)
myDynamicArray(ubound(myDynamicArray)) ==“Second”
 myDynamicArray(ubound(myDynamicArray)) “Second”
forall thatEntry in myDynamicArray
 forall thatEntryentry is: “+ thatEntry
                  in myDynamicArray
    Print “That entry is: “+ thatEntry
end forall “That
      Print
 end forall
                                                                                49
Memory Structures: Arrays (cont.)

•   By default, they count from zero
      Don't change this by using “option base”
      You can guarantee that someone will either:
         Cut'n'paste this code somewhere else
         Remove your “option base” directive!
•   Extending arrays is a relatively expensive operation:
      When building collections of more than 20 data items, don't
      extend the array item by item




                                                                    50
Memory Structures: Lists

•   Lists are:
        Non-ordered
           That is, the memory layout does not reflect   Tip
           their value or their index value
        Indexed by a unique lookup value
        Very fast & memory efficient
•   Example:
    Dim myList List as String
     Dim myList List as String
    MyList (1) ==“First”
     MyList (1) “First”
    MyList (2) ==“Second”
     MyList (2) “Second”
    forall listEntry in myList
     forall listEntrylistmyList “+ listEntry
        Print “This in entry is: “+ listEntry
    end forall “This list entry is:
         Print
     end forall

                                                               51
Memory Structures: Types

•   Types:
       Help bind together multiple values
•   Example:
    Type Customer
     Type Customer
       name as NotesName
         name as NotesName
       UNID as String
         UNID as String
       Department as String
         Department as String
    end type
     end type
    Dim newCustomer as Customer
     Dim newCustomer as Customer
    newCustomer.Name ==new NotesName(“Joe Bloggs/Acme”)
     newCustomer.Name new NotesName(“Joe Bloggs/Acme”)
    newCustomer.UNID ==doc.UniqueID
     newCustomer.UNID doc.UniqueID
    newCustomer.UNID ==doc.Department(0)
     newCustomer.UNID doc.Department(0)




                                                          52
Memory Structures: Types (cont.)

•   Pros:
      Binds data together
      Functions can then use this type as a parameter
      Makes the data structure easier to extend
      You can copy simple types
•   Cons:
      Functions which deal with this type have to understand the
      data associated with this type
         The functions are therefore tightly bound to this type
      More complex types – containing arrays or lists – cannot be
      automatically copied
         You have to write code for this


                                                                    53
Memory Structures: Classes
                                                     Solution

  •   Classes
         Bind data and code together
         May be extended from another class
         May contain (“Encapsulate”) other classes
  •   Example
Class Customer
 Class Customeras NotesName
    Public name as NotesName
     Public name
    Public UNID as String
     Public UNID as String
    Public Department as String
     Public Department as String
    Public Sub new(doc as NotesDocument)
      Public Sub new(doc NotesName(doc.name(0))
         me.Name ==new as NotesDocument)
          me.Name new NotesName(doc.name(0))
         me.UNID ==doc.UniqueID
          me.UNID doc.UniqueID
         me.UNID ==doc.Department(0)
          me.UNID doc.Department(0)
    end sub
end type sub
      end
 end type
Dim newCustomer as Customer(doc)
 Dim newCustomer as Customer(doc)
Print “My customer name is: “ “++newCustomer.Name
 Print “My customer name is:      newCustomer.Name
                                                                54
Memory Structures: Combinations

•   Combining Lists and Classes is particularly useful:
Dim CustomerList List as Customer
 Dim CustomerList List as Customer
dim doc as NotesDocument
 dim doc as NotesDocument
set doc ==vCustomers.getFirstDocument
 set doc vCustomers.getFirstDocument
while not doc is nothing
 while not doc is nothing
   dim C as new Customer(doc)
    dim C as new Customer(doc)
   set CustomerList(C.name) ==C
    set CustomerList(C.name) C
   set doc ==vCustomers.GetNextDocument(doc)
wendset doc vCustomers.GetNextDocument(doc)
 wend
forall thisCustomer in CustomerList
 forall thisCustomer in + thisCustomer.Name + “ is in Department: “ + _
    Print “Customer: “ “CustomerList
      Print “Customer: + thisCustomer.Name + “ is in Department: “ + _
          thisCustomer.Department
end forallthisCustomer.Department
 end forall




                                                                          55
Memory Structures: Encapsulation

  •   Classes can contain other classes:
Class Customers                                    Dim CL as new CustomerList
                                                    Dim CL as new CustomerList
 Class Customers                                   call CL.load(viewCustomers)
                                                    call CL.load(viewCustomers)
    Public CustomerList List as Customer           call CL.Print
                                                    call CL.Print
     Public CustomerList List as Customer
   Public function load(vCust as notesView) as integer
     Public functionNotesDocument
        dim doc as load(vCust as notesView) as integer
         dim doc as NotesDocument
        set doc ==vCust.getFirstDocument
         set doc vCust.getFirstDocument
        while not doc is nothing
         while not as new Customer(doc)
            dim C doc new Customer(doc)
              dim C as
                        is nothing
            set CustomerList(C.name) ==C
              set CustomerList(C.name) C
            set doc ==vCust.GetNextDocument(doc)
        wendset doc vCust.GetNextDocument(doc)
         wend
   end function
     end function
   Public Function Print as Integer
     Public Function Print as Integer
        forall thisCustomer in CustomerList
         forall “Customer: “ + thisCustomer.Name + “ is in Department: “ + _
         Print thisCustomer in thisCustomer.Name + “ is in Department: “ + _
           Print “Customer: “ +
                                 CustomerList
            thisCustomer.Department
              thisCustomer.Department
        end forall
         end forall
   end function
end classfunction
     end
 end class
                                                                                  56
Memory Structures: Classes: Implementation

•   Classes are all defined in
    the declarations section.
      Difficult to navigate
      and edit
      Keep classes small – 1000
      lines maximum
•   No Class Browser
      Check out
      http://www.teamstudio.co
      m for Craig Schumann's
      LotusScript Class
      Browser


                                             57
Memory Structures: Usage

•   Use these memory structures to:
      Build intermediate information in memory
      Cache intermediate results
•   Much more efficient to use memory than:
      Re-open Notes documents multiple times
•   Where would I use them ?
      Directory or data synchronization tools
      Reporting or analysis tooling
      Database content checking tools
      Complex data structure management



                                                 58
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            59
Performance: Introduction

•   I said “Architect for Maintainability”
       This is still true
       However, sometimes – especially on large data runs – you
       need to know how to perform better
       Don't prematurely optimize
•   Expensive operations:
       Opening a NotesView
       Opening large number of NotesDocuments
•   Cheap operations:
       Holding something in memory
•   Why ?
       CPU is now very very cheap
       Memory is now very cheap
       Disk I/O – whilst faster – is still thousands of times slower
       than accessing memory                                           60
Performance: Views

  •   Fast
        Use “NotesViewEntries” to parse data from existing view
        summary information
  •   Medium
        Use NotesViews to iterate through documents
        Use NotesDocumentCollections to iterate through documents
  •   Slow
        Looking up every single document
  •   Very slow
      Opening up every single document, and using “extended
      class syntax” to obtain data fields:
         Always use “GetItemValue” instead
             This will reduce incorrectly named fields
             You can get type conversion
GOTCHA!      doc.GetItemValue(“field”)(0) is faster than doc.Field(0)   61
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            62
Design Patterns: Introduction

•   Design patterns are:
      Generally accepted Best Practices for designing part of an
      application
      Prevalent in the Java world
      A good way of solving common problems
•   Design patterns are not:
      A replacement for actually designing the application!
      To be used prescriptively
         After all, if all of our job could be automatically performed,
         we would not be required!
•   We shall discuss:
      A common Notes design pattern
      An object oriented design pattern: Singleton                        63
Design Pattern: Notes Replication

•   Before Notes/Domino v6, scheduled agents were not
    allowed to open databases on other servers
      This led to catalog.nsf style designs, where:
         A single database was replicated to multiple servers
         A “run on all servers” agent collected data
         All the data was replicated to all servers
      This in turn leads to a huge replication overhead, pushing all
      that data back to all replicas
•   In v6.x, you can assign “Trusted Servers”
      Defined in the Server Document on the security Tab
      List all servers that this server is allowed connections from
      Agents can then open databases on other servers


                                                                       64
Trusted Servers vs Replication: Application

•   Architecturally, you may now:
      Have a single central database
      A single scheduled agent
      Now pushes and pulls data to and from remote servers
•   This changes the architecture of applications
      Reduces data replication
      Increases response rate – no longer waiting for replication
      schedules
      Depends on reliable network links




                                                                    65
Design Pattern: Singleton

•   The Singleton is:
       A method of ensuring that only one object of
       a particular type is created
       Also a very fine Scottish malt whiskey
          Do not mix these two up!
•   Particularly useful for:
       Configuration class objects
         An object that holds global configuration
         information about your application




                                                      66
Design Pattern: Singleton Implementation

  •   Create a class in a script library
          Let’s call it “ConfigurationClass”
          Let’s create it in script library “Class:ConfigurationClass”
          It contains all global setup information for an application
          It loads itself from a profile doc in the current database
          It is used by the application to get configuration variables
Class ConfigurationClass                           Use “class:ConfigurationClass”
 Class ConfigurationClass                           Use “class:ConfigurationClass”
    Public ConfigVar1 as String                    sub initialize()
     Public ConfigVar1 as String                    subdim C as new ConfigurationClass()
                                                         initialize()
                                                          dim C as new ConfigurationClass()
    Sub new ()                                          Print “Config is: “ + C.ConfigVar1
     Sub new ()
         dim sSession as new NotesSession
          dim sSession as new NotesSession
         dim dbThis as NotesDatabase               end sub “Config is: “ + C.ConfigVar1
                                                          Print
                                                    end sub
         set dbThis = as NotesDatabase
          dim dbThis sSession.CurrentDatabase
         dim docProfilesSession.CurrentDatabase
          set dbThis = as NotesDocument
         set docProfile = as NotesDocument
          dim docProfile dbThis.GetProfileDocument(“Configuration”)
          set docProfile = dbThis.GetProfileDocument(“Configuration”)
         ConfigVariable1 = docProfile.GetItemValue(“ConfigVariable1”)(0)
          ConfigVariable1 = docProfile.GetItemValue(“ConfigVariable1”)(0)
    end sub
end class sub
     end
 end class
                                                                                          67
Design Pattern: Singleton Implementation (cont.)

  •   The code so far does not load a singleton
          It loads a new copy every time it's called
  •   To make ConfigurationClass a singleton
          Create a global function called “GetConfiguration”
          Create a global variable called CurrentConfiguration
          Make the class “Private”          Use “class:ConfigurationClass”
                                             Use “class:ConfigurationClass”
                                                       sub initialize()
                                                        subdim C as ConfigurationClass()
                                                             initialize()
                                                            set C C as ConfigurationClass()
                                                              dim = getConfiguration
                                                              set C = getConfiguration
Private CurrentConfiguration as ConfigurationClass          Print “Config is: “ + C.ConfigVar1
 Private CurrentConfiguration as ConfigurationClass end sub “Config is: “ + C.ConfigVar1
                                                              Print
                                                        end sub
Public Function getConfiguration as ConfigurationClass
 Public Function getConfiguration as ConfigurationClass
     if CurrentConfiguration is nothing then
       if CurrentConfiguration is nothing then
           set CurrentConfiguration = new ConfigurationClass()
     end if set CurrentConfiguration = new ConfigurationClass()
       end if
     set getSingleton = CurrentConfiguration
       set getSingleton = CurrentConfiguration
end function
 end function
                                                                                             68
What We'll Cover

•   Introduction
•   Structure
•   Variables
•   Comments
•   Cut 'n' Paste Code
•   Error Handling
•   Functions and Subs
•   Memory Structures
•   Performance
•   Design Patterns
•   Summary and Questions
                            69
Resources

•   Code Complete 2
      Steve McConnell, Microsoft Press

•   http://www.openNtf.org
•   http://www.keysolutions.com/Notesfaq
•   http://www.notes.net
      For forum and for support database

•   My “Object Orientated LotusScript” Presentation



                                                      70
Key Points to Take Home

•   Best Practices
      Don't be too prescriptive – use them as guidelines
      Sometimes using Best Practices means more work
      Always be willing to learn new techniques
      Always be willing to discuss implementation with other
      parties – this will always pay off
      Always code for maintenance. It's the highest cost
      Make your code easy to deploy
         Your Administrators will be more forgiving
      You are not alone – use the on-line forums to investigate



                                                                  71
Your Turn!




                Questions?

             How to Contact Me:
                Bill Buchan
              Bill@hadsl.com
                                  72

Más contenido relacionado

La actualidad más candente

Domino Server Health - Monitoring and Managing
 Domino Server Health - Monitoring and Managing Domino Server Health - Monitoring and Managing
Domino Server Health - Monitoring and ManagingGabriella Davis
 
Configuring Domino To Be An Ldap Directory And To Use An Ldap Directory
Configuring Domino To Be An Ldap Directory And To Use An Ldap DirectoryConfiguring Domino To Be An Ldap Directory And To Use An Ldap Directory
Configuring Domino To Be An Ldap Directory And To Use An Ldap DirectoryEdson Oliveira
 
HTTP - The Other Face Of Domino
HTTP - The Other Face Of DominoHTTP - The Other Face Of Domino
HTTP - The Other Face Of DominoGabriella Davis
 
Engage2022 - Domino Admin Tips
Engage2022 - Domino Admin TipsEngage2022 - Domino Admin Tips
Engage2022 - Domino Admin TipsGabriella Davis
 
Group Replication in MySQL 8.0 ( A Walk Through )
Group Replication in MySQL 8.0 ( A Walk Through ) Group Replication in MySQL 8.0 ( A Walk Through )
Group Replication in MySQL 8.0 ( A Walk Through ) Mydbops
 
Ansible presentation
Ansible presentationAnsible presentation
Ansible presentationKumar Y
 
Microsoft Offical Course 20410C_03
Microsoft Offical Course 20410C_03Microsoft Offical Course 20410C_03
Microsoft Offical Course 20410C_03gameaxt
 
Alles, was Sie ueber HCL Notes 64-Bit Clients wissen muessen
Alles, was Sie ueber HCL Notes 64-Bit Clients wissen muessenAlles, was Sie ueber HCL Notes 64-Bit Clients wissen muessen
Alles, was Sie ueber HCL Notes 64-Bit Clients wissen muessenpanagenda
 
Using CloudStack With Clustered LVM
Using CloudStack With Clustered LVMUsing CloudStack With Clustered LVM
Using CloudStack With Clustered LVMMarcus L Sorensen
 
Introduction to Docker storage, volume and image
Introduction to Docker storage, volume and imageIntroduction to Docker storage, volume and image
Introduction to Docker storage, volume and imageejlp12
 
Comparison of existing cni plugins for kubernetes
Comparison of existing cni plugins for kubernetesComparison of existing cni plugins for kubernetes
Comparison of existing cni plugins for kubernetesAdam Hamsik
 
Introduction to Nginx
Introduction to NginxIntroduction to Nginx
Introduction to NginxKnoldus Inc.
 
June OpenNTF Webinar - Domino V12 Certification Manager
June OpenNTF Webinar - Domino V12 Certification ManagerJune OpenNTF Webinar - Domino V12 Certification Manager
June OpenNTF Webinar - Domino V12 Certification ManagerHoward Greenberg
 
L4-L7 Application Services with Avi Networks
L4-L7 Application Services with Avi NetworksL4-L7 Application Services with Avi Networks
L4-L7 Application Services with Avi NetworksAvi Networks
 
Speed up your XPages Application performance
Speed up your XPages Application performanceSpeed up your XPages Application performance
Speed up your XPages Application performanceMaarga Systems
 

La actualidad más candente (20)

Domino Server Health - Monitoring and Managing
 Domino Server Health - Monitoring and Managing Domino Server Health - Monitoring and Managing
Domino Server Health - Monitoring and Managing
 
Configuring Domino To Be An Ldap Directory And To Use An Ldap Directory
Configuring Domino To Be An Ldap Directory And To Use An Ldap DirectoryConfiguring Domino To Be An Ldap Directory And To Use An Ldap Directory
Configuring Domino To Be An Ldap Directory And To Use An Ldap Directory
 
HTTP - The Other Face Of Domino
HTTP - The Other Face Of DominoHTTP - The Other Face Of Domino
HTTP - The Other Face Of Domino
 
Engage2022 - Domino Admin Tips
Engage2022 - Domino Admin TipsEngage2022 - Domino Admin Tips
Engage2022 - Domino Admin Tips
 
Group Replication in MySQL 8.0 ( A Walk Through )
Group Replication in MySQL 8.0 ( A Walk Through ) Group Replication in MySQL 8.0 ( A Walk Through )
Group Replication in MySQL 8.0 ( A Walk Through )
 
Domino Adminblast
Domino AdminblastDomino Adminblast
Domino Adminblast
 
60 Admin Tips
60 Admin Tips60 Admin Tips
60 Admin Tips
 
Ansible presentation
Ansible presentationAnsible presentation
Ansible presentation
 
Query logging with proxysql
Query logging with proxysqlQuery logging with proxysql
Query logging with proxysql
 
Microsoft Offical Course 20410C_03
Microsoft Offical Course 20410C_03Microsoft Offical Course 20410C_03
Microsoft Offical Course 20410C_03
 
Alles, was Sie ueber HCL Notes 64-Bit Clients wissen muessen
Alles, was Sie ueber HCL Notes 64-Bit Clients wissen muessenAlles, was Sie ueber HCL Notes 64-Bit Clients wissen muessen
Alles, was Sie ueber HCL Notes 64-Bit Clients wissen muessen
 
Using CloudStack With Clustered LVM
Using CloudStack With Clustered LVMUsing CloudStack With Clustered LVM
Using CloudStack With Clustered LVM
 
Introduction to Docker storage, volume and image
Introduction to Docker storage, volume and imageIntroduction to Docker storage, volume and image
Introduction to Docker storage, volume and image
 
Comparison of existing cni plugins for kubernetes
Comparison of existing cni plugins for kubernetesComparison of existing cni plugins for kubernetes
Comparison of existing cni plugins for kubernetes
 
Introduction to Nginx
Introduction to NginxIntroduction to Nginx
Introduction to Nginx
 
Nginx
NginxNginx
Nginx
 
June OpenNTF Webinar - Domino V12 Certification Manager
June OpenNTF Webinar - Domino V12 Certification ManagerJune OpenNTF Webinar - Domino V12 Certification Manager
June OpenNTF Webinar - Domino V12 Certification Manager
 
L4-L7 Application Services with Avi Networks
L4-L7 Application Services with Avi NetworksL4-L7 Application Services with Avi Networks
L4-L7 Application Services with Avi Networks
 
Speed up your XPages Application performance
Speed up your XPages Application performanceSpeed up your XPages Application performance
Speed up your XPages Application performance
 
Spnego configuration
Spnego configurationSpnego configuration
Spnego configuration
 

Similar a The View - Lotusscript coding best practices

The View - 30 proven Lotuscript tips
The View - 30 proven Lotuscript tipsThe View - 30 proven Lotuscript tips
The View - 30 proven Lotuscript tipsBill Buchan
 
Dev buchan 30 proven tips
Dev buchan 30 proven tipsDev buchan 30 proven tips
Dev buchan 30 proven tipsBill Buchan
 
The View - The top 30 Development tips
The View - The top 30 Development tipsThe View - The top 30 Development tips
The View - The top 30 Development tipsBill Buchan
 
10 Reasons You MUST Consider Pattern-Aware Programming
10 Reasons You MUST Consider Pattern-Aware Programming10 Reasons You MUST Consider Pattern-Aware Programming
10 Reasons You MUST Consider Pattern-Aware ProgrammingPostSharp Technologies
 
Driving application development through behavior driven development
Driving application development through behavior driven developmentDriving application development through behavior driven development
Driving application development through behavior driven developmentEinar Ingebrigtsen
 
Topic production code
Topic production codeTopic production code
Topic production codeKavi Kumar
 
Improving The Quality of Existing Software
Improving The Quality of Existing SoftwareImproving The Quality of Existing Software
Improving The Quality of Existing SoftwareSteven Smith
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing SoftwareSteven Smith
 
How to test a Mainframe Application
How to test a Mainframe ApplicationHow to test a Mainframe Application
How to test a Mainframe ApplicationMichael Erichsen
 
Software development best practices & coding guidelines
Software development best practices & coding guidelinesSoftware development best practices & coding guidelines
Software development best practices & coding guidelinesAnkur Goyal
 
Software Quality via Unit Testing
Software Quality via Unit TestingSoftware Quality via Unit Testing
Software Quality via Unit TestingShaun Abram
 
Agile Methodologies And Extreme Programming
Agile Methodologies And Extreme ProgrammingAgile Methodologies And Extreme Programming
Agile Methodologies And Extreme ProgrammingUtkarsh Khare
 
Improving the Design of Existing Software
Improving the Design of Existing SoftwareImproving the Design of Existing Software
Improving the Design of Existing SoftwareSteven Smith
 
YAGNI Principle and Clean Code
YAGNI Principle and Clean CodeYAGNI Principle and Clean Code
YAGNI Principle and Clean CodeLuan Reffatti
 
Test-Driven Development Reference Card
Test-Driven Development Reference CardTest-Driven Development Reference Card
Test-Driven Development Reference CardSeapine Software
 
Agile Methodologies And Extreme Programming - Svetlin Nakov
Agile Methodologies And Extreme Programming - Svetlin NakovAgile Methodologies And Extreme Programming - Svetlin Nakov
Agile Methodologies And Extreme Programming - Svetlin NakovSvetlin Nakov
 
Integration strategies best practices- Mulesoft meetup April 2018
Integration strategies   best practices- Mulesoft meetup April 2018Integration strategies   best practices- Mulesoft meetup April 2018
Integration strategies best practices- Mulesoft meetup April 2018Rohan Rasane
 
Winning strategies in Test Automation
Winning strategies in Test AutomationWinning strategies in Test Automation
Winning strategies in Test AutomationXBOSoft
 

Similar a The View - Lotusscript coding best practices (20)

The View - 30 proven Lotuscript tips
The View - 30 proven Lotuscript tipsThe View - 30 proven Lotuscript tips
The View - 30 proven Lotuscript tips
 
Clean code
Clean codeClean code
Clean code
 
Dev buchan 30 proven tips
Dev buchan 30 proven tipsDev buchan 30 proven tips
Dev buchan 30 proven tips
 
The View - The top 30 Development tips
The View - The top 30 Development tipsThe View - The top 30 Development tips
The View - The top 30 Development tips
 
10 Reasons You MUST Consider Pattern-Aware Programming
10 Reasons You MUST Consider Pattern-Aware Programming10 Reasons You MUST Consider Pattern-Aware Programming
10 Reasons You MUST Consider Pattern-Aware Programming
 
Driving application development through behavior driven development
Driving application development through behavior driven developmentDriving application development through behavior driven development
Driving application development through behavior driven development
 
Topic production code
Topic production codeTopic production code
Topic production code
 
Improving The Quality of Existing Software
Improving The Quality of Existing SoftwareImproving The Quality of Existing Software
Improving The Quality of Existing Software
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing Software
 
How to test a Mainframe Application
How to test a Mainframe ApplicationHow to test a Mainframe Application
How to test a Mainframe Application
 
Software development best practices & coding guidelines
Software development best practices & coding guidelinesSoftware development best practices & coding guidelines
Software development best practices & coding guidelines
 
Software Quality via Unit Testing
Software Quality via Unit TestingSoftware Quality via Unit Testing
Software Quality via Unit Testing
 
Agile Methodologies And Extreme Programming
Agile Methodologies And Extreme ProgrammingAgile Methodologies And Extreme Programming
Agile Methodologies And Extreme Programming
 
Improving the Design of Existing Software
Improving the Design of Existing SoftwareImproving the Design of Existing Software
Improving the Design of Existing Software
 
YAGNI Principle and Clean Code
YAGNI Principle and Clean CodeYAGNI Principle and Clean Code
YAGNI Principle and Clean Code
 
Test-Driven Development Reference Card
Test-Driven Development Reference CardTest-Driven Development Reference Card
Test-Driven Development Reference Card
 
Agile Methodologies And Extreme Programming - Svetlin Nakov
Agile Methodologies And Extreme Programming - Svetlin NakovAgile Methodologies And Extreme Programming - Svetlin Nakov
Agile Methodologies And Extreme Programming - Svetlin Nakov
 
Agile
AgileAgile
Agile
 
Integration strategies best practices- Mulesoft meetup April 2018
Integration strategies   best practices- Mulesoft meetup April 2018Integration strategies   best practices- Mulesoft meetup April 2018
Integration strategies best practices- Mulesoft meetup April 2018
 
Winning strategies in Test Automation
Winning strategies in Test AutomationWinning strategies in Test Automation
Winning strategies in Test Automation
 

Más de Bill Buchan

Dummies guide to WISPS
Dummies guide to WISPSDummies guide to WISPS
Dummies guide to WISPSBill Buchan
 
WISP for Dummies
WISP for DummiesWISP for Dummies
WISP for DummiesBill Buchan
 
WISP Worst Practices
WISP Worst PracticesWISP Worst Practices
WISP Worst PracticesBill Buchan
 
Marykirk raft race presentation night 2014
Marykirk raft race presentation night 2014Marykirk raft race presentation night 2014
Marykirk raft race presentation night 2014Bill Buchan
 
Dev buchan best practices
Dev buchan best practicesDev buchan best practices
Dev buchan best practicesBill Buchan
 
Dev buchan leveraging
Dev buchan leveragingDev buchan leveraging
Dev buchan leveragingBill Buchan
 
Dev buchan leveraging the notes c api
Dev buchan leveraging the notes c apiDev buchan leveraging the notes c api
Dev buchan leveraging the notes c apiBill Buchan
 
Dev buchan everything you need to know about agent design
Dev buchan everything you need to know about agent designDev buchan everything you need to know about agent design
Dev buchan everything you need to know about agent designBill Buchan
 
Entwicker camp2007 calling-the-c-api-from-lotusscript
Entwicker camp2007 calling-the-c-api-from-lotusscriptEntwicker camp2007 calling-the-c-api-from-lotusscript
Entwicker camp2007 calling-the-c-api-from-lotusscriptBill Buchan
 
Entwicker camp2007 blackberry-workshop
Entwicker camp2007 blackberry-workshopEntwicker camp2007 blackberry-workshop
Entwicker camp2007 blackberry-workshopBill Buchan
 
Admin2012 buchan web_services-v101
Admin2012 buchan web_services-v101Admin2012 buchan web_services-v101
Admin2012 buchan web_services-v101Bill Buchan
 
Reporting on your domino environment v1
Reporting on your domino environment v1Reporting on your domino environment v1
Reporting on your domino environment v1Bill Buchan
 
12 Step Guide to Lotuscript
12 Step Guide to Lotuscript12 Step Guide to Lotuscript
12 Step Guide to LotuscriptBill Buchan
 
Everything you ever wanted to know about lotus script
Everything you ever wanted to know about lotus scriptEverything you ever wanted to know about lotus script
Everything you ever wanted to know about lotus scriptBill Buchan
 
Admin camp 2011-domino-sso-with-ad
Admin camp 2011-domino-sso-with-adAdmin camp 2011-domino-sso-with-ad
Admin camp 2011-domino-sso-with-adBill Buchan
 
Softsphere 08 web services bootcamp
Softsphere 08 web services bootcampSoftsphere 08 web services bootcamp
Softsphere 08 web services bootcampBill Buchan
 
Connections Lotusphere Worst Practices 2013
Connections Lotusphere Worst Practices 2013Connections Lotusphere Worst Practices 2013
Connections Lotusphere Worst Practices 2013Bill Buchan
 

Más de Bill Buchan (20)

Dummies guide to WISPS
Dummies guide to WISPSDummies guide to WISPS
Dummies guide to WISPS
 
WISP for Dummies
WISP for DummiesWISP for Dummies
WISP for Dummies
 
WISP Worst Practices
WISP Worst PracticesWISP Worst Practices
WISP Worst Practices
 
Marykirk raft race presentation night 2014
Marykirk raft race presentation night 2014Marykirk raft race presentation night 2014
Marykirk raft race presentation night 2014
 
Dev buchan best practices
Dev buchan best practicesDev buchan best practices
Dev buchan best practices
 
Dev buchan leveraging
Dev buchan leveragingDev buchan leveraging
Dev buchan leveraging
 
Dev buchan leveraging the notes c api
Dev buchan leveraging the notes c apiDev buchan leveraging the notes c api
Dev buchan leveraging the notes c api
 
Dev buchan everything you need to know about agent design
Dev buchan everything you need to know about agent designDev buchan everything you need to know about agent design
Dev buchan everything you need to know about agent design
 
Entwicker camp2007 calling-the-c-api-from-lotusscript
Entwicker camp2007 calling-the-c-api-from-lotusscriptEntwicker camp2007 calling-the-c-api-from-lotusscript
Entwicker camp2007 calling-the-c-api-from-lotusscript
 
Entwicker camp2007 blackberry-workshop
Entwicker camp2007 blackberry-workshopEntwicker camp2007 blackberry-workshop
Entwicker camp2007 blackberry-workshop
 
Bp301
Bp301Bp301
Bp301
 
Ad507
Ad507Ad507
Ad507
 
Ad505 dev blast
Ad505 dev blastAd505 dev blast
Ad505 dev blast
 
Admin2012 buchan web_services-v101
Admin2012 buchan web_services-v101Admin2012 buchan web_services-v101
Admin2012 buchan web_services-v101
 
Reporting on your domino environment v1
Reporting on your domino environment v1Reporting on your domino environment v1
Reporting on your domino environment v1
 
12 Step Guide to Lotuscript
12 Step Guide to Lotuscript12 Step Guide to Lotuscript
12 Step Guide to Lotuscript
 
Everything you ever wanted to know about lotus script
Everything you ever wanted to know about lotus scriptEverything you ever wanted to know about lotus script
Everything you ever wanted to know about lotus script
 
Admin camp 2011-domino-sso-with-ad
Admin camp 2011-domino-sso-with-adAdmin camp 2011-domino-sso-with-ad
Admin camp 2011-domino-sso-with-ad
 
Softsphere 08 web services bootcamp
Softsphere 08 web services bootcampSoftsphere 08 web services bootcamp
Softsphere 08 web services bootcamp
 
Connections Lotusphere Worst Practices 2013
Connections Lotusphere Worst Practices 2013Connections Lotusphere Worst Practices 2013
Connections Lotusphere Worst Practices 2013
 

The View - Lotusscript coding best practices

  • 1. LotusScript Coding Best Practices Bill Buchan HADSL © 2006 Wellesley Information Services. All rights reserved.
  • 2. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 2
  • 3. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 3
  • 4. What is this About? • This talk aims to demonstrate LotusScript coding Best Practices, showing: Why Best Practices are useful How to save time and effort • Best Practices? Guidelines adopted by the marketplace to help increase quality General assumption about custom business code: It's developed for maintainability 4
  • 5. Who am I? • Bill Buchan Dual PCLP in v3, v4, v5, v6, v7 10+ years senior development consultancy for Enterprise customers Learn from my pain! 5+ Years code auditing CEO of HADSL – developing Best Practice tools 5
  • 6. Introduction to Best Practices: • The first rule of Best Practices is: There is no Best Practice! • Seriously Don’t use this as a prescriptive list! Examine each one and decide whether it makes sense in your current context Be open to new ideas all the time • Attitude is better than prescriptive coding No “Not invented here” Collaborative programming: Discuss ideas and approaches There will always be an improvement The Humble Programmer The Lazy Programmer 6
  • 7. How to Code • Architect well Get the data model right • Code for maintainability Code updates cost more than new code! Remember – the next person to maintain code might be you! Keep it simple. Over-architecting is bad, too! • Example: A Scottish Insurance Company: In the 60's, decided to only use two digits for dates, full in the knowledge that this would have to change in Y2k Assumed that the code would not last 40 years The manager who made that decision was yanked back from retirement to be the Y2K manager It rarely works out this well 7
  • 8. How to Test • Test soon, test often, test completely Look at test-driven development Write the specification Write the structure Write the tests Write the code Automatic testing means: Far easier to regression test all the time Minimise run-time errors by: Always assuming that data operations outside the current database may fail Trapping all run-time errors and providing an execution path that fails safely 8
  • 9. How to Test (cont.) • Why test early ? Costs rise as the tests fail further away from development Cheapest to most expensive are: Unit tests – by the developer User acceptance tests (UAT) – by the tester End-user failure – by the user The more tests you perform in unit testing: The cheaper your development will be The more professional your colleagues will think you are The more your boss will like you 9
  • 10. Where to Test • Developers should work in a development environment • User acceptance testing (UAT) should occur in a test environment • Administrators should deploy templates Developer manager Dev Edito r us er UAT er manag Administrator manager Production 10
  • 11. Where to Test (cont.) • Why? It's a basic change control environment You insulate developers from the production environment No changing applications on the production environment • Does this create more work? Yes. The Administrator now has to deploy templates • Does this help testing? Absolutely. It shakes out any hard-coded errors These account for 15%-20% of all errors! • Does this help developers? Yes. It means that someone else tests the application before it's promoted to production • Does this save money? Yes. It increases testing in non-user facing areas 11
  • 12. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 12
  • 13. Structure – Code Structure • Try to structure code so that it is composed of short logic functions This encourages re-use Shorter code is far easier to maintain. Do not put 1,600 lines of code in a single function! • Advanced Best Practices: use “Classes” This binds a data structure and the code associated with the data in one place Can extend this code structure to increase functionality Encourages code re-use 13
  • 14. Structure – Code Structure (cont.) • Try to avoid building functions and subs with lots of parameters An example of tight binding Brittle Always changing You might find that two or three functions are more appropriate Try passing a type or class instead • Few parameters More re-use Simpler • Hint: If you have to use “_” —the continuation character—in a function declaration, stop yourself and re-evaluate! If you always have to change functions, then re-evaluate! 14
  • 15. Code Structure – Defensive Programming Solution • Defensive Programming is: Assuming that the consumers (in most cases, you!) of your code will pass bad data Checking all dependencies before making changes • Example: Function test(param1 as String, param2 as String) as integer Function test(param1 as String, param2 as String) as integer Test == false Test false if param1=”” then exit function if param1=”” then exit function if param2=”” then exit function if param2=”” then exit function ... '' Do some work ... Do some work Test == true Test true end function end function 15
  • 16. Code Structure – Defensive Programming (cont.) • Pros: Far more robust code Far better at dealing with and failing gracefully when things change Better at dealing with transactions All dependencies are checked before a transaction commit. Consistency is maintained • Cons: More code! Redundant code? Performance hit? Perhaps not. In our world, only a few operations actually take a long time: Opening a NotesView Opening a NotesDocument 16
  • 17. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 17
  • 18. Variable Naming • Should I adopt a variable naming methodology? If it helps! For instance: docCurrent, viewDocuments, sSession indicates that this variable is a document, a view or a session However, it falls down because there are over 70 notes classes in v7! I tend to prefix: Strings with “str” Integers with “i” Variants with “v” • Do not use variable names that are not meaningful EG: “elephant”, “donut”, “apple” Unless you work in a zoo 18
  • 19. Variable Naming (cont.) • Variables that only exist for a short period of time should have short names: For example; Loop counters - “i” But only if they are easily viewable on a screen • Complex variables – such as NotesDocument, etc. Longer names – but less than 15-20 characters Make them “CamelCase” (humped) For example: docPersonOldDir, instead of DOCPERSONOLDDIR • Use UPPERCASE for 'Consts‘ An old “C” habit where UPPERCASE indicated preprocessor variables • Beware the accidental “rude” variable name Especially in multi-lingual environments 19
  • 20. Variable Existence • A big part of “Code Complete” is: Variables only exist as long as they are useful • Within a large function, therefore: Don’t declare all variables at the top Declare the variables as you need them The goal is to have the meaningful parts of a sub-section of code visible in one screen • Why? This cuts down the time required to understand & debug A large part of debugging is looking at each variable and understanding where it's being changed and where it's being used. If it's all visible in one screen, this is far simpler. Which in turn cuts maintenance costs 20
  • 21. Variable Declarations • Always use Option Declare. Why? If you don't declare the variable in advance then it will default to a variant This gives you a 10x performance overhead as the variant is data-converted on each operation If you mistype the variable – easy to do – you end up with an implicit variable declaration – and two separate variables • Always put code in Script Libraries instead of forms and shared actions Because Option Declare is switched off for these • Remember: Declaring your variables in advance means that the LotusScript compiler is ensuring type correctness It's better to shake out syntax errors in unit testing than during user testing 21
  • 22. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 22
  • 23. What to Put in Comments • Comments should be inserted into code to aid understanding Document the why, not the what Especially if you have to introduce a non-intuitive fix – such as an edge condition A competent programmer can read your code But don’t over-comment! • Author/Age/Last Change comments: Rarely get updated Mistrust them • Comments such as the following help no one “This should never get executed” “Here there be dragons” 23
  • 24. Meta Code in Comments • A good use of comments is to write meta-code For instance, when first writing a function, write the code- branches as a series of comments Leave them in once the code is complete Function test (param1 as String, param2 as String) as integer Function test (param1 as String, param2 as String) as integer ' check the parameters and bail out if incorrect. ' check the parameters and bail out if incorrect. ' Add Param 1 to param 2 ' Add Param 1 to param 2 ' Check it’s valid. If so – update... ' Check it’s valid. If so – update... ' Errorhandler ' Errorhandler end function end function 24
  • 25. Comments Tricks • Remember: Comments consume code-space in LotusScript There's a 64k – about 1,400 line – limit for each code- sequence This should not normally be an issue Classes, of course, are all declared in Declarations In terms of classes, you can “subclass” to break up large class declarations • Check out LotusScript Doc: http://www.lsdoc.org/ It's a “JavaDoc for LotusScript” You can annotate code to make the comments clearer 25
  • 26. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 26
  • 27. Introduction to Cut 'n' Paste Code • Code re-use is a good thing However it should be treated with caution The code should be examined to determine Whether it's complete Whether it's appropriate for this situation Whether it requires context Whether it's legal to use in this context If you don't understand it It will bite you later on Remember: You will be responsible for the application 27
  • 28. How to use Cut 'n' Paste Code: • Try to isolate new complex functions in separate script libraries Aids debugging, isolation, etc. Try to understand the context of the function Isolate the impact of the function • With all those caveats in mind, check out: http://www.openNTF.org. http://www.keysolutions.com/NotesFAQ. • Remember: To leave in accreditations To thank the original developers To check back to see if there have been updates/fixes 28
  • 29. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 29
  • 30. Error Handling Introduction • An Error is thrown at run-time when: A resource is unavailable: database, server, memory File I/O breaks Etc., etc. • Execution stops at the point of error • Sets error information: Error$ - a textual description Err – a numeric error code Erl – the line number of the error • Jumps to the error handling routine If there is no error handling routine in the current code- sequence, jumps to calling function If top-level function has no error handler, then default error handling is used 30
  • 31. Error Handling Effects • If an error occurs in the middle of a critical sequence of updates, possibly some updates will happen, and some will not Serious data consistency errors Get all your validation done before committing transactions Perform all the transaction “commits” at the same time In our case, all the “saves” Defensive coding minimises this effect Do not use “on error goto next” • You must deal with errors 31
  • 32. How to Handle Errors • Two approaches: Error trap in almost every routine Very granular Lots of information Minimal chance of breaking transactions However, lots of code Error trap at the top Very simple Minimal code You will lose context – you might not be able to get valid data on how the error happened You might break transactions – and therefore compromise data integrity • I recommend: Error trap in most routines! 32
  • 33. Writing a Minimal Error Trapping Routine • If you are going to write error trapping in most routines: Keep it simple Keep it cut'n'paste friendly • This means that: It might be difficult obtaining the name of the function that the error occurred in Check out getThreadInfo() or lsi_info() 33
  • 34. Example Function with Error Trapping Function test(param1 as String) as integer Function test(param1 as String) as integer Test == false Test false on error goto errorhandler on error goto errorhandler '' do something here! do something here! Test == true Test true exitFunction: exitFunction: exit function exit function errorhandler: errorhandler: call raiseError() call raiseError() resume exitfunction resume exitfunction end function end function 34
  • 35. Example 'RaiseError()' Routine Functiondoes not tell us the name of the This raiseError() as integer •Function raiseError() as integer calling function raiseError == false raiseError false Remember. script library, etc. Nor which No error trapping here! '' Remember. No error trapping here! Print “Run time error: (“ && cstr(err) && __ Print “Run time error: (“ cstr(err) “: ““ && Error$ && ““ at line: ““ && cstr(erl) “: Error$ at line: cstr(erl) raiseError == true raiseError true exit function exit function 35
  • 36. Better 'RaiseError()' Routine Functionnow tells us: as integer This raiseError() •Function raiseError() as integer raiseError == false raiseError false Which library Print “Run time error: (“ ++ cstr(err) && __ Print “Run time error: (“ cstr(err) Which function “: ““ && Error$ && ““ at line: ““ && cstr(erl) && __ “: Error$ at line: cstr(erl) “called from: ““ && getThreadInfo(11) && __ Thein module: ““ && getThreadInfo(10) error text “called from: ““ in module: getThreadInfo(11) getThreadInfo(10) raiseError number The line raiseError == true true exit function exit function 36
  • 37. Example: OpenLog • OpenLog is an OpenNtf Project: http://www.openntf.org • It provides a simple framework for collecting error logging To use in your database: Copy the Script libraries from the OpenLog database Update the code: Function test(param1 as String) as integer Function test(param1 as String) as integer Test = false on errorfalse errorhandler Test = goto 'on error goto errorhandler ... ' ... true Test = Test = true exitFunction: exitFunction: exit function exit function errorhandler: errorhandler: call logError() resumelogError() call exitfunction resume exitfunction end function 37 end function
  • 38. OpenNtf.org • Example Log output: 38
  • 39. Other Logging • So far we have discussed logging run-time errors You may wish to log other levels of event. For instance: Verbose: All variables values plus Normal: Code events plus Minimal: Errors • Why? You may wish to record non-error events You may wish to produce performance information • The OpenLog solution may not scale to this level It creates a new document for each error raised If you were to introduce verbose logging The log database would become huge Solution You may see performance issues keeping up with logging 39
  • 40. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 40
  • 41. Functions and Subs: Introduction • A function or subroutine: Is a good way of decomposing problems Is a good way of packaging up a common solution Should carry as little context as possible to maximize re-use Always assume someone will cut'n'paste Try and minimise the number of calling parameters Decide what your error handling strategy will be Beware short Function/Sub names: You might “collide” with functions in newer versions of LotusScript in the future, e.g., ArraySplit Not a bad idea to prefix all functions or Subs with a name- space prefix such as “MyCompany_.” 41
  • 42. Functions and Subs: Overview • Functions return a value For very simple functions: It's fine that the return value is a value Make sure those values are consistent in your problem- space For more complex functions: It's best to return whether the function itself has worked properly Pass back return values via the calling parameters • Subs: Difficult to see how they can be useful in a defensive coding world How do you know they have worked ? 42
  • 43. Functions and Subs: Approach • Try to minimize the size of the function Consider splitting up anything over 100 lines • Don’t be afraid to create a low-level function and a number of higher-level exploitation functions • Code Hiding: Explicitly document your externally visible functions by prefixing them with Public Don't be afraid to hide helper functions in your script library by prefixing them with Private • If you find you are passing a lot of contextual information between functions, investigate types or classes to bundle information: You can then pass a single object between functions Simpler to add another item of data in future Consider wrapping the code into a class 43
  • 44. Functions and Subs: Approach (cont.) • Place all functions and subs into script libraries Better grouping of functions Easier to debug Easier to code – full syntax checking You don't get full syntax checking on form events or shared actions! Easier to reuse GOTCHA! 44
  • 45. Functions and Subs: Tricks • Use Variants to “loosely bind” parameters Then you can pass in containers such as arrays or lists into the same function Function test(param as variant) as integer Function test(param as variant) as integer test == false test false if (isContainer(param)) then if forall thisThing in Param (isContainer(param)) then forall thisThing in Param call test(thisThing) end call test(thisThing) end forall forall else else Print “I've been passed: ““ ++ param test ==“I've been passed: Print true param end test if end if true end function end function 45
  • 46. Functions and Subs: Tricks (cont.) • Use Variants to “loosely bind” parameters To make the function more useful Function ListCollection(p as variant) as integer Function ListCollection(p as variant) as integer test == false test false if (typeName(p) == “NOTESVIEW”) or __ if (typeName(p) “NOTESVIEW”) or (typeName(p) == “NOTESDOCUMENTCOLLECTION”) then (typeName(p) this collection into a number of “NOTESDOCUMENTCOLLECTION”) then '' decompose this collection into a number of decompose '' single document calls to myself dimsingleas NotesDocument to myself doc asdocument calls dim doc NotesDocument Note set doc == P.getFirstDocument whiledoc set (not P.getFirstDocument while (not doc is nothing) doc is nothing) call listCollection(doc) call listCollection(doc) set doc == p.getNextDocument(doc) wendset doc p.getNextDocument(doc) elsewend else We've been passed a single document. '' We've been passed a single document. '' Process it. Process it. Print “I have been passed doc: ““ ++ doc.Title(0) test ==“I have been passed doc: Print true doc.Title(0) end test if end if true end function end function 46
  • 47. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 47
  • 48. Memory Structures: Introduction • Use memory structures to store collections of temporary information Design your data structure correctly and save effort • Arrays Store multiple values of the same type in an array • Lists Associate a terminal value with a lookup value • Types Bundle a number of different types of data into one structure • Classes Bundle a number of different types of data into one structure Associate the code for that structure 48
  • 49. Memory Structures: Arrays • Arrays: Are non-ordered That is, they retain their insertion order, but are not sorted by value Can be of fixed or dynamic size Dim myFixedArray(1) as String Dim myFixedArray(1) as String Store any other variable type myFixedArray(0) ==“First” myFixedArray(0) “First” myFixedArray(1) ==“Second” • Example: myFixedArray(1) “Second” Print myFixedarray(0) Print myFixedarray(0) Dim myDynamicArray() as String Print myFixedarray(1) redimmyDynamicArray() as String Dim myDynamicArray(0) redim myDynamicArray(0) Print myFixedarray(1) myDynamicArray(0) ==“First” myDynamicArray(0) “First” redim preserve myDynamicArray(ubound(myDynamicArray)+1) redim preserve myDynamicArray(ubound(myDynamicArray)+1) myDynamicArray(ubound(myDynamicArray)) ==“Second” myDynamicArray(ubound(myDynamicArray)) “Second” forall thatEntry in myDynamicArray forall thatEntryentry is: “+ thatEntry in myDynamicArray Print “That entry is: “+ thatEntry end forall “That Print end forall 49
  • 50. Memory Structures: Arrays (cont.) • By default, they count from zero Don't change this by using “option base” You can guarantee that someone will either: Cut'n'paste this code somewhere else Remove your “option base” directive! • Extending arrays is a relatively expensive operation: When building collections of more than 20 data items, don't extend the array item by item 50
  • 51. Memory Structures: Lists • Lists are: Non-ordered That is, the memory layout does not reflect Tip their value or their index value Indexed by a unique lookup value Very fast & memory efficient • Example: Dim myList List as String Dim myList List as String MyList (1) ==“First” MyList (1) “First” MyList (2) ==“Second” MyList (2) “Second” forall listEntry in myList forall listEntrylistmyList “+ listEntry Print “This in entry is: “+ listEntry end forall “This list entry is: Print end forall 51
  • 52. Memory Structures: Types • Types: Help bind together multiple values • Example: Type Customer Type Customer name as NotesName name as NotesName UNID as String UNID as String Department as String Department as String end type end type Dim newCustomer as Customer Dim newCustomer as Customer newCustomer.Name ==new NotesName(“Joe Bloggs/Acme”) newCustomer.Name new NotesName(“Joe Bloggs/Acme”) newCustomer.UNID ==doc.UniqueID newCustomer.UNID doc.UniqueID newCustomer.UNID ==doc.Department(0) newCustomer.UNID doc.Department(0) 52
  • 53. Memory Structures: Types (cont.) • Pros: Binds data together Functions can then use this type as a parameter Makes the data structure easier to extend You can copy simple types • Cons: Functions which deal with this type have to understand the data associated with this type The functions are therefore tightly bound to this type More complex types – containing arrays or lists – cannot be automatically copied You have to write code for this 53
  • 54. Memory Structures: Classes Solution • Classes Bind data and code together May be extended from another class May contain (“Encapsulate”) other classes • Example Class Customer Class Customeras NotesName Public name as NotesName Public name Public UNID as String Public UNID as String Public Department as String Public Department as String Public Sub new(doc as NotesDocument) Public Sub new(doc NotesName(doc.name(0)) me.Name ==new as NotesDocument) me.Name new NotesName(doc.name(0)) me.UNID ==doc.UniqueID me.UNID doc.UniqueID me.UNID ==doc.Department(0) me.UNID doc.Department(0) end sub end type sub end end type Dim newCustomer as Customer(doc) Dim newCustomer as Customer(doc) Print “My customer name is: “ “++newCustomer.Name Print “My customer name is: newCustomer.Name 54
  • 55. Memory Structures: Combinations • Combining Lists and Classes is particularly useful: Dim CustomerList List as Customer Dim CustomerList List as Customer dim doc as NotesDocument dim doc as NotesDocument set doc ==vCustomers.getFirstDocument set doc vCustomers.getFirstDocument while not doc is nothing while not doc is nothing dim C as new Customer(doc) dim C as new Customer(doc) set CustomerList(C.name) ==C set CustomerList(C.name) C set doc ==vCustomers.GetNextDocument(doc) wendset doc vCustomers.GetNextDocument(doc) wend forall thisCustomer in CustomerList forall thisCustomer in + thisCustomer.Name + “ is in Department: “ + _ Print “Customer: “ “CustomerList Print “Customer: + thisCustomer.Name + “ is in Department: “ + _ thisCustomer.Department end forallthisCustomer.Department end forall 55
  • 56. Memory Structures: Encapsulation • Classes can contain other classes: Class Customers Dim CL as new CustomerList Dim CL as new CustomerList Class Customers call CL.load(viewCustomers) call CL.load(viewCustomers) Public CustomerList List as Customer call CL.Print call CL.Print Public CustomerList List as Customer Public function load(vCust as notesView) as integer Public functionNotesDocument dim doc as load(vCust as notesView) as integer dim doc as NotesDocument set doc ==vCust.getFirstDocument set doc vCust.getFirstDocument while not doc is nothing while not as new Customer(doc) dim C doc new Customer(doc) dim C as is nothing set CustomerList(C.name) ==C set CustomerList(C.name) C set doc ==vCust.GetNextDocument(doc) wendset doc vCust.GetNextDocument(doc) wend end function end function Public Function Print as Integer Public Function Print as Integer forall thisCustomer in CustomerList forall “Customer: “ + thisCustomer.Name + “ is in Department: “ + _ Print thisCustomer in thisCustomer.Name + “ is in Department: “ + _ Print “Customer: “ + CustomerList thisCustomer.Department thisCustomer.Department end forall end forall end function end classfunction end end class 56
  • 57. Memory Structures: Classes: Implementation • Classes are all defined in the declarations section. Difficult to navigate and edit Keep classes small – 1000 lines maximum • No Class Browser Check out http://www.teamstudio.co m for Craig Schumann's LotusScript Class Browser 57
  • 58. Memory Structures: Usage • Use these memory structures to: Build intermediate information in memory Cache intermediate results • Much more efficient to use memory than: Re-open Notes documents multiple times • Where would I use them ? Directory or data synchronization tools Reporting or analysis tooling Database content checking tools Complex data structure management 58
  • 59. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 59
  • 60. Performance: Introduction • I said “Architect for Maintainability” This is still true However, sometimes – especially on large data runs – you need to know how to perform better Don't prematurely optimize • Expensive operations: Opening a NotesView Opening large number of NotesDocuments • Cheap operations: Holding something in memory • Why ? CPU is now very very cheap Memory is now very cheap Disk I/O – whilst faster – is still thousands of times slower than accessing memory 60
  • 61. Performance: Views • Fast Use “NotesViewEntries” to parse data from existing view summary information • Medium Use NotesViews to iterate through documents Use NotesDocumentCollections to iterate through documents • Slow Looking up every single document • Very slow Opening up every single document, and using “extended class syntax” to obtain data fields: Always use “GetItemValue” instead This will reduce incorrectly named fields You can get type conversion GOTCHA! doc.GetItemValue(“field”)(0) is faster than doc.Field(0) 61
  • 62. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 62
  • 63. Design Patterns: Introduction • Design patterns are: Generally accepted Best Practices for designing part of an application Prevalent in the Java world A good way of solving common problems • Design patterns are not: A replacement for actually designing the application! To be used prescriptively After all, if all of our job could be automatically performed, we would not be required! • We shall discuss: A common Notes design pattern An object oriented design pattern: Singleton 63
  • 64. Design Pattern: Notes Replication • Before Notes/Domino v6, scheduled agents were not allowed to open databases on other servers This led to catalog.nsf style designs, where: A single database was replicated to multiple servers A “run on all servers” agent collected data All the data was replicated to all servers This in turn leads to a huge replication overhead, pushing all that data back to all replicas • In v6.x, you can assign “Trusted Servers” Defined in the Server Document on the security Tab List all servers that this server is allowed connections from Agents can then open databases on other servers 64
  • 65. Trusted Servers vs Replication: Application • Architecturally, you may now: Have a single central database A single scheduled agent Now pushes and pulls data to and from remote servers • This changes the architecture of applications Reduces data replication Increases response rate – no longer waiting for replication schedules Depends on reliable network links 65
  • 66. Design Pattern: Singleton • The Singleton is: A method of ensuring that only one object of a particular type is created Also a very fine Scottish malt whiskey Do not mix these two up! • Particularly useful for: Configuration class objects An object that holds global configuration information about your application 66
  • 67. Design Pattern: Singleton Implementation • Create a class in a script library Let’s call it “ConfigurationClass” Let’s create it in script library “Class:ConfigurationClass” It contains all global setup information for an application It loads itself from a profile doc in the current database It is used by the application to get configuration variables Class ConfigurationClass Use “class:ConfigurationClass” Class ConfigurationClass Use “class:ConfigurationClass” Public ConfigVar1 as String sub initialize() Public ConfigVar1 as String subdim C as new ConfigurationClass() initialize() dim C as new ConfigurationClass() Sub new () Print “Config is: “ + C.ConfigVar1 Sub new () dim sSession as new NotesSession dim sSession as new NotesSession dim dbThis as NotesDatabase end sub “Config is: “ + C.ConfigVar1 Print end sub set dbThis = as NotesDatabase dim dbThis sSession.CurrentDatabase dim docProfilesSession.CurrentDatabase set dbThis = as NotesDocument set docProfile = as NotesDocument dim docProfile dbThis.GetProfileDocument(“Configuration”) set docProfile = dbThis.GetProfileDocument(“Configuration”) ConfigVariable1 = docProfile.GetItemValue(“ConfigVariable1”)(0) ConfigVariable1 = docProfile.GetItemValue(“ConfigVariable1”)(0) end sub end class sub end end class 67
  • 68. Design Pattern: Singleton Implementation (cont.) • The code so far does not load a singleton It loads a new copy every time it's called • To make ConfigurationClass a singleton Create a global function called “GetConfiguration” Create a global variable called CurrentConfiguration Make the class “Private” Use “class:ConfigurationClass” Use “class:ConfigurationClass” sub initialize() subdim C as ConfigurationClass() initialize() set C C as ConfigurationClass() dim = getConfiguration set C = getConfiguration Private CurrentConfiguration as ConfigurationClass Print “Config is: “ + C.ConfigVar1 Private CurrentConfiguration as ConfigurationClass end sub “Config is: “ + C.ConfigVar1 Print end sub Public Function getConfiguration as ConfigurationClass Public Function getConfiguration as ConfigurationClass if CurrentConfiguration is nothing then if CurrentConfiguration is nothing then set CurrentConfiguration = new ConfigurationClass() end if set CurrentConfiguration = new ConfigurationClass() end if set getSingleton = CurrentConfiguration set getSingleton = CurrentConfiguration end function end function 68
  • 69. What We'll Cover • Introduction • Structure • Variables • Comments • Cut 'n' Paste Code • Error Handling • Functions and Subs • Memory Structures • Performance • Design Patterns • Summary and Questions 69
  • 70. Resources • Code Complete 2 Steve McConnell, Microsoft Press • http://www.openNtf.org • http://www.keysolutions.com/Notesfaq • http://www.notes.net For forum and for support database • My “Object Orientated LotusScript” Presentation 70
  • 71. Key Points to Take Home • Best Practices Don't be too prescriptive – use them as guidelines Sometimes using Best Practices means more work Always be willing to learn new techniques Always be willing to discuss implementation with other parties – this will always pay off Always code for maintenance. It's the highest cost Make your code easy to deploy Your Administrators will be more forgiving You are not alone – use the on-line forums to investigate 71
  • 72. Your Turn! Questions? How to Contact Me: Bill Buchan Bill@hadsl.com 72