SlideShare a Scribd company logo
The 12 step guide to
LotusScript
Bill Buchan
hadsl
2
#1: 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 beYOU
3
#2: 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
current database may fail
• Trapping all run-time errors and providing an execution
path that fails safely
4
#2: 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
5
#3: “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 night
when you wake up next to some
code you don’t recognize.”
	

 – Bob Balaban
6
#4: 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
• Remember to always declare the type of variables and
parameters - otherwise it defaults to variants!
7
#5: 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 document
item – convert to an array first
Dim Pres list as String
Pres(“George”) = “Bush”
Pres(“Bill”) = “Clinton”
Print “Georges’s last name is: “ + Pres(“George”)
if not isElement(Pres(“Chad”)) then print “Chad wasn’t
found”
forall thisPres in Pres
	
  Print listtag(thisPres) + “ “ + thisPres
end forall
8
#6: 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) as
integer
	
  mytest = false
	
  if p1=”” then exit function
	
  if p2=”” then exit function
	
  ...
	
  ' Now actually do something!
	
  ....
	
  mytest = true
end function
9
#7: 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” value
Sub initialize()
	
  Dim myArray() as String
	
  redim myArray(0)
	
  call myExtend (myArray, “Hello Sailor”)
end sub
function myExtend(S() as String, ns as String) as integer
if (S(ubound(S)) <> “”) then redim preserve S(ubound(S)+1)
S(ubound(S)) = ns
extend = true
end function
• 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 logging
so slow that it affects
application performance!
10
#8: Logging
11
#8: 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 integer
	
  Test = false
	
  on error goto errorhandler
	
  ' ...
	
  Test = true
exitFunction:
	
  exit function
errorhandler:
	
  call logError()
	
  resume exitfunction
end function
12
#8: Logging (cont.)
• Example OpenLog output:
13
#9: 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
14
#10: Always use full canonical names in
reader/author fields!
• Common names assume the same hierarchy as the
server in use
• Abbreviated names dont work
• Always use multi-values for multiple names - sticking ‘;’
between names wont work
• And always set the field to reader/author in
LotusScript!
15
#11: Evaluate
• Evaluate allows you to run @Functions within
LotusScript
• Sometimes faster, easier
• Example:	

	

 	

 	

 evaluate(|@unique|)
• DON’T:
• Overuse it. Lots of LotusScript functions mimic @functions
• strRight == @StrRight
16
#12: “Trusted Servers”
• Scheduled Agents cannot normally open databases on
other servers
• “Trusted Servers” field in R6 server document, security
section 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 …
17
#13: 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 error
trapping code
• Prevents “cut-n-paste coding” errors ...
18
#13: LSI_Info()/GetThreadInfo (cont.)
Function RaiseError()
	
  Dim thisType As String
	
  Dim es as String
	
  thisType = Typename(Me)
	
  	
 
' Not a class, use the calling module instead
If (thisType = "") Then 	
  thisType = Getthreadinfo(11)
	
  	
 
	
  es = thisType & "::" & Getthreadinfo(10) & ": "
	
  If (Err = 0) Then
	
  	
  es = es + "Manually raised an error"
	
  Else
es = es + "Run time error: (" + Trim(Str(Err)) + ") " + _
	
  	
  Error$ + " at line: "+ Trim(Str(Erl))
End If
	
  Print es
end function
	
  ' calling code...
...
ExitFunction:
exit function
errorhandler:
Call RaiseError()
resume exitFunction
end function
19
Okay
I added a new step
20
Done!

More Related Content

What's hot

CNIT 127: Ch 8: Windows overflows (Part 1)
CNIT 127: Ch 8: Windows overflows (Part 1)CNIT 127: Ch 8: Windows overflows (Part 1)
CNIT 127: Ch 8: Windows overflows (Part 1)
Sam Bowne
 
Java 8 concurrency abstractions
Java 8 concurrency abstractionsJava 8 concurrency abstractions
Java 8 concurrency abstractions
Nawazish Mohammad Khan
 
Batch Apex in Salesforce
Batch Apex in SalesforceBatch Apex in Salesforce
Batch Apex in Salesforce
David Helgerson
 
Reflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond SmalltakReflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond Smalltak
Marcus Denker
 
