Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
© 2007 Wellesley Information Services. All rights reserved.30 Proven Tips toOptimize YourLotusScriptDevelopmentBill Buchan...
2What We’ll Cover …• Introduction• Theory• Practice• Advanced• Wrap-up
3Introduction• Who is the target audience? Lotus Notes Developers• What is this about? This talk aims to run through 30 ...
4Introduction (cont.)• Why 30 tips? “The Lazy Programmer” methodology Experience and understanding Push your comfort zo...
5What We’ll Cover …• Introduction• Theory• Practice• Advanced• Wrap-up
6Theory #1: Option Declare• You should always use “Option Declare”• Yes, but why? If not, all variables are created at ru...
7Theory #2: Templates and Versions• In terms of custom code, you should always: Create templates with new code Databases...
8Theory #3: Application Lifecycle• You should always: Develop in a development “sandbox” Test in a user acceptance envir...
9Theory #3: Application Lifecycle (cont.)managerDevDeveloper managerAdministratorUATProductionmanagereditoruser
10Theory #4: “Measure Twice, Cut Once”• Spend more time thinking and less time coding• Think of at least TWO methods of so...
11Theory #5: Code Structure• Problem decomposition: Smaller code sequences are easier to: Maintain – the majority of the...
12Theory #5: Code Structure (cont.)• Tips: Keep functions/procedures/classes at a manageable size But don’t be prescript...
13Theory #6: How to Code• How to code Code for maintenance Code updates cost more than new code Architect well. Get the...
14Theory #7: How to Test• Test soon, test often, test completely Look at test-driven development Write the specification...
15Theory #7: How to Test (cont.)• Why test early? Costs rise as the tests fail further away from development Cheapest to...
16Theory #8: “Attitude”• The first rule of Best Practices is: There is no Best Practice!• Seriously: Don’t use Best Prac...
17Theory #9: Comments• Comments Don’t over-comment – explain the “Why!” I usually only comment non-intuitive algorithms...
18Theory #9: Comments (cont.)• Remember: Comments consume code space in LotusScript There’s a 64k — about 1,400 line — l...
19Theory #10: Error Handling• An Error is thrown at run-time when: A resource is unavailable: Database, server, memory F...
20Theory #10: Error Handling (cont.)• If an error occurs in the middle of a critical sequence ofupdates, possibly some upd...
21Theory #10: Error Handling (cont.)• Two approaches: Error trap in almost every routine Very granular, lots of informat...
22What We’ll Cover …• Introduction• Theory• Practice• Advanced• Wrap-up
23Practice #1: The List Operator• List stores a value with a unique lookup key Pros: It’s easy and it’s fast It’s built...
24Practice #2: Defensive Coding• Defensive coding is: Assume the worst, check all input On every function Does this aff...
25Practice #3: Extending Arrays the Easy Way• Pros: No need to keep separate index of array size Automatically “trims”• ...
26Practice #4: Logging• If you have applications with scheduled Agents• Or, if you have a diverse range of clients Then, ...
27Practice #4: Logging (cont.)• OpenLog is an OpenNTF Project: www.openntf.org• It provides a framework for collecting er...
28Practice #4: Logging (cont.)• Example OpenLog output:
29Practice #5: Code Hiding• Code hiding Means decomposing your code so that consumers don’t seeyour code Including yours...
30Practice #6: Use NotesDateTime Instead of Strings!• Don’t store date/time values as Strings• Use NotesDateTime structure...
31Practice #7: Wizards• A Wizard interface in Notes Client: Create a form with a tabbed table Set the tabs to “1,” “2,” ...
32Practice #8: Consuming Web Services• Two approaches: First, quick and dirty Install MS Soap on client machines Write L...
33Practice #8: Consuming Web Services (cont.)• Two approaches: Second, big and robust Create a Java Agent that you pass a...
34Practice #9: Evaluate• Evaluate allows you to run @Functions withinLotusScript• Sometimes faster, easier• Example:evalua...
35Practice #10: “Trusted Servers”• Scheduled Agents cannot normally open databases onother servers “Trusted Servers” fiel...
36What We’ll Cover …• Introduction• Theory• Practice• Advanced• Wrap-up
37Advanced #1: Custom Classes• What are Custom Classes? Custom Classes help to: Bundle data and code in one place Decom...
38Advanced #1: Custom Classes (cont.)Class Personprivate nName as NotesNameprivate strUNID as Stringsub new(strNewName as ...
39Advanced #2: Understanding Binding• There are two types of binding: Early: Set by the compiler Pros: Type checking, sp...
40Advanced #2: Understanding Binding (cont.)Function ListCollection(p as variant) as integertest = falseif (typeName(p) = ...
41Advanced #3: Coding for Performance• Remember: Expensive operations include: Opening databases and views Documents wit...
42Advanced #3: Coding for Performance (cont.)• Performance example: 100,000 document database 7 hours for “open every do...
43Advanced #4: Lists and Custom Classes• Custom Classes bind complex data and operations• Lists look these up quickly in m...
44Advanced #5: Class Inheritance• Class inheritance allows us to “Extend” classes to addfunctionality:class StaffPerson as...
45Advanced #6: Encapsulation• Encapsulation allows us to include other complex typesin our classes: Allows you to collect...
46Advanced #7: Version-Specific Code with ClassesClass createUserfunction createUser(...) as integer....end function….end ...
47Advanced #8: LSI_Info()/GetThreadInfo• LSI_INFO() gives some run-time information• Superceded by GetThreadInfo GetThrea...
48Advanced #8: LSI_Info()/GetThreadInfo (cont.)Function RaiseError()Dim thisType As StringDim es as StringthisType = Typen...
49Advanced #9: Execute• Execute runs LotusScript code from a String: Example: Why? Accommodates version/platform differ...
50Advanced #10: Mixing Java and LotusScript• Use each language to its strengths: Java – good for Web services, network I/...
51Advanced #10: Mixing Java and LotusScript …// Create a Script Library of type “Java” called xlib// containing the follow...
52What We’ll Cover …• Introduction• Theory• Practice• Advanced Tips• Wrap-up
53Resources• Homework: Classes – my OO presentation www.billbuchan.com/web.nsf/htdocs/BBUN6MQECQ.htm Steve McConnell, “...
54Resources (cont.)• LS 2004/AD104 – LotusScript Tips & Tricks http://www-10.lotus.com/ldd/sandbox.nsf/ecc552f1ab6e46e485...
55Resources (cont.)• Brian Benz and Rocky Oliver, “Lotus Notes and Domino6 Programming Bible” (Wiley, 2003) www.amazon.co...
567 Key Points to Take Home• You never stop learning good development techniques• Develop your code for maintenance• Good ...
57Your Turn!How to contact me:Bill BuchanBill@hadsl.com
Upcoming SlideShare
Loading in …5
×

