BP107 Best Practices for Object Orientated Lotusscript
Bill Buchan Director, HADSL Premier Business Partner
Agenda
Why use Object Orientated Methodologies? OO Basics in Script Demo OO application Directory Compare Extend or Encapsulate ? Large OO projects Pitfalls and Tricks Summary and questions
What is OO Programming?
Its a way of writing large, complex systems in a more intuitive manner The core assumptions are:
Most objects will represent actors or processes in a business problem You do not need to know how an object is implemented in order to use it. (Information Hiding)
Its been in Lotusscript since its inception. Its a different way of breaking down problems.
Compared to structured programming It requires more thought during architecture It requires less work during implementation (in a well architected system)
3
Why use OO Methodologies ?
Maintainability & Robustness Small code sequences are easier to maintain Code hiding lends to better componentisation and design Loose Coupling is better than tight coupling. Classes can be tested in a stand-alone basis before integration with other components. It can help you test sooner (and should be considered best practice) Promotes Re-use The holy grail of software development Standard business components can be re-used. Look at the future Java anyone ?
How to use OO Methodologies ?
Define a class
Class fred public mystring as String sub new() me.myString = Hello World end sub end class
Create one or instances of this class in memory
Dim myFred as new Fred() print myFred.myString
Some OO Generalisations
Its difficult to use - Not at all. Its a steep learning curve No There is no benefit.
Untrue. From a medium to large scale project, getting it right from the start means more code reuse, more robust applications, and less effort.
There is one class for each item in a system
Probably not. Try not to be too prescriptive in any architecture.
It takes a couple of projects before you get it.
This is probably true. The oo moment.
Agenda
Why use Object Orientated Methodologies? OO Basics in Script Demo OO application Directory Compare Extend or Encapsulate ? Large OO projects Pitfalls and Tricks Summary and questions
How to use OO within Lotusscript ?
Use Classes to define objects. Use new and delete to create instances of classes Think of notesDatabase They bundle together members (properties) Functions and Subs (methods) Classes can be based on other classes In which case they inherit all the properties and functions of the parent class More on this later
OO Basics
Classes are defined by wrapping them with Classes are defined by wrapping them with
class <name> [as <parentClass>] end class
The classes are all defined in the declarations section of a The classes are all defined in the declarations section of a Lotusscript code sequence. Lotusscript code sequence.
Remember. R5 64 limit. R6 bigger. ND7 - Best Remember. R5 64 limit. R6 bigger. ND7 - Best
When a class is constructed When a class is constructed
The sub new() function (the constructor) is called for this class, and all its parent-classes
The top-most parent class constructor is called firstWhen The top-most parent class constructor is called firstWhen
a class is deleted a class is deleted
The sub delete() (the destructor) function is called
You cannot extend subclasses from base notes classes. You cannot extend subclasses from base notes classes.
OO Basics
You can define items within a class as
Public anything else can use this property or method Private only the class itself (or any subclasses) can use this property or method)
You can extend or subclass classes
For instance, the class Animal could be extended by class dog, which is a more precise version of the class Class dog shares and re-uses all properties and methods from Animal. Class dog may OVERRIDE methods within animal Class dog may provide MORE properties and methods than class ANIMAL.
10
Example: Animal and Dog
Class animal Class animal Private myName as String Private myName as String Sub new() Sub new() me.myName = Animal me.myName = Animal End sub End sub Public function getName() as String Public function getName() as String getName = me.myName getName = me.myName end function end function Public function getSpecies() as String Public function getSpecies() as String getSpecies = Animal getSpecies = Animal End function End function End class End class Class Dog as Animal Class Dog as Animal Public masterName as String Public masterName as String sub new() sub new() me.myName = Dog me.myName = Dog end sub end sub End class End class
Private Member Constructor Constructor
Dog inherits from class Animal Public Member Overridden Constructor
11
OO Basics some best practices
Each class contained in a different script library Dont expose your internal properties
Declare them as private!
Use Me. to resolve ambiguity You can use property get & set constructs.
Functions that look like class properties Advise against it
Keep the classes small.
Large classes mean that you should split them up
that you probably aren't re-using things as much as you that you probably aren't re-using things as much as you can can
Always Architect before optimising
12
Agenda
Why use Object Orientated Methodologies? OO Basics in Script Demo OO application Directory Compare Extend or Encapsulate ? Large OO projects Pitfalls and Tricks Summary and questions
13
OO Basics. The Person Class
Class Person Public PersonName as NotesName Public DominoDomain as String Private UNID as String sub new(doc as notesDocument) set me.PersonName = new NotesName(doc.FullName(0)) me.DominoDomain = doc.Domain(0) me.UNID = doc.UniversalID end sub End class
14
So how do I use this ?
Use class:personClass Dim P as new person(doc)
Library names are case sensitive on non-wintel platforms!
Print This persons name is: & P.personName.Abbreviated
15
Agenda
Why use Object Orientated Methodologies? OO Basics in Script Demo OO application Directory Compare Extend or Encapsulate ? Large OO projects Pitfalls and Tricks Summary and questions
16
Extend or Encapsulate ?
Remember: Extending class
takes a class, makes a new class from it, but inherits all properties and methods You can override original class methods You cannot overload methods (as Java can) You can add new methods And of course you can extend to any depth
Encapsulating a class
makes a new class more useful by using other classes within it
17
Make this more useful by Encapsulation
Class PersonCollection Class PersonCollection private people list as Person private people list as Person public sub addPerson(P as Person) public sub addPerson(P as Person) set me.people(P.PersonName.Abbreviated) = P set me.people(P.PersonName.Abbreviated) = P end sub end sub public function findPerson(userName as String) as Person public function findPerson(userName as String) as Person set findPerson = nothing set findPerson = nothing if (isElement(me.people(userName))) then if (isElement(me.people(userName))) then set findPerson = me.people(userName) set findPerson = me.people(userName) end if end if end function end function End class End class
18
So how do I use personCollection?
Dim PC as new PersonCollection Dim PC as new PersonCollection Dim doc as NotesDocument Dim doc as NotesDocument Set doc = myView.getFirstDocument Set doc = myView.getFirstDocument While Not (doc is nothing) While Not (doc is nothing) dim P1 as new Person(doc) dim P1 as new Person(doc) call PC.addPerson(P1) call PC.addPerson(P1) set doc = myView.getnextDocument(doc) set doc = myView.getnextDocument(doc) Wend Wend Dim P as person Dim P as person Set P = PC.findPerson(Joe Bloggs/Acme) Set P = PC.findPerson(Joe Bloggs/Acme) If Not (P is nothing) then If Not (P is nothing) then print found person: & P.PersonName.Abbreviated print found person: & P.PersonName.Abbreviated End if End if
19
Lets improve PersonCollection
Class PersonCollection public Function loadAllDocsInView(mV as NotesView) dim doc as NotesDocument set doc = mV.getFirstDocument while Not (doc is nothing) dim P as new Person(doc) call me.addPerson(P) set doc = mV.getNextDocument(doc) wend end function end class
20
New example code.
Dim PC as new PersonCollection Call PC.loadAllDocsInView(myView) . Dim P as person Set P = PC.findPerson(Joe Bloggs/Acme) If Not (P is nothing) then print found person: & P.PersonName.Abbreviated End if
21
Now lets use PersonCollection
Well use this example class to quickly compare two domino directories.
Open both directories, and views in each database Create a new PersonCollection from each view. Iterate through the first PersonCollection, and check to see that this person is in the second view. And vice versa.
Why does this help ?
We only load the Person Documents once
We can further improve this by:
Using NotesViewEntryCollection instead of notesView
22
An interesting observation
Class PersonCollection Class PersonCollection public Function loadAllDocsInView(mV as Variant) public Function loadAllDocsInView(mV as Variant) dim doc as NotesDocument dim doc as NotesDocument set doc = mV.getFirstDocument set doc = mV.getFirstDocument while Not (doc is nothing) while Not (doc is nothing) dim P as new Person(doc) dim P as new Person(doc) me.addPerson(P) me.addPerson(P) set doc = mV.getNextDocument(doc) set doc = mV.getNextDocument(doc) wend wend end function end function end class end class
23
Demo Directory Comparison Tool
24
Agenda
Why use Object Orientated Methodologies? OO Basics in Script Demo OO application Directory Compare Extend or Encapsulate ? Large OO projects Pitfalls and Tricks Summary and questions
25
Large OO Projects
How to design large OO projects Consider various approaches, and iterate towards a good OO architecture. Good design and architecture is better than coding Use skeleton classes to mimic behaviour
Allows early integration Allows you to finalise class structure quickly
Unit test each class.
And keep unit testing them to prevent regressions
26
Large OO Projects
Its *never* completely correct
Beware tightly bound mutually dependant classes! Remember that specifications change over time. Architect for clarity and maintenance. Performance is an implementation consideration!
If you have to change class methods frequently
You are exposing weaknesses in the design phase You are open to regression errors Once methods behaviour are finalised, dont change them! Add more methods, but dont modify.
You may have to do several OO applications before you get it.
27
Agenda
Why use Object Orientated Methodologies? OO Basics in Script Demo OO application Directory Compare Extend or Encapsulate ? Large OO projects Pitfalls and Tricks Summary and questions
28
Pitfalls Fixup Time on Load
Remember, LotusScript is a p-code compiled, interpreted language
Similar to Java
Lotusscript has some loose data constructs: This means that Fixup Time is significant.
What is fixup time ?
The time taken to load all modules, and to resolve all variables. In The time taken to load all modules, and to resolve all variables. In traditional compiled programs, this was performed by the linker at traditional compiled programs, this was performed by the linker at executable build time. executable build time.
How does this affect me ?
The more complex your applications, the longer it takes almost The more complex your applications, the longer it takes almost geometrically to load. (this applies to ALL code, not just classes) geometrically to load. (this applies to ALL code, not just classes) Example: 20 classes 4 seconds load time. 120 classes 145 Example: 20 classes 4 seconds load time. 120 classes 145 seconds load time. seconds load time.
29
Fixup time ?
Fixup time vs Complexity Fixup time vs Complexity
Time (Seconds) Time (Seconds)
Complexity Complexity
30
How to code around it
Fixup time doesnt have significant impact before 20+ classes and/or script libraries (in my experience)
My Example: 120+ classes 145 seconds to load.
Use loose binding instead of tight binding.
Use Variants to hold and pass classes Use Dynamic Loading to instantiate classes After implementation, same 120+ classes 15 seconds. Downside. No more type checking!
Demands programming discipline and rigour! Demands programming discipline and rigour!
31
Dynamic Loading reference
Dynamic loading is a technique outlined in Redbook
Performance Considerations for Domino Applications SG24-5602 Buried in Appendix B, Page 243
Numerous Gary Devendorf Web Services examples
32
Dynamic Loading Example
Private P as variant Private P as variant This HAS to be global! This HAS to be global! Function createOtherClass_ Function createOtherClass_ (scriptName as String, className as String) as variant (scriptName as String, className as String) as variant Dim exString as String Dim exString as String exString = | Use | & scriptName & | This string contains exString = | Use | & scriptName & | sub initialize Lotusscript code sub initialize Set P = new | & className & |Factory & Set P = new | & className & |Factory & end sub | end sub | Execute exString Now run the code in exString Execute exString Now run the code in exString Set createOtherClass = P Set createOtherClass = P End sub End sub Sub DynamicLoadingExample Sub DynamicLoadingExample dim myClass as variant dim myClass as variant set myClass = createotherClass(class:fred, fred) set myClass = createotherClass(class:fred, fred) End sub End sub
33
Script library class:fred looks like:
Class FredFactory Public Function produce As Variant Set produce = New Fred End Function End Class Class Fred End class
The Factory Version of this class exists only to create a new instance of the main class
There are no constructor arguments being passed to class fred. This will have to be changed if you choose to add constructor arguments.
34
Dynamic Loading OO Architecture
Always have one class that knows how to construct the rest WITHOUT using the use directive.
A Factory class, for instance.
You dont have to dynamically load ALL classes.
Common classes such as log or config are always normally resident
You can dynamically load different classes.
Based on Notes/Domino version, Platform, Data Using one dynamic load function means you have to use the same signature on the class constructor
35
Dynamic Loading OO Example
Factory Request Log Configuration
User Create v5 User Create v6 User Create UI User Create Profile
36
Hang on you had a v5 class ?
Remember youre loading a class you decide at RUN TIME You can load separate classes depending on:
Version, Platform, Capability, User permission, Your data!
Different version classes can inherit from each other
So your version 6 class inherits from the version 5 class Or your AIX class inherits from your core class Only overrides the functions that need to be different.
Use Classes to do the work for you!
37
Compilation Woes
Expect Compilation Complexity. For instance, consider the fairly simple class structure
Agent 1 Agent 2 Agent 3 Agent 4
Routines:Examples Class Factory
Class PersonCollection Class Person
38
Compilation Woes
Change a subclass deep in the inheritance hierarchy and you Change a subclass deep in the inheritance hierarchy and you will probably: will probably:
See Server Console AMGR message or client dialog:
11/23/2004 12:03:03 PM Agent '(Blah)' error: 11/23/2004 12:03:03 PM Agent '(Blah)' error: Error loading USE or USELSX module: cl_event_v2 Error loading USE or USELSX module: cl_event_v2 Error %s Error %s Why ? The signature of the subclass has changed Why ? The signature of the subclass has changed How to resolve ? How to resolve ?
Tools, Compile all Lotusscript. Similar to Java. Most java IDEs will rebuild all when significant change is spotted.
Dynamic loading completely sidesteps this issue
39
Code Hiding
The Hide Design database property can sometimes be too restrictive. Should all of your commercial code be in script libraries, then:
Find the script librarys design document Find the script librarys design document Replace item ScriptLib with some text such as Replace item ScriptLib with some text such as MyName, 2004 MyName, 2004 The end-user cannot recompile the library and cannot The end-user cannot recompile the library and cannot see your code. see your code. Warning. No way back (obviously). So do this on your Warning. No way back (obviously). So do this on your BUILD copies of templates, not your development BUILD copies of templates, not your development templates templates
40
Agenda
Why use Object Orientated Methodologies? OO Basics in Script Demo OO application Directory Compare Extend or Encapsulate ? Large OO projects Pitfalls and Tricks Summary and questions
41
Summary
OO is a simple, pain-free way of building and maintaining large Domino Projects. OO should be part of your toolset during application design Lotusscript can do large, serious and complex OO projects
42
Related Sessions and Resources
Redbook: Performance Considerations for Domino Applications
Search for SG24-5602 at http://www.lotus.com/redbooks
Notes.net Article:
Using the object-orientated features of Lotusscript by Bruce Perry, from October 2001.
Dev.kaangard.net
http://dev.kanngard.net/dev/home.nsf/ArticlesByTitle/LSClass.html
OpenNTF
Check out OpenDom by Alain H Romedenne http://www.openntf.org
43
Related Sessions and Resources
Book: Code Complete 2, Steve McConnell, MS Press. Book: The Pragmatic Programmer, Addison Wesley Book: Understanding Object-Oriented Programming With Java Timothy Budd AD101 What 's New in Lotus Domino Designer? AD211 Leveraging the Power of Object Oriented Programming in LotusScript
44
Questions?
Please fill out your evaluations Remember you can ask me more questions in:
Toucan 2 for the next hour Guru-Pazoola in the Swan at 10:30am all Best Practices Speakers will be there. By sending me mail to Bill at BillBuchan.com
Check out our product iDM
http://www.hadsl.com
Thanks for coming!
45