CNIT 127 Lecture 7: Intro to 64-Bit Assembler
CNIT 127 Lecture 7: Intro to 64-Bit AssemblerCNIT 127 Lecture 7: Intro to 64-Bit Assembler
CNIT 127 Lecture 7: Intro to 64-Bit Assembler
Sam Bowne
 
127 Ch 2: Stack overflows on Linux
127 Ch 2: Stack overflows on Linux127 Ch 2: Stack overflows on Linux
127 Ch 2: Stack overflows on Linux
Sam Bowne
 
CNIT 127 Ch 8: Windows overflows (Part 1)
CNIT 127 Ch 8: Windows overflows (Part 1)CNIT 127 Ch 8: Windows overflows (Part 1)
CNIT 127 Ch 8: Windows overflows (Part 1)
Sam Bowne
 
CNIT 126 12: Covert Malware Launching
CNIT 126 12: Covert Malware LaunchingCNIT 126 12: Covert Malware Launching
CNIT 126 12: Covert Malware Launching
Sam Bowne
 
Java 8 New features
Java 8 New featuresJava 8 New features
Java 8 New features
Son Nguyen
 
Practical Malware Analysis: Ch 9: OllyDbg
Practical Malware Analysis: Ch 9: OllyDbgPractical Malware Analysis: Ch 9: OllyDbg
Practical Malware Analysis: Ch 9: OllyDbg
Sam Bowne
 
Pharo: A Reflective System
Pharo: A Reflective SystemPharo: A Reflective System
Pharo: A Reflective System
Marcus Denker
 
Async Programming in C# 5
Async Programming in C# 5Async Programming in C# 5
Async Programming in C# 5
Pratik Khasnabis
 
CNIT 127: L9: Web Templates and .NET
CNIT 127: L9: Web Templates and .NETCNIT 127: L9: Web Templates and .NET
CNIT 127: L9: Web Templates and .NET
Sam Bowne
 
CNIT 127 Ch 3: Shellcode
CNIT 127 Ch 3: ShellcodeCNIT 127 Ch 3: Shellcode
CNIT 127 Ch 3: Shellcode
Sam Bowne
 
PharoDAYS 2015: Pharo Status - by Markus Denker
PharoDAYS 2015: Pharo Status - by Markus DenkerPharoDAYS 2015: Pharo Status - by Markus Denker
PharoDAYS 2015: Pharo Status - by Markus Denker
Pharo
 
Reflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond SmalltakReflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond Smalltak
Marcus Denker
 
Practical Malware Analysis: Ch 5: IDA Pro
Practical Malware Analysis: Ch 5: IDA ProPractical Malware Analysis: Ch 5: IDA Pro
Practical Malware Analysis: Ch 5: IDA Pro
Sam Bowne
 
CNIT 127 Ch 6: The Wild World of Windows
CNIT 127 Ch 6: The Wild World of WindowsCNIT 127 Ch 6: The Wild World of Windows
CNIT 127 Ch 6: The Wild World of Windows
Sam Bowne
 
CNIT 126: 10: Kernel Debugging with WinDbg
CNIT 126: 10: Kernel Debugging with WinDbgCNIT 126: 10: Kernel Debugging with WinDbg
CNIT 126: 10: Kernel Debugging with WinDbg
Sam Bowne
 
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
 

What's hot (20)

CNIT 127: Ch 8: Windows overflows (Part 1)
CNIT 127: Ch 8: Windows overflows (Part 1)CNIT 127: Ch 8: Windows overflows (Part 1)
CNIT 127: Ch 8: Windows overflows (Part 1)
 
Java 8 concurrency abstractions
Java 8 concurrency abstractionsJava 8 concurrency abstractions
Java 8 concurrency abstractions
 
Batch Apex in Salesforce
Batch Apex in SalesforceBatch Apex in Salesforce
Batch Apex in Salesforce
 
Reflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond SmalltakReflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond Smalltak
 
CNIT 127 Lecture 7: Intro to 64-Bit Assembler
CNIT 127 Lecture 7: Intro to 64-Bit AssemblerCNIT 127 Lecture 7: Intro to 64-Bit Assembler
CNIT 127 Lecture 7: Intro to 64-Bit Assembler
 
127 Ch 2: Stack overflows on Linux
127 Ch 2: Stack overflows on Linux127 Ch 2: Stack overflows on Linux
127 Ch 2: Stack overflows on Linux
 