Dev buchan 30 proven tips

730 views

Published on

Published in: Technology, Business
  • Be the first to comment

  • Be the first to like this

Dev buchan 30 proven tips

  1. 1. © 2007 Wellesley Information Services. All rights reserved.30 Proven Tips toOptimize YourLotusScriptDevelopmentBill BuchanHADSL
  2. 2. 2What We’ll Cover …• Introduction• Theory• Practice• Advanced• Wrap-up
  3. 3. 3Introduction• Who is the target audience? Lotus Notes Developers• What is this about? This talk aims to run through 30 different LotusScript tips 10 of these tips (“Theory”) are fundamental 10 of these tips (“Practice”) are what you should be doing 10 of these tips (“Advanced”) are there to provoke thought
  4. 4. 4Introduction (cont.)• Why 30 tips? “The Lazy Programmer” methodology Experience and understanding Push your comfort zone and provoke thought• Who am I? Bill Buchan Dual PCLP in v3, v4, v5, v6, v7 10+ years senior development for Enterprise customers Learn from my pain! 5+ years code auditing CEO – HADSL – developing best-practice tools
  5. 5. 5What We’ll Cover …• Introduction• Theory• Practice• Advanced• Wrap-up
  6. 6. 6Theory #1: Option Declare• You should always use “Option Declare”• Yes, but why? If not, all variables are created at run-time as variants This makes type-checking redundant Data conversion costs ten times more performance! And means all errors will be run-time errors Remember: Test lots, test early Use the strengths of the compiler to help you
  7. 7. 7Theory #2: Templates and Versions• In terms of custom code, you should always: Create templates with new code Databases with “ntf” extension OR databases with Master Template Name set Create a separate copy for each version Keep them in a central repository• Why? It makes it far easier to roll back Version control Easier to construct test cases with “other” versions
  8. 8. 8Theory #3: Application Lifecycle• You should always: Develop in a development “sandbox” Test in a user acceptance environment Pass the template to your administrator to apply• Why? It’s a basic change control system Professionalism It shakes out “hardcoded” bugs Hardcoded server names, paths, replica IDs It allows you to run extensive testing without affectingproduction
  9. 9. 9Theory #3: Application Lifecycle (cont.)managerDevDeveloper managerAdministratorUATProductionmanagereditoruser
  10. 10. 10Theory #4: “Measure Twice, Cut Once”• Spend more time thinking and less time coding• Think of at least TWO methods of solving a problem The best approach is usually a blend of the two Think about the data model!• Why? More planning, less work• “You know it’s been a rough nightwhen you wake up next to somecode you don’t recognize.”– Bob Balaban
  11. 11. 11Theory #5: Code Structure• Problem decomposition: Smaller code sequences are easier to: Maintain – the majority of the cost Reuse – if kept simple Rule of thumb: If its more than a screenful – can it bebroken up? But – don’t be prescriptive• It’s all about: Problem decomposition Maintainability Code reuse Get the data model right to start with!
  12. 12. 12Theory #5: Code Structure (cont.)• Tips: Keep functions/procedures/classes at a manageable size But don’t be prescriptive Think before decomposing problems• Discussion “Declare at the top” or “Declare in the code” I prefer to declare variables in the code
  13. 13. 13Theory #6: How to Code• How to code Code for maintenance Code updates cost more than new code Architect well. Get the data model right to start with.• Only code for performance, if required Get it working before getting it working for speed• Why? The highest cost in development is software maintenance Make it easier for the person maintaining the app It could be YOU
  14. 14. 14Theory #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 Minimize run-time errors by: Always assuming that data operations outside the currentdatabase may fail Trapping all run-time errors and providing an executionpath that fails safely
  15. 15. 15Theory #7: 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 (UATs) — 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
  16. 16. 16Theory #8: “Attitude”• The first rule of Best Practices is: There is no Best Practice!• Seriously: Don’t use Best Practices in a prescriptive manner Examine each one and decide whether it makes sense inthis context Be open to new ideas• Attitude is better than prescriptive coding No “Not invented here” syndrome Collaborate “The Lazy Programmer”
  17. 17. 17Theory #9: Comments• Comments Don’t over-comment – explain the “Why!” I usually only comment non-intuitive algorithms “This isn’t what you think … ”• 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 completeFunction test (param1 as String, param2 as String) as integer check the parameters and bail out if incorrect. Add Param 1 to param 2 Check it’s valid. If so – update... Errorhandlerend function
  18. 18. 18Theory #9: Comments (cont.)• Remember: Comments consume code space in LotusScript There’s a 64k — about 1,400 line — limit for each codesequence 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 largeclass declarations• Check out LotusScript.doc: www.lsdoc.org It’s a “JavaDoc for LotusScript” You can annotate code to make the comments clearer
  19. 19. 19Theory #10: Error Handling• 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 codesequence, jumps to calling function If top-level function has no error handler, then default errorhandling is used
  20. 20. 20Theory #10: Error Handling (cont.)• If an error occurs in the middle of a critical sequence ofupdates, possibly some updates will happen, and somewill 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 minimizes this effect Do not use “on error goto next”• You must deal with errors
  21. 21. 21Theory #10: Error Handling (cont.)• 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 validdata on how the error happened You might break transactions — and therefore compromisedata integrity• I recommend: Error trap in most routines!
  22. 22. 22What We’ll Cover …• Introduction• Theory• Practice• Advanced• Wrap-up
  23. 23. 23Practice #1: The List Operator• List stores a value with a unique lookup key Pros: It’s easy and it’s fast It’s built right into LotusScript, since v4.5 Cons: You can’t directly read and write a list from a documentitem – convert to an array firstDim Pres list as StringPres(“George”) = “Bush”Pres(“Bill”) = “Clinton”Print “Georges’s last name is: “ + Pres(“George”)if not isElement(Pres(“Chad”)) then print “Chad wasn’tfound”forall thisPres in PresPrint listtag(thisPres) + “ “ + thisPresend forall
  24. 24. 24Practice #2: Defensive Coding• Defensive coding is: Assume the worst, check all input On every function Does this affect performance? Not usually. A typical function looks like:Function mytest(p1 as String, p2 as String) asintegermytest = falseif p1=”” then exit functionif p2=”” then exit function... Now actually do something!....mytest = trueend function
  25. 25. 25Practice #3: Extending Arrays the Easy Way• Pros: No need to keep separate index of array size Automatically “trims”• Cons: Slow with large arrays Need to define some “empty” valueSub initialize()Dim myArray() as Stringredim myArray(0)call myExtend (myArray, “Hello Sailor”)end subfunction myExtend(S() as String, ns as String) as integerif (S(ubound(S)) <> “”) then redim preserve S(ubound(S)+1)S(ubound(S)) = nsextend = trueend function
  26. 26. 26Practice #4: Logging• If you have applications with scheduled Agents• Or, if you have a diverse range of clients Then, you need to log your Agent (both client and scheduled)run-time status• Why? Applications will break You need to know when they break Timing metrics for performance testing• Beware! Don’t make the loggingso slow that it affectsapplication performance!
  27. 27. 27Practice #4: Logging (cont.)• OpenLog is an OpenNTF Project: www.openntf.org• It provides a 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 integerTest = falseon error goto errorhandler ...Test = trueexitFunction:exit functionerrorhandler:call logError()resume exitfunctionend function
  28. 28. 28Practice #4: Logging (cont.)• Example OpenLog output:
  29. 29. 29Practice #5: Code Hiding• Code hiding Means decomposing your code so that consumers don’t seeyour code Including yourself Infers a logical interface (with clear naming!) Customers/peers now write to the “interface” Not the code itself It simplifies the coding experience How? “Private/Public” methods in classes, script libraries, etc.
  30. 30. 30Practice #6: Use NotesDateTime Instead of Strings!• Don’t store date/time values as Strings• Use NotesDateTime structures, and save them• Why? You don’t know how the client will interpret dates Is it dd/mm/yyyy or mm/dd/yyyy? It means that views will be able to sort on dates• This happens more often than you think! And things always break on the 13th of the month
  31. 31. 31Practice #7: Wizards• A Wizard interface in Notes Client: Create a form with a tabbed table Set the tabs to “1,” “2,” “3,” etc. Select “Switch Rows Programmatically” Set the “name” field to the name of the table: e.g., “RequestTable” Create a variable on the form with $Name: e.g., “$RequestTable” Have “forward” and “back” buttons increment/decrementthe variable
  32. 32. 32Practice #8: Consuming Web Services• Two approaches: First, quick and dirty Install MS Soap on client machines Write LotusScript to create an MS Soap Object Pro: Very quick, handy for testing Con: Platform specific, requires DLLon clients, no timeoutDim Client As VariantSet Client = CreateObject("MSSOAP.SoapClient")Initialize connection to the Web ServiceCall Client.mssoapinit ("http://localhost/testWS.nsf/Simple?wsdl")Call our simple GetEmailAddress function provided by Web serviceDim result As Stringresult = Client.getJoke()output result to message boxMessagebox result, 48, "Get Joke"
  33. 33. 33Practice #8: Consuming Web Services (cont.)• Two approaches: Second, big and robust Create a Java Agent that you pass a Notes document to – withall your setup information Read the document in your Java Agent, and consume theWeb service Write the results back to your Notes document Once the Java Agent returns, read the document forthe results Pro: Multi-platform, scalable Con: Quite a lot of work
  34. 34. 34Practice #9: Evaluate• Evaluate allows you to run @Functions withinLotusScript• Sometimes faster, easier• Example:evaluate(|@unique|)• DON’T: Overuse it. Lots of LotusScript functions mimic @functions strRight == @StrRight
  35. 35. 35Practice #10: “Trusted Servers”• Scheduled Agents cannot normally open databases onother servers “Trusted Servers” field in R6 server document, securitysection allows servers to “trust” other servers This allows you to centralize “collection” Agents Caveat: Don’t trust servers in another domain!• Pros: Simplifies architecture Fewer Agents• Con: Relies on fast, reliable network infrastructure …
  36. 36. 36What We’ll Cover …• Introduction• Theory• Practice• Advanced• Wrap-up
  37. 37. 37Advanced #1: Custom Classes• What are Custom Classes? Custom Classes help to: Bundle data and code in one place Decompose problems into “objects” Write smaller, more focused code Define and implement the internal data model Custom Classes aid reusability Pros: Good design methodology, leads to Java Cons: “Different,” and takes time to sink in
  38. 38. 38Advanced #1: Custom Classes (cont.)Class Personprivate nName as NotesNameprivate strUNID as Stringsub new(strNewName as string, strNewUNID asString)me.nnName = new NotesName(strNewName)me.strUNID = strNewUNIDend subpublic function getName as Stringif (me.nnName is nothing) then exit functiongetName = nnName.Canonicalend functionpublic function getUNID as StringgetUNID = strUNIDend functionend class
  39. 39. 39Advanced #2: Understanding Binding• There are two types of binding: Early: Set by the compiler Pros: Type checking, speed, and ease of use Example: “Dim S as String” Late: Set at run-time Pros: Flexibility, NO type checking Cons: Performance, run-time errorsDim V as variantDim S as new NotesSessionset V = S.CurrentDatabaseprint V.getTitle()
  40. 40. 40Advanced #2: Understanding Binding (cont.)Function ListCollection(p as variant) as integertest = falseif (typeName(p) = “NOTESVIEW”) or _(typeName(p) = “NOTESDOCUMENTCOLLECTION”) then decompose this collection into a number of single document calls to myselfdim doc as NotesDocumentset doc = P.getFirstDocumentwhile (not doc is nothing)call listCollection(doc)set doc = p.getNextDocument(doc)wendelse Weve been passed a single document. Process it.Print “I have been passed doc: “ + doc.Title(0)test = trueend ifend function
  41. 41. 41Advanced #3: Coding for Performance• Remember: Expensive operations include: Opening databases and views Documents with lots of fields• When collecting data: Cache views where possible Use NotesViewEntry instead of opening documents
  42. 42. 42Advanced #3: Coding for Performance (cont.)• Performance example: 100,000 document database 7 hours for “open every document in Database” Not using views 60 minutes using NotesView and opening documents 12 minutes for “NotesViewEntry”See also:Application Performance Techniques for Notes and Web Clients(Jamie Magee)
  43. 43. 43Advanced #4: Lists and Custom Classes• Custom Classes bind complex data and operations• Lists look these up quickly in memory Example: Let’s extend our Person class:dim People list as Persondim PeopleByUNID list as PersonDim P as new Person(“Joe Bloggs/ACME”, “010101010201020”)....set People(P.getName) = Pset PeopleByUNID(P.getUNID) = Pif (isElement(People(“Joe Bloggs/ACME”))) then _Print “Joes UNID is: “ + People(“Joe Bloggs/ACME”).getUNIDif (isElement(PeopleByUNID(“010101010201020”))) then _Print “UNID 010101010201020 is: “ + _PeopleByUNID(“010101010201020”).getName
  44. 44. 44Advanced #5: Class Inheritance• Class inheritance allows us to “Extend” classes to addfunctionality:class StaffPerson as Personprivate strStaffID as Stringsub new(strNewPerson as String, strNewUNID as String)end subpublic function setStaffNumber(newNo as String)strStaffID = newNoend functionpublic function getStaffNumber as StringgetStaffNumber = me.strStaffIDend functionend class
  45. 45. 45Advanced #6: Encapsulation• Encapsulation allows us to include other complex typesin our classes: Allows you to collect different types ofcomplex informationclass Departmentprivate headOfDepartment as Personprivate members list as Person as Stringprivate departmentname as Stringprivate Locations list as String…end class
  46. 46. 46Advanced #7: Version-Specific Code with ClassesClass createUserfunction createUser(...) as integer....end function….end classClass createUserv6 as createUserfunction createUser(...) as integer....end functionend classDim s as new NotesSessiondim vCU as variantselect case s.versioncase 5set vCU = new createUser()case 6set vCU = new createUserv6()case elsePrint “Version not supported”set vCU = nothingend caseif (not vCU is nothing) then _call vCU.CreateUser(....)
  47. 47. 47Advanced #8: LSI_Info()/GetThreadInfo• LSI_INFO() gives some run-time information• Superceded by GetThreadInfo GetThreadInfo(11) gives calling class GetThreadInfo(10) gives function name And lots more• Why? Error trapping: We can track where we came from We don’t have to pass lists of parameters to errortrapping code Prevents “cut-n-paste coding” errors ...
  48. 48. 48Advanced #8: LSI_Info()/GetThreadInfo (cont.)Function RaiseError()Dim thisType As StringDim es as StringthisType = Typename(Me) Not a class, use the calling module insteadIf (thisType = "") Then thisType = Getthreadinfo(11)es = thisType & "::" & Getthreadinfo(10) & ": "If (Err = 0) Thenes = es + "Manually raised an error"Elsees = es + "Run time error: (" + Trim(Str(Err)) + ") " + _Error$ + " at line: "+ Trim(Str(Erl))End IfPrint esend function calling code......ExitFunction:exit functionerrorhandler:Call RaiseError()resume exitFunctionend function
  49. 49. 49Advanced #9: Execute• Execute runs LotusScript code from a String: Example: Why? Accommodates version/platform differences at run-timeDim executeString as StringexecuteString = |print “Hello world”dim s as new NotesSessiondim db as NotesDatabaseset db = s.currentDatabaseprint “Current Database name is: “ + db.Title|execute (executeString)
  50. 50. 50Advanced #10: Mixing Java and LotusScript• Use each language to its strengths: Java – good for Web services, network I/O, multi-threadedoperations LotusScript – traditional Notes development language, worksin UI• How to mix: Simple: Call an Agent, passing a Notes Document Fast. I didn’t say you had to save the document! Works both ways LS2J Call Java from LotusScript Example on the next slide ...
  51. 51. 51Advanced #10: Mixing Java and LotusScript …// Create a Script Library of type “Java” called xlib// containing the following function:public class calculator {public int add(int a, int b) { return a + b; }public int div(int a, int b) { return a / b; }public int mul(int a, int b) { return a * b; }public int sub(int a, int b) { return a - b; }}Option PublicUse "xlib"Uselsx "*javacon"Sub InitializeDim mySession As JavaSessionDim myClass As JavaClassDim calculator As JavaObjectDim a,b,c As IntegerSet mySession = New JavaSession()Set myClass = mySession.GetClass("calculator")Set calculator = myClass.CreateObject()a = 10b = 5c = calculator.mul(a,b)MessageBox "a * b = " & cEnd Sub
  52. 52. 52What We’ll Cover …• Introduction• Theory• Practice• Advanced Tips• Wrap-up
  53. 53. 53Resources• Homework: Classes – my OO presentation www.billbuchan.com/web.nsf/htdocs/BBUN6MQECQ.htm Steve McConnell, “Code Complete, SecondEdition” (Microsoft Press, 2004) www.amazon.com/gp/product/0735619670 Duffbert’s presentation on Java http://hostit1.connectria.com/twduff/home.nsf/htdocs/TDUF5VAQSY.htm Bob Balaban, “Programming Domino 4.6 with Java” (M&TBooks, 1998) http://www.amazon.com/gp/product/1558515836
  54. 54. 54Resources (cont.)• LS 2004/AD104 – LotusScript Tips & Tricks http://www-10.lotus.com/ldd/sandbox.nsf/ecc552f1ab6e46e4852568a90055c4cd/68797abc4efa809a85256e51006a2c8a?OpenDocument&Highlight=0,AD104• nsftools – Notes Tips www.nsftools.com/tips/NotesTips.htm• The Notes FAQ! www.keysolutions.com/NotesFAQ/
  55. 55. 55Resources (cont.)• Brian Benz and Rocky Oliver, “Lotus Notes and Domino6 Programming Bible” (Wiley, 2003) www.amazon.com/gp/product/0764526111• Notes.net (of course) www.notes.net• Articles in THE VIEW André Guirard, “Speed up view development — A LotusScriptagent to automatically create a view with fields from anyform” (THE VIEW, July/August 2006) Mikkel Heisterberg, “Self-documenting LotusScriptcode” (THE VIEW, January/February 2006)
  56. 56. 567 Key Points to Take Home• You never stop learning good development techniques• Develop your code for maintenance• Good architecture is the best starting point• Understand the problem area before proposingsolutions• Spend a little time each day reading blogs, “THE VIEW,”and the support database Even though specific articles may not be of immediateinterest, they may pay off in the future• A problem shared/discussed is a problem better defined• Have fun and enjoy your work
  57. 57. 57Your Turn!How to contact me:Bill BuchanBill@hadsl.com

×