CNIT 127 Ch 8: Windows overflows (Part 1)
CNIT 127 Ch 8: Windows overflows (Part 1)CNIT 127 Ch 8: Windows overflows (Part 1)
CNIT 127 Ch 8: Windows overflows (Part 1)
 
CNIT 126 12: Covert Malware Launching
CNIT 126 12: Covert Malware LaunchingCNIT 126 12: Covert Malware Launching
CNIT 126 12: Covert Malware Launching
 
Java 8 New features
Java 8 New featuresJava 8 New features
Java 8 New features
 
Practical Malware Analysis: Ch 9: OllyDbg
Practical Malware Analysis: Ch 9: OllyDbgPractical Malware Analysis: Ch 9: OllyDbg
Practical Malware Analysis: Ch 9: OllyDbg
 
Pharo: A Reflective System
Pharo: A Reflective SystemPharo: A Reflective System
Pharo: A Reflective System
 
Async Programming in C# 5
Async Programming in C# 5Async Programming in C# 5
Async Programming in C# 5
 
CNIT 127: L9: Web Templates and .NET
CNIT 127: L9: Web Templates and .NETCNIT 127: L9: Web Templates and .NET
CNIT 127: L9: Web Templates and .NET
 
CNIT 127 Ch 3: Shellcode
CNIT 127 Ch 3: ShellcodeCNIT 127 Ch 3: Shellcode
CNIT 127 Ch 3: Shellcode
 
PharoDAYS 2015: Pharo Status - by Markus Denker
PharoDAYS 2015: Pharo Status - by Markus DenkerPharoDAYS 2015: Pharo Status - by Markus Denker
PharoDAYS 2015: Pharo Status - by Markus Denker
 
Reflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond SmalltakReflection in Pharo: Beyond Smalltak
Reflection in Pharo: Beyond Smalltak
 
Practical Malware Analysis: Ch 5: IDA Pro
Practical Malware Analysis: Ch 5: IDA ProPractical Malware Analysis: Ch 5: IDA Pro
Practical Malware Analysis: Ch 5: IDA Pro
 
CNIT 127 Ch 6: The Wild World of Windows
CNIT 127 Ch 6: The Wild World of WindowsCNIT 127 Ch 6: The Wild World of Windows
CNIT 127 Ch 6: The Wild World of Windows
 
CNIT 126: 10: Kernel Debugging with WinDbg
CNIT 126: 10: Kernel Debugging with WinDbgCNIT 126: 10: Kernel Debugging with WinDbg
CNIT 126: 10: Kernel Debugging with WinDbg
 
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
 

Viewers also liked

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
 
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
 
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
 
Entwickercamp - Development for Administrators
Entwickercamp - Development for AdministratorsEntwickercamp - Development for Administrators
Entwickercamp - Development for AdministratorsBill Buchan
 
Dev buchan 30 proven tips
Dev buchan 30 proven tipsDev buchan 30 proven tips
Dev buchan 30 proven tipsBill Buchan
 
Brand Toscana: monitoraggio conversazioni Maggio 2013
Brand Toscana: monitoraggio conversazioni Maggio 2013Brand Toscana: monitoraggio conversazioni Maggio 2013
Brand Toscana: monitoraggio conversazioni Maggio 2013
Costanza Giovannini
 
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
 

Viewers also liked (9)

Ad505 dev blast
Ad505 dev blastAd505 dev blast
Ad505 dev blast
 
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
 
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
 
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
 
Entwickercamp - Development for Administrators
Entwickercamp - Development for AdministratorsEntwickercamp - Development for Administrators
Entwickercamp - Development for Administrators
 
Dev buchan 30 proven tips
Dev buchan 30 proven tipsDev buchan 30 proven tips
Dev buchan 30 proven tips
 
Brand Toscana: monitoraggio conversazioni Maggio 2013
Brand Toscana: monitoraggio conversazioni Maggio 2013Brand Toscana: monitoraggio conversazioni Maggio 2013
Brand Toscana: monitoraggio conversazioni Maggio 2013
 
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
 

Similar to 12 Step Guide to Lotuscript

Speed geeking-lotusscript
Speed geeking-lotusscriptSpeed geeking-lotusscript
Speed geeking-lotusscriptBill Buchan
 
Lotuscript for large systems
Lotuscript for large systemsLotuscript for large systems
Lotuscript for large systemsBill Buchan
 
Utilizing the open ntf domino api
Utilizing the open ntf domino apiUtilizing the open ntf domino api
Utilizing the open ntf domino api
Oliver Busse
 
Utilizing the OpenNTF Domino API
Utilizing the OpenNTF Domino APIUtilizing the OpenNTF Domino API
Utilizing the OpenNTF Domino API
Oliver Busse
 
Utilizing the OpenNTF Domino API
Utilizing the OpenNTF Domino APIUtilizing the OpenNTF Domino API
Utilizing the OpenNTF Domino API
Oliver Busse
 
Design Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesDesign Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best Practices
Inductive Automation
 
Design Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesDesign Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best Practices
Inductive Automation
 
APIs distribuidos con alta escalabilidad
APIs distribuidos con alta escalabilidadAPIs distribuidos con alta escalabilidad
APIs distribuidos con alta escalabilidad
Software Guru
 
Redundant devops
Redundant devopsRedundant devops
Redundant devops
Szabolcs Szabolcsi-Tóth
 
Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)
Viral Solani
 
KYSUC - Keep Your Schema Under Control
KYSUC - Keep Your Schema Under ControlKYSUC - Keep Your Schema Under Control
KYSUC - Keep Your Schema Under Control
Coimbra JUG
 
Running Airflow Workflows as ETL Processes on Hadoop
Running Airflow Workflows as ETL Processes on HadoopRunning Airflow Workflows as ETL Processes on Hadoop
Running Airflow Workflows as ETL Processes on Hadoop
clairvoyantllc
 
Tales Of The Black Knight - Keeping EverythingMe running
Tales Of The Black Knight - Keeping EverythingMe runningTales Of The Black Knight - Keeping EverythingMe running
Tales Of The Black Knight - Keeping EverythingMe running
Dvir Volk
 
Dev buchan best practices
Dev buchan best practicesDev buchan best practices
Dev buchan best practicesBill Buchan
 
Treasure Data Summer Internship 2016
Treasure Data Summer Internship 2016Treasure Data Summer Internship 2016
Treasure Data Summer Internship 2016
Yuta Iwama
 
Breaking data
Breaking dataBreaking data
Breaking data
Terry Bunio
 
Profiling and Tuning a Web Application - The Dirty Details
Profiling and Tuning a Web Application - The Dirty DetailsProfiling and Tuning a Web Application - The Dirty Details
Profiling and Tuning a Web Application - The Dirty Details
Achievers Tech
 

Similar to 12 Step Guide to Lotuscript (20)

Speed geeking-lotusscript
Speed geeking-lotusscriptSpeed geeking-lotusscript
Speed geeking-lotusscript
 
Lotuscript for large systems
Lotuscript for large systemsLotuscript for large systems
Lotuscript for large systems
 
Utilizing the open ntf domino api
Utilizing the open ntf domino apiUtilizing the open ntf domino api
Utilizing the open ntf domino api
 
Utilizing the OpenNTF Domino API
Utilizing the OpenNTF Domino APIUtilizing the OpenNTF Domino API
Utilizing the OpenNTF Domino API
 
Utilizing the OpenNTF Domino API
Utilizing the OpenNTF Domino APIUtilizing the OpenNTF Domino API
Utilizing the OpenNTF Domino API
 
Design Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesDesign Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best Practices
 
Design Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best PracticesDesign Like a Pro: Scripting Best Practices
Design Like a Pro: Scripting Best Practices
 
SGCE 2015 REST APIs
SGCE 2015 REST APIsSGCE 2015 REST APIs
SGCE 2015 REST APIs
 
APIs distribuidos con alta escalabilidad
APIs distribuidos con alta escalabilidadAPIs distribuidos con alta escalabilidad
APIs distribuidos con alta escalabilidad
 
Redundant devops
Redundant devopsRedundant devops
Redundant devops
 
Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)Introduction to Laravel Framework (5.2)
Introduction to Laravel Framework (5.2)
 
KYSUC - Keep Your Schema Under Control
KYSUC - Keep Your Schema Under ControlKYSUC - Keep Your Schema Under Control
KYSUC - Keep Your Schema Under Control
 
Tool
ToolTool
Tool
 
Running Airflow Workflows as ETL Processes on Hadoop
Running Airflow Workflows as ETL Processes on HadoopRunning Airflow Workflows as ETL Processes on Hadoop
Running Airflow Workflows as ETL Processes on Hadoop
 
Tales Of The Black Knight - Keeping EverythingMe running
Tales Of The Black Knight - Keeping EverythingMe runningTales Of The Black Knight - Keeping EverythingMe running
Tales Of The Black Knight - Keeping EverythingMe running
 
Introduction
IntroductionIntroduction
Introduction
 
Dev buchan best practices
Dev buchan best practicesDev buchan best practices
Dev buchan best practices
 
Treasure Data Summer Internship 2016
Treasure Data Summer Internship 2016Treasure Data Summer Internship 2016
Treasure Data Summer Internship 2016
 
Breaking data
Breaking dataBreaking data
Breaking data
 
Profiling and Tuning a Web Application - The Dirty Details
Profiling and Tuning a Web Application - The Dirty DetailsProfiling and Tuning a Web Application - The Dirty Details
Profiling and Tuning a Web Application - The Dirty Details
 

More from Bill Buchan

Dummies guide to WISPS
Dummies guide to WISPSDummies guide to WISPS
Dummies guide to WISPS
Bill Buchan
 
WISP for Dummies
WISP for DummiesWISP for Dummies
WISP for Dummies
Bill Buchan
 
WISP Worst Practices
WISP Worst PracticesWISP Worst Practices
WISP Worst Practices
Bill Buchan
 
Marykirk raft race presentation night 2014
Marykirk raft race presentation night 2014Marykirk raft race presentation night 2014
Marykirk raft race presentation night 2014
Bill 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
 
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 v1
Bill 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 script
Bill 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-ad
Bill Buchan
 
Softsphere 08 web services bootcamp
Softsphere 08 web services bootcampSoftsphere 08 web services bootcamp
Softsphere 08 web services bootcamp
Bill Buchan
 
Connections Lotusphere Worst Practices 2013
Connections Lotusphere Worst Practices 2013Connections Lotusphere Worst Practices 2013
Connections Lotusphere Worst Practices 2013
Bill Buchan
 
Lotusphere 2009 The 11 Commandments
Lotusphere 2009 The 11 CommandmentsLotusphere 2009 The 11 Commandments
Lotusphere 2009 The 11 Commandments
Bill Buchan
 
Lotusphere 2008 Worst practices
Lotusphere 2008 Worst practicesLotusphere 2008 Worst practices
Lotusphere 2008 Worst practices
Bill Buchan
 
Lotusphere 2008 - Jumpstart 206 - Web Services Bootcamp
Lotusphere 2008 - Jumpstart 206 - Web Services BootcampLotusphere 2008 - Jumpstart 206 - Web Services Bootcamp
Lotusphere 2008 - Jumpstart 206 - Web Services Bootcamp
Bill Buchan
 
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScriptLotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Bill Buchan
 
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
Bill Buchan
 
Lotusphere 2007 AD505 DevBlast 30 LotusScript Tips
Lotusphere 2007 AD505 DevBlast 30 LotusScript TipsLotusphere 2007 AD505 DevBlast 30 LotusScript Tips
Lotusphere 2007 AD505 DevBlast 30 LotusScript Tips
Bill Buchan
 

More from 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 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
 
Bp301
Bp301Bp301
Bp301
 
Ad507
Ad507Ad507
Ad507
 
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
 
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
 
Lotusphere 2009 The 11 Commandments
Lotusphere 2009 The 11 CommandmentsLotusphere 2009 The 11 Commandments
Lotusphere 2009 The 11 Commandments
 
Lotusphere 2008 Worst practices
Lotusphere 2008 Worst practicesLotusphere 2008 Worst practices
Lotusphere 2008 Worst practices
 
Lotusphere 2008 - Jumpstart 206 - Web Services Bootcamp
Lotusphere 2008 - Jumpstart 206 - Web Services BootcampLotusphere 2008 - Jumpstart 206 - Web Services Bootcamp
Lotusphere 2008 - Jumpstart 206 - Web Services Bootcamp
 
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScriptLotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
Lotusphere 2007 BP301 Advanced Object Oriented Programming for LotusScript
 
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
Lotusphere 2007 AD507 Leveraging the Power of Object Oriented Programming in ...
 
Lotusphere 2007 AD505 DevBlast 30 LotusScript Tips
Lotusphere 2007 AD505 DevBlast 30 LotusScript TipsLotusphere 2007 AD505 DevBlast 30 LotusScript Tips
Lotusphere 2007 AD505 DevBlast 30 LotusScript Tips
 

Recently uploaded

From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
Product School
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
Product School
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
UiPathCommunity
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
DianaGray10
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
RTTS
 

Recently uploaded (20)

From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
From Daily Decisions to Bottom Line: Connecting Product Work to Revenue by VP...
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...How world-class product teams are winning in the AI era by CEO and Founder, P...
How world-class product teams are winning in the AI era by CEO and Founder, P...
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdfFIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
FIDO Alliance Osaka Seminar: Passkeys at Amazon.pdf
 
Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4UiPath Test Automation using UiPath Test Suite series, part 4
UiPath Test Automation using UiPath Test Suite series, part 4
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 

12 Step Guide to Lotuscript

  • 1. The 12 step guide to LotusScript Bill Buchan hadsl
  • 2. 2 #1: 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 beYOU
  • 3. 3 #2: 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 current database may fail • Trapping all run-time errors and providing an execution path that fails safely
  • 4. 4 #2: 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
  • 5. 5 #3: “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 night when you wake up next to some code you don’t recognize.” – Bob Balaban
  • 6. 6 #4: 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 • Remember to always declare the type of variables and parameters - otherwise it defaults to variants!
  • 7. 7 #5: 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 document item – convert to an array first Dim Pres list as String Pres(“George”) = “Bush” Pres(“Bill”) = “Clinton” Print “Georges’s last name is: “ + Pres(“George”) if not isElement(Pres(“Chad”)) then print “Chad wasn’t found” forall thisPres in Pres Print listtag(thisPres) + “ “ + thisPres end forall
  • 8. 8 #6: 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) as integer mytest = false if p1=”” then exit function if p2=”” then exit function ... ' Now actually do something! .... mytest = true end function
  • 9. 9 #7: 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” value Sub initialize() Dim myArray() as String redim myArray(0) call myExtend (myArray, “Hello Sailor”) end sub function myExtend(S() as String, ns as String) as integer if (S(ubound(S)) <> “”) then redim preserve S(ubound(S)+1) S(ubound(S)) = ns extend = true end function
  • 10. • 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 logging so slow that it affects application performance! 10 #8: Logging
  • 11. 11 #8: 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 integer Test = false on error goto errorhandler ' ... Test = true exitFunction: exit function errorhandler: call logError() resume exitfunction end function
  • 12. 12 #8: Logging (cont.) • Example OpenLog output:
  • 13. 13 #9: 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
  • 14. 14 #10: Always use full canonical names in reader/author fields! • Common names assume the same hierarchy as the server in use • Abbreviated names dont work • Always use multi-values for multiple names - sticking ‘;’ between names wont work • And always set the field to reader/author in LotusScript!
  • 15. 15 #11: Evaluate • Evaluate allows you to run @Functions within LotusScript • Sometimes faster, easier • Example: evaluate(|@unique|) • DON’T: • Overuse it. Lots of LotusScript functions mimic @functions • strRight == @StrRight
  • 16. 16 #12: “Trusted Servers” • Scheduled Agents cannot normally open databases on other servers • “Trusted Servers” field in R6 server document, security section 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 …
  • 17. 17 #13: 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 error trapping code • Prevents “cut-n-paste coding” errors ...
  • 18. 18 #13: LSI_Info()/GetThreadInfo (cont.) Function RaiseError() Dim thisType As String Dim es as String thisType = Typename(Me) ' Not a class, use the calling module instead If (thisType = "") Then thisType = Getthreadinfo(11) es = thisType & "::" & Getthreadinfo(10) & ": " If (Err = 0) Then es = es + "Manually raised an error" Else es = es + "Run time error: (" + Trim(Str(Err)) + ") " + _ Error$ + " at line: "+ Trim(Str(Erl)) End If Print es end function ' calling code... ... ExitFunction: exit function errorhandler: Call RaiseError() resume exitFunction end function
  • 19. 19 Okay I added a new step