博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理
COMBEST-DOMINO新手指南(开发工具、编码语言选择优化、内置对象、限制、错误处理等)

1.前言
  DOMINO是一个以电子邮件为基础发展起来的标准群件平台,从1982年开始发布第一个版本,至今已经有数十年的历史,正式注册用户过亿。
  它最大的优点就是提供了大量内置的如SMTP、POP、LDAP、HTTP、HTTPS等集成的系统服务,所以使用户快速构建跨平台的解决方案成为可能。
  整个平台由DOMINOSERVER(DOMINO服务器)、ADMINISTRATOR(DOMINO管理工具)、DESIGNER(DOMINO开发设计工具)、NOTES(DOMINO客户端)组成,在一些针对性应用方面还有LOTUS-WORKFLOW(DOMINO工作流设计系统)、LOTUS-DOMINO.DOC(DOMINO文档管理系统)、LOTUS-QUICKPLACE(DOMINO协作平台)、LOTUS-LEI(DOMINO数据交互系统)、LOTUS-LEARNINGSPACE(DOMINO培训系统)等强有力支持。

2.开发工具分析
2.1 帧结构集
  帧结构类似于HTML开发中的框架设计,帧结构集是帧结构的集合。帧结构是较大帧结构集的一个区段或窗格,并且可以独立滚动。通过使用帧结构集,设计者可以在帧结构之间创建链接使彼此相互关联。帧结构集可以在用户转向或链接到其他页面或数据库是仍然保持某个页面的显示状态。帧结构一般不采用3-D边框,边框宽度设为0。
2.2 页面
  页面是用来显示信息的设计元素。与收集信息的表单不同,页面主要用来向用户展示信息,因此用户不能在页面上创建任何字段或者子表单,但可以创建HTML控件。因此页面可以用所见即所得的HTML制作工具来进行开发设计。
   页面适用于静态信息或者作为其他元素的容器。可以使用页面作为用户应用的开始界面或者作为提交文件后的提示界面。
2.3 主表单
  表单是用于在数据库中输入和查看信息的载体。
  表单可以包含
  1)存储数据的字段   2)标注字段或者提供指示的文本  
  3) 存储用户想要在多个表单上使用的表单元素集合的子表单
4) 可以结合图形和字段的布局区域 它们所采用的方法可以提供更大的设计灵活性
  5)可以使表单更容易理解的图形   6) 汇总或者组织信息的表格
  7)对象 OLE 预定 Notes/FX(TM)字段 文件附件 URL 以及可以扩展Notes
  文档范围的链接
  8)可以自动执行函数的动作按钮
  9)可以强化文档外观的背景颜色和图形
  10)在表单中包含其他设计元素的嵌入式元素
  在应用上细分DOMINO系统中表单一般分为主表单和子表单,而主表单又分为数据存放表单和数据展现表单。
  其中数据存放表单一般的设计处理方式是数据字段设计在该主表单中,公共控制信息(如流转控制)设计成子表单(component)。再将该子表单加入到主表单中。确保整体设计结构清晰,在内容上主要包含的内容有:数据信息、按钮操作、用户界面、功能子表单等。
  而数据显示表单的设计处理方式是用于在浏览器中进行数据浏览的表单,为了保证界面的友好性,一般采用CSS定义整体风格。
2.4 视图
  视图是访问数据库中文档的入口,每一个数据库至少必须包含一个视图,基于所选择的准则,视图可以显示数据库的文档子集或者所有的文档。基于文档的内容,也可以对文档进行分组和排序。
  在创建视图的之前一定要:
* 视图有一个中文名称和一个英文别名,在代码中始终引用英文别名
* 视图的列样式、列头字体、颜色、大小在同一个数据库内应该统一
* 视图标题栏高度,行间距应该统一设定好,一般设定为1和1 1/4
* 如果视图需要分类折叠显示,要出现可折叠标记
* 视图上的操作应该出现在操作栏的左侧
* 视图应该行数应该使用交替颜色显示
* 视图列的最后一列应该扩展到窗口宽度
* 用户不直接查看的视图应定义为隐藏视图
* 如果视图要嵌入到页面,用于Web访问,则应该选定“在浏览器中使用小程序”
2.5 文件夹
  文件夹是用来存储文档的容器。文件夹与视图具有相同的外观,而且其设计方法也与视图大致相同。其区别仅在于应用的时候视图具有可以自动选择并显示文档的文档选择公式,而文件夹则不是,它是通过用户手动的添加来显示文档的。所以在设计的时候,其设计知道方法可以大致跟视图相类似。   
2.6 共享代码
2.6.1 代理
  代理Agent可以让用户在Domino中自动执行许多任务。它们是可以在数据库中为用户执行特定任务的独立程序。例如可以归档文档、改变字段值、发送邮件消息、删除文档或者执行与外部应用进行交互这样的功能更为强大的动作 。
  代理还能够进行设置在服务器上基于安排或者在出现特定事件时自行运行。
2.6.2 WEB服务
Web服务和Domino
  Domino 6是一个理想的应用程序,用于宿主或使用Web服务。由于Web服务主要是由XML数据组成。因为DOMINO目前有更多被设计用来特殊处理XML的LotusScript类,因此DOMINO对WEB服务有天生的好支持。
  也有一些有用的工具可提供对Domino里Web服务的附加的支持,它们是:
  对LotusScript的 SOAPConnect-这个工具包含了一个LotusScript库它允许您使用和宿主Web服务。
  MS SOAP工具包-由Microsoft 提供的允许Domino在Windows平台上使用或
宿主Web服务
    .NET-来自Microsoft 的一个工具集让您使用和宿主Web服务这个工具集可
Lotus Notes/Domino经由Common Object Model (COM)接口访问。
    以下的段落接着描述WEB服务的本质。Web服务可以被定义为一个应用程序它提供了一个API,以便将自己与其他应用程序集成在一起。Web服务的主要功能是提供过程到过程的交互作用而不需要用户界面,也就是说您可以通过与API接口远程调用这个应用程序,调用这个服务的应用程序被称为客户机程序。
  XML位于Web服务的核心并为描述远程过程调用Remote Procedure Call Web服务以及Web服务目录提供了一种公共的语言。
  Web服务这个短语有时可能会容易误解好像它意味着使用Web浏览器,然而并不总是这种情况,有许多不同的调用Web服务的方法例如一个HTTP请求或者来自另一个应用程序的一个电子邮件是其中的一些方法。
   调用一个Web服务的最常用的方法之一是通过发送一个HTTP Get 请求到API。经由Internet 访问API有许多优点,API可以被任何具有Web服务地址的全球客户机访问,Web 服务应用程序里的一个修改只需要在数据源完成,Web 服务可以以任何语言和在任何平台上书写,只要那些Web服务根据Web服务标准可访问,
为了使协同性有效,Web服务平台必须提供一个标准系统,该系统将与使用不同的平台和/或编程语言的系统有接口。
  一个Web 服务平台需要描述此Web服务并提供其他应用程序为了调用这个Web服务所需要的信息。构成Web服务平台的主要技术如下:
  XML-这是用于在Web服务平台上表示数据的基本格式
  SOAP-简单对象访问协议 (Simple Object Access Protocol) Web服务的远程过程调用(RPC)工具SOAP是一个传输协议,它使用HTTP POST请求来传输。方法所返回的响应是一个XML文档。
  WDSL Web服务描述语言Web Service Description Language-是一个基于XML的文法,它用于描述Web服务及其函数参数和返回值。
  UDDI-通用描述发现和集成(Universal Description, Discovery, and Integration)
  一个基于XML的目录它表示一种技术规范用于发布和发现业务和Web服务。


2.6.3 大纲
  每个数据库都需要一种方法进行导航。可以利用大纲设计起来创建大纲,给用户提供一个自动链接,具有个人风格的站点导航图。大纲可以包含背景图形、定制图标、链接或者操作。
  所以在设计大纲的时候,对大纲采用的大纲项图标,以及大纲项所采用的字体,字号,颜色,mouseover的颜色等都要事先定制,颜色,图标采用不一定要相同,但是应该在保证风格统一,并且与整体界面没有冲突的前提下,体现出各自的特点。大纲项与大纲都应该采用别名的形式,在程序调用中调用英文别名
2.6.4 子表单
   子表单 subform是用户可以在多个表单中使用的表单片段。例如用户可以在子表单中建立公司的信头,然后在各种商业表单中使用这个子表单。
   子表单能够包含与常规表单相同的元素, 可以基于公式在表单上加载子表单。
2.6.5 共享域
    共享域类似于字段,但是可以在不同的表单中使用,如果用户改变共享域的属性,那么这些改变就会应用于所有出现这个字段的场合,他的主要作用是域进行一次定义而后重复使用。便于设计改动时的工作。  
2.6.6 自动化组件
  向应用程序中添加自动功能可以加速执行重复任务、路有文档、更新信息、执行计算、运行程序以及检查错误的自动化组件:
* 操作按钮
  通过点击它们,可以使某些任务得以自动完成。特别是对于Web浏览器用户,需要使用操作来模拟Notes菜单项。
* 热点
  热点是用户单击后可执行操作、运行公式或Script以及转向链接的文本或图片。热点是可以到另一个Web站点、数据库或数据库元素的链接,还可以是按钮、弹出式文本或公式以及操作。
2.6.7 共享操作
  共享操作是在表单或视图中设置用户激活的任务。共享操作的设计位置虽然与操作不同,但是设计方法两者没有什么区别,对操作设计的一些规定,在此同样适用。
2.6.8 SCRIPT库
   脚本库是集中存放共享代码的位置具体可包含LotusScript、JavaScript以及Java库。
2.6.9 导航器
  导航器是用户能够包含可以用于导航的可编程区域和热点的图形。热点通常可以指示用户前往数据库或者Web站点的另外部分。但是总的来讲,导航器是NOTES 4.X版本的产物,是一项过时的技术,所以在开发的时候不再建议开发人员使用导航器,而去使用页面嵌入大纲来对应用进行导航。
2.6.10 层
  层layer这种设计元素不能在数据库级别建立,而是要在页面表单或者子表单中建立。层可以让用户在页面表单或者子表单上放置重叠的内容块,因为用户能够控制信息的位置大小和内容。所以层能够让用户进行灵活的设计,用户能够建立和堆砌多个层使其彼此交错。透明层可以展现其下的层不透明的层可以隐藏其下的层。 层的内容要依赖于用户要在页面还是表单上建立层,当用户在页面上建立层的时候层就可以包含与页面包含内容相同的元素,例如用户能够增加文本和图形等内容;当用户在表单上建立层的时候层就能够包含与表单包含内容相同的元素例如用户能够增加文本和图形 以及受控的访问部分 字段和子表单
2.6.11  DXL  
   Domino数据的XMLExtensible Markup Zarauage可扩展标记语言表示称为DXL。
DXL可以描述特定于Domino的数据以及嵌入式视图表单和文档这样的设计元素。随着XML成为交换信息的标准基础,DXL也为将数据的XML表示导入和导出到
Domino应用提供了基础。利用DXL实用工具用户就能够查看和导出用户的Domino设计元素,用户还可以使用转换器Transformer实用工具和XSL样式表单文件将其转换为另外的格式,XSL文件包含了针对XML数据的格式  

3. 开发要点编码语言以及代码优化分析
3.1 编码语言的选择
在具体的开发过程中,根据需求性质,DOMINO可以有多种编码语言的选择。
主要有公式、lotusscript、java、javascript语言,比较起来,特别简单的功能和逻辑,用公式实现比较快;复杂的功能和逻辑,用lotusscript比较快。
java语言可以实现多线程,完全面向对象,处理大量文档时,如果程序利用
到多线程,比不能利用多线程的lotusscript快。
另外针对于底层开发,LOTUS还有专门的Toolkits支持:
  按Lotus产品系列来分,Lotus提供下列产品的工具包: Notes/Domino 、Sametime 、QuickPlace 、Discovery Server 、Other。
  其中,Notes/Domino和Sametime的工具包比较多,C、C++、Java语言的都有,其他产品的则很少。从这个角度,也可以看出文档数据处理、协同工作是Lotus系列产品的核心价值所在。其中,Notes/Domino的工具包有:
Lotus C API toolkit Lotus            C++ API toolkit
Lotus Domino Toolkit for Java/CORBA  Lotus and Notes Toolkit for COM
Lotus Domino Driver for JDBC (简称LDDJ)  NotesSQL
Lotus XML Toolkit(简称DXL) Custom Tag Converion kit(简称DCT)
LotusScript Extensions toolkit(简称LSX)
   在Domino/Notes的Toolkit中,C API的功能最为强大:可以操纵notes数据库中几乎所有的数据对象:数据库及ACL、文档和域、表单、视图和文件夹、代理、可以为Notes客户端的增加附加菜单、可以用来创建附加的Domino服务任务、可以用来扩展Domino/Notes的事件管理。
而其主要限制如下:
  不能修改已有的Domino/Notes软件,不能去除其已有的功能、特性,或者改变其工作机理、不能修改安全特性、不能修改用户活动记录
    支持的操作系统: WindowsNT/2000, Linux, Solaris SPARC/Intel, HP-UX, MacOS, AIX, AS/400, S/390等。
3.2 编码优化原则
1)公式语言优化
1.使用@ClientType代替@UserRoles来检查客户端类型
   从R4.6开始,不必使用@UserRoles中的$$WebClient来检查客户端是否使用浏览器,直接使用@ClientType比较快
2.使用简单的公式隐藏条件比较快
  以下三种写隐藏的选择,性能递减。可以利用第一个,不要写判断@ClientType的公式;可以利用编辑模式,不要写判断@isdocbeingedited的公式
   a.根据客户端程序类型   b.根据编辑模式   c.根据公式隐藏
3.在@dblookup和@dbcolumn公式中使用列号比使用域名快
  使用域名需要在域列表中对比,但直接使用列号会带来维护的困难。
4.打开@dblookup和@dbcolumn的cache开关
  cache不但可以使这个公式执行更加快,而且可以使‘同一个数据库’中,‘同样公式’的另一个lookup运行更快。cache是基于数据库的,不同数据库的相同lookup不能利用相同的cache。注意:无论是否打开cache,lotusscript调用evaluate的lookup都不能利用cache。
5.根据4,如果公式和lotusscript都要利用相同的lookup结果,可以将信息放到profile文档中。
6.要lookup一个包含很多文档的视图时,创建一个隐藏视图,仅包含必要的列。视图越小,越快。
7.如果要取视图中的几个列,分别取的话,每个lookup都要花时间。将几个列组合成一个列,用特别的字符分隔,一次取出来,然后分析出几个域。
8.一段公式中,数次利用同一个结果集,用临时变量保存,而不是每次重新取
9.使用不同的搜索方法,如果处理的文档集较小(例如少于数据库中所有文档的15%),使用lotusscript比公式快,如使用getview , search, ftsearch等方法。
10.使用‘显示时计算’域来避免不必要的重复计算。下表是使用各种类型域时,不同事件引发的计算情况:
Field    Create    Open      Open         Show      Save     Refresh
Type               (empty)   (data)      Dialog
Edit     DV                                          IT,IV   IT IV
(normal)
Edit     DV                   KF           KF        IT,IV   IT IV
(K-UF-DB)
Edit     KF,DV      KF        KF                     IT,IV   IT IV
(K-UF-Not DB)
Computed  V                                          V       V
Computed for
display   V          V         V                     V       V
Computed for
composed  V
上面缩写的解释
normal----Normal edit field (not one of the two special ones that follow)
K-UF-DB---Keyword, Use formula for choices, dialog box
K-UF-Not DB---Keyword, Use formula for choices, check boxes or radio buttons
DV   -----Default value formula executes
IT   -----Input translation formula executes
IV   -----Input validation formula executes
KF   -----Keyword formula executes
V    -----Value formula executes
Create----Field is being created (either because the document is being created
or an existing document is opened that does not contain the field)
Open -----Opening an existing document — in either Read or Edit mode
Empty---Field is empty (exists in document but has no contents)
data-----Field has data
Show Dialog---User presses the icon to display the dialog box
注意两点:
1.使用check box和radio box,一打开文档,公式总要计算,即使仅仅打算阅读而不是修改文档,看起来是合理的,因为需要计算出各个项目供阅读嘛
2.已经有数据的,使用对话框格式的编辑域,打开时候也要重新计算,这个就不太合理了。
   当使用复杂的@dblookup时,性能有很大影响。隐藏公式域没有作用,因为仍然会发生计算。按照下面方法解决
1)创建一个隐藏的多值‘显示时计算’域:kwDataHidden,计算公式是原来的@dblookup公式,但仍然要做如下处理,值公式写成这样:
   rem "Do not run formula during doc save";
   @if (@IsDocBeingSaved; @Return("");"");
   rem "Only run if doc is in edit mode";
   @if (@IsDocBeingEdited;@DBColumn(............);"")
2)在表单的PostModeChange中,写:@If(@IsDocBeingEdited;@Command([ViewRefreshFields]);""),(实际上,如果觉得公式的值的修改频率不是太快的话,这里也可以不写)
3)真正操作那个域的公式写:kwDataHidden;并且该域属性选择‘刷新文档时刷新选项’。
2)脚本语言优化
1.使用For loop,不使用Do loop 或者 while loop的循环
  前者比后者快60%(不计算循环内部时间的情况下)
2.引用数组元素的时候,使用Forall比for快
  一维数组,前者快75%,二维以上,也可以快50%
3.简化if语句
  lotusscript不会象c那样进行逻辑语句优化,所以
    If a=x and b=y then
    应该写成
    If a=x then
       if b=y then
    后者快40%
4.避免混合变量类型(计算)(也就是不要隐式造型)
    dim a as single
    dim z as long
    z = 3
    a = 1.0
    z = z+a
    上面这一段使用了implied casting,z=z+(long)a会比较快
1.对整数结果,使用整数除法:z& = x& \ y& 比 z& = x& / y& 快60%
2.仅在有必要的时候才使用variant类型,lotus使用更多的时间处理variant
3.读取文件的时候,一次读取一块,而不是一行,下面的例子A比B快接近5倍!而且读取的文件越大,越明显。
    example A
Open fName$ for input as #fNum
buff$ = Input$(Lof(fNum),fNum)
stPos = 1
lineNo = 1
eoFile = false
While Not eoFile
  nlPos = Instr(stPos,buff$,Chr$(13))
  If (nlPos) > 0) then
    fData$(lineNo) = Mid$(buff$,stPos,nlPos - stPos)
    stPos = nlPos + 1
  else
    fData$(lineNo) = Mid$(buff$,stPos)
    eoFile = true
  end if
  lineNo = LineNo + 1
wend
close #fNum
   
    example B
Open fName$ for Input as #fNum
lineNo = 1
while Not Eof(fNum)
  Line Input #fNum , fData$(lineNo)
  lineNo = lineNo + 1
wend
close #fNum
注意,R4.6以及之前的版本,string变量有64k的限制,所以一上例子a需要再增加一些东西(不能一次读取,而是要分次读取文件),但块读取的好处仍然是显而易见的。R5开始,string变量可以最大达到2G,足够读取非常大的文件了。例子A虽然增加了代码量,但是可以大大加快速度,某些场合非常有用
5.避免无谓地使用数组,下面例子A比例子B快两倍
Example A
For i = 1 to 100
  sum = sum + x(i)
Next
t(1)=sum
Example B
For i = 1 to 100
  t(1) = t(1) + x(i)
Next
Domino R5引入了新的数组处理函数:ArrayAppend , ArrayGetIndex , ArrayReplace , FullTrim,使用这些函数比自己写相同的功能快
6.有一个不使用字符串数组的替代方法
  把所有数组中的字符串元素构造成一个字符串,用特殊分隔符分开(例如回车符),然后用  Instr  来取各个元素
7.优化字符串的处理
  字符串的处理非常消耗资源,例如下面这句很常见
X$= X$ & "a"
这个语句非常消耗资源(java中有类似现象,因为涉及到重新生成字符串),下面这句缩短字符串也是很消耗资源的
x$ = Right$(x$ , currentLength% - lengthStrippeddOff%)
8.创建一个新的字符串有时候更加快
下面例子A比B快25%
A
str$ = stringA$ & stringB$
B
str$ = stringA$
str$ = str$ & stringB$
9.反复处理字符串时,记住处理位置
  比不断修改字符串长度快(其实是不断生成新的字符串),下面例子A比B快85%
A
strPiece$ = Mid$(str$ , startPos% , pieceLength%)
startPos% = startPos% + pieceLength%
B
strPiece$ = Left$(str$ , pieceLength)
strLength% = strLength% - pieceLength%
str$ = Right$(str$ , strLength%)
10.谨慎是用redim命令
   可以理解,每次redim,是内存堆数据的乾坤大挪移,所以尽可能事先决定数组大小。实在没有办法,也千万不要在循环中redim。以下例子A比B快20%
A
For i = 1 to 10000
  If ( i> iMax) then
     iMax = iMax + 100
     redim Preserve sArray(1 to iMax)
  end if
  sArray(i) = ""
Next
B
For i = 1 to 10000
  Redim Preserve sArray(1 to i)
  sArray(i)=""
Next
以上实际是减少redim的次数,每次增加多些,循环后可能还需要一次redim,让数组空间和实际一致
11.在多维数组中循环
  应使用正确的顺序。在外循环中操作后面的维数,在内循环中操作前面的维数(这个最奇怪了,估计跟数组的内存排放有关),下面的例子A比例子B快400%!(实际测试,500的PIII,看不出差别,都很快,当我再想增大数组元素个数的时候,宣称已经超过32K限制了,faint!看来意义不大)
A
For y = 0 to 2
  for q = 0 to 5000
    z = z + x(q,y)
  Next
Next
B
For q = 0 to 5000
  For y = 0 to 2
    z = z + x(q,y)
  next
next
12.比较整数,而不是比较字符串
下面的例子A比例子B快50%,例子C比例子D快30%
A  If(Asc(x$) = Asc("A")) then
B  If(Left$(X$,1) = "A") then
C  If(Asc(Mid$(x$ , 1, 1) = "A") then
D  If(Mid$(x,1,1) = "A") then
下面比较空串的例子E也比例子F快30%
E  If (Len(x$) = 0) then
F  If (x$="") then
13.将数字转为字符串的时候使用自动造型,不用手工转换
   例如 s2$ = "Text" & iNum 比s2$="Text & Cstr(iNum%) 稍微快一点,不过不明显。
14.重要:避免过多使用环境变量
   环境变量要读取notes.ini文件,对性能造成影响,替代办法是使用profile。如果一定要使用环境变量,将多个环境变量合并成一个,用特殊符号分隔,取出来后再分析成多个。取10个单独的环境变量要比取一个长的环境变量多花10倍时间!
3)Java & JavaScriptino应用程序优化
   Java需要装入JVM,client端第一次运行的时候装入,server端,随着http装入的时候装入(所以不用http就不要装入了,估计慢也是受到jvm影响   )有关java没有什么好说,就说两点。
1.将需要的java类,尽可能放在类列表前面,尽可能接近base类,可以加快搜索速度
2.周期性调用回收函数,java本身是自动进行垃圾收集的,但是该书的意思似乎说java的垃圾回收,不能回收相关lotus objects用掉的内存
3.Javascript,没有什么好说的,用于web页面,域校验,和输入转换,可以避免browser和web server来回交换数据,减少网络流量
4)DOMINO对象模型优化
 利用后期初始化和对象重用技术来最大限度地利用资源
1.后期初始化(lazy initialization)。学习到一定地步的lotus程序员,为了程序结果清晰,往往喜欢事先将一些对象如db , view , doc等初始化,然后每个函数都可以使用。从提高效率的角度,可以改进为使用后期初始化(自己翻译的,不知道是否准确,应用期初始化?),下面是后期初始化的方法
' *** Globals
' *** Declare the global data we share
Public gDb As NotesDatabase
Public gVwCustomerType As NotesView
'*** Functions
'*** Get the customer type view (lazy initialization)
'*** Do account validation
Sub Initialize
'*** Set up the database (NOT lazy)
Dim ss As New NotesSession
Set gDb = ss.CurrentDatabase
End Sub
Function GetCustomerTypeView() As NotesView
'*** Only get it the 1st time it is used
If (gVwCustomerType Is Nothing) Then
  Set gVwCustomerType = gDb.GetView("Customer Type")
End If
Set GetCustomerTypeView = gVwCustomerType
End Function
Function ValidateAccount(custName As String, _
accountType As String) As Integer
'*** Return True if account is valid
Dim vw As NotesView
Dim doc As NotesDocument
Dim aKeys(0 To 1) As String
Select Case AccountType
Case “New”
'*** New accounts are always valid
  ValidateAccount% = True
Case Else
'*** Is customer allowed the specified account type?
  Set vw = GetCustomerTypeView()
  aKeys(0) = custName$
  aKeys(1) = accountType$
  Set doc = vw.GetDocumentByKey(aKeys, True)
  If (doc Is Nothing) Then
   ValidateAccount% = False
  Else
   ValidateAccount% = True
  End If
End Select
End Function
以上GetCustomerTypeView函数中使用了lazy initialization方法,当该函数第一次被调用,它调用getview取得视图,以后只要直接取public的vw即可,其他程序的结构不会受到影响(如果将全局变量的vw封装在class中,则更加符合面向对象的规则)
5)最大限度重用对象
1.打开数据库时的动作
   a.创建数据库,涉及到内存分配和初始化
   b.定位数据库,涉及到目录查找,或者存取其他服务器
   c.初始化对象属性,需要从数据库读取ACL等属性
由于打开数据库如此耗费资源,所以应该尽量重复利用打开的db,作为参数传递,或者全局变量(或者类变量)而不是在每个函数中重新打开。
2.使用已有对象,比较下面,A比B快
A
dbTitle$ = doc.ParentDatabase.Title
B
set session = new NotesSession
set db = session.CurrentDatabase
dbTitle = db.Title
3.使用back-end类,比用front-end类快,并且back-end类可以添加任何数据类型和新域
4.使用NotesUIDocument类时,如果需要大量修改文档域,禁止AutoReload属性
修改前:source.AutoReload = false
修改后:source.AutoReload = true
        source.Reload
5.如果从视图存取文档,使用 ColumnValues访问域,比直接访问要快,但只有从视图存取文档才能利用这点,还有就是要注意columnNumber这个列数的计算,呵呵,很讨厌的,不是视图上的每个列都算在里面
A
var = doc.ColumnValues(columnNumber%)
x   = var(0)
B
x =doc.fieldname

4。所有内置对象分析  
4.1 内置变量
类型
命名规则(前缀)
说明
NotesSession
Session
NotesDataBase
Db
NotesView
View
NotesViewEntryCollection
Vec
NotesViewEntry
Entry
NotesViewColumn
Column
NotesACL
Acl
NotesACLEntry
Acle
NotesAgent
Agt
NotesDateTime
Dt
NotesDbDirectory
Dir
NotesDocument
Doc,cdoc
Cdoc表示当前文档
NotesDocumentCollection
Dcc
NotesEmbeddedObject
Embobj
NotesItem
Item
NotesRichTextItem
Rt
NotesForm
Frm
NotesRegistration
reg
string
str
integer
N或i
4.2 内置表单
1. $$ViewTemplate for +视图名称.
?? $$Search;$$NavigateTemplate for;$defaultView;$defaultForm、$defaultNav、$searchForm、$file、$icon、$help、$about 和 $first
2. $$ViewTemplateDefault
?? 在Notes的WEB编程中,使用命名为『($$ViewTemplateDefault) | $$ViewTemplateDefault』的表单可以为Notes数据库提供一个缺省的WEB导航格式。
3.$$ReturnDocumentDeleted
? 定义WEB上文档被删除后的提示信息
4.$$ReturnAuthenticationFailure
?? 用户名称和口令验证失败后的提示信息表单.
5.$$ReturnAuthorizationFailure
?? 当用户对数据库的访问权限不够时提示信息.
6.$$ReturnGeneralError
?? 一些其他的错误发生时提示信息.
7.$$SearchTemplateDefaultForm
? 数据库在WEB上的缺省搜索表单名称
另外针对视图的查询搜索增加如下内容:可以定制针对某个视图的查询显示表单,如:DBName:=@Subset(@DbName;-1);
"[[/"+dbname+"/(searchview)?Searchview&Query=("+Query+") &Start=1&SearchOrder=1&SearchMax=10000]]" 中,指定了在视图(searchview)中查询,如果首先定制form表单:$$SearchTemplate for(searchview),则会自动调用该form显示,如果没定制,则调用默认的搜索显示表单$$searchTemplateDefault;
4.3 内置域
  Form-表单名;SendTo-发件人;Subject-发件主题;
  SaveOptions
  如果是0则文档不保存,默认是1;
  MailOptions
  如果是1,则文档关闭时要被邮寄,默认是0
  $$Return
  WEB下提交页面的返回内容
  $$HTMLHead
  表示页面HEAD的内容,
  $$HTMLBody
  表示页面Body的属性
  $Anonymous 1
  表示此文档是由匿名表单创建的匿名文档
  $GroupScheduleShowLegend 1
  安排群组日程时,决定是否显示图例
  $PublicAccess 1
  文档中包含此域表示允许为公共访问文档
  $$WebClient
  如果是WEB浏览器用户,则自动包含在@UserRoles中
  Auth_Type
  如果服务器支持用户验证而且 Script 被保护,这是用于校验用户的特定协议的验证方法。
  Content_Length
  内容的长度,与客户机给出的相同。
  Content_Type
  对于带有附加信息的查询,比如 HTTP POST 和 PUT,这是数据的内容类型。
  Gateway_Interface
  服务器所遵守的 CGI 规范版本。
  HTTP_Accept
  客户机接受的 MIME 类型,通过 HTTP 标题指定。
  HTTP_Accept_language
  客户机接受的语言,通过 HTTP 标题指定。
  HTTP_Referer
  用户经常访问的页面的 URL 地址。
  HTTPS
  指示服务器是否启用 SSL 模式。
  HTTPS_CLIENT_CERT_COMMON_NAME
  x.509 验证字上的公共名称
  HTTPS_CLIENT_CERT_ISSUER_COMMON_NAME
  x.509 验证字的发行者
  HTTPS_KEYSIZE SSL 会话过程中的会话密钥
  例如:40-bit、128-bit。
  Path_Translated
  服务器提供 PATH_INFO 的翻译版本,它获得路径并能对其进行从虚拟地址到物理地址的任何映射。
  Query_String
? 后的信息,或在某些情况下是引用此 Script 的 URL 中位于 !* 后的信息。
  
  Query_String_Decoded
  返回值与 Query_String 相同,但是将字符串解码。例如:如果 URL 引用了一个包含不允许出现在 URL 中的字符的视图名称,此名称会被编码。此 CGI 变量将字符串解码。Path_Info_Decoded 仅对于 Domino 应用程序可用。
  Remote_Addr
  发出请求的远程主机的 IP 地址。
  Remote_Host
  发出请求的主机名称。
  Remote_Ident
  此变量会设置为从服务器提取的远程用户名。仅登录时使用此变量。
  Remote_User
  返回被验证用户名的验证方法。
  Request_Content
  仅由代理支持。包含使用 HTTP POST 请求发送的数据。此数据经常是“URL 编码的”,由用“&”连接的 name=value 对组成。例如: FirstName=John&LastName=Doe
  Request_Method
  用于发出请求的方法。对于 HTTP,是“GET”、“HEAD”、“POST” 等等。
  Script_Name
  到被执行的 Script 的虚拟路径,用于自引用的 URL。
  Server_Name
  服务器的宿主名称、DNS 别名或 IP 地址,将出现在自引用的 URL 中。
  Server_Protocol
  与请求同时出现的信息协议的名称和修订。
  Server_Port
  发送请求的端口。
  Server_Software
  运行 CGI 程序的信息服务器软件的名称和版本。
  Server_URL_Gateway_Interface
  服务器遵守的 CGI 规范的版本。
  $Readers
  如果设置了表单的读者权限,则在文档中会出现这个域
  $FILE
  如果文档包含附件,则会出现这个域,RTF包含附件,不会出现
  $$ViewBody
  在web下嵌入视图
  $KeepPrivate
  为1时文档不可拷贝、打印、转发
  $V2AttachmentOptions
  此值如果设置为0就可以隐藏表单中的附件
  $VersionOpt
  控制记录文档的版本
  FolderOptions
  在文件夹中放入新文档
  SecretEncryptionKeys
  使用密匙加密文档不是公共密匙而是加密密匙
  HTML
  将HTML直接传递给浏览器
  Versioning
  本字段规定用户是否想要进行版本控制时可以使用如下选项 None、New versions become responses。当最初版本最为重要的时候可以使用这个选项在视图中会首先列出最初的文档。
  Prior versions become responses  当新版本最为重要的时候可以使用这个选项;
  在视图中会首先列出最新的版本 New versions become siblings,当所有版本同样重要的时候可以使用这个选项,在视图中会首先列出最初的文档。然后所有随后的版本都会作为附加主文档紧随其后进而避免重复或者冲突,但如果用户决定要进行版本控制。
  那么这里可以有两个创建版本选项  Manual-File, New Version可以在用户选择FileSave as New Version的时候立文档的新版本   Automatic-File, Save可以在每次用户保存文档的时候 建立文档的新版本。

5、 已知限制
数据库的最大大小是多少?
最大的 OS 文件大小限制 -(最大为 64GB)
文本域的最大大小是多少?
15KB(存储);15KB,显示在视图列中
RTF 文本域的最大大小是多少?
仅由可用磁盘空间限定,最大为 1GB
RTF 文本域中单个段落的最大大小是多少?
64KB
一个层次结构视图中有几级响应;每一级中有几个文档?
31 级;300,000 个文档
视图、表单等的名字最多允许包含多少个字符?
数据库标题:96 个字节
文件名:在 Windows 和 Unix 平台上的最小限制为 255 和/或由操作系统限定; 本地的 Macintosh 工作站上为 31
域名: 32
视图名: 64
表单名: 32
代理名: 32
一个数据库中可包含多少个域?
t3000(所有域名的总长度限制在 t64K)。可以启用数据库属性“允许数据库中包含多个域”以使得数据库中的唯一命名域可到达 64K。
一个表中可包含多少列? 64
一个表中可包含多少行? 255
可以向一个数据库中添加多少视图?
没有限制;不过,随着视图数目的增加,用于显示其他视图的时间也会增加
可以向一个数据库中添加多少表单?
仅受数据库大小限制。
一个视图中允许有多少列?
289 个 10 字符列;取决于 # 或每列的字符数
可以向一个视图中引入多少文档?
文档合计至少为 350K
一个数据库中可允许有多少个层叠视图? 200
可输入的页边距的最大值(以英寸计)为多少? 46
可输入的页面裁减尺寸的最大值(以英寸计)为多少? 46
可选择/打印的最大字号是多少? 250
一个视图中允许有多少文档?
一个视图索引最大可为 130MB
最多可向“制表文本”中引出多少个文档?
仅受可用磁盘空间限制
一个“存取控制列表”中最多可有多少个项目?
t50 个名字(“存取控制列表”的大小不能超过 32767 字节)
一个“存取控制列表”中最多可有多少个角色? 75 个角色
可允许的标识符最大口令长度为多少? 63 个字符
对于一个多口令标识符,最多可有多少个用户拥有授权口令? 8 个用户
全文索引引擎的保留字
Topic,AND, NOT, OR, CONTAINS, NEAR, ACCRUE, EXACTCASE, TERMWEIGHT, PARAGRAPH, FIELD, SENTENCE.
如果想要绕开此限制,可以通过添加统配符的方式. 例如,如果想搜索"Topic"这个词, 可以添加一个"*"号, 即"Topic*". 或者把这个词用双引号括起来。

  
6。 Domino CGI变量
  公共网关接口CGI是外部应用与HTTP服务器进行交互的标准,当Web用户保存文档或者打开已有文档的时候Domino Web服务器就会使用CGI变量收集用户信息包括用户名称 浏览器 用户的Internet协议 IP 地址。
  为了在Web应用中收集这些信息 用户可以采用以下两种选择1)使用与CGI变量相同的名称建立字段2)使用LotusScript代理  
Domino所支持的CGI变量表
  Domino可以通过字段或者LotusScript代理获取以下CGI变量用户还可以通过HTTP或者HTTPS提前获取CGI变量。
Auth_Type
如果服务器支持用户认证并且可以保护脚本那么这个变量就是可以用于验证用户的特定于协议的认证方法
Content_Type
对于那些具有附加信息的查询例如HTTP POST和PUT这个变量就是数据的内容
Content_Length
由客户所提供的指定内容的长度
Gateway_Interface
服务器用来进行编译的CGI规范版本
HTTP_Accept
由HTTP头信息所规定的客户所能够接受的MIME类型
HTTP_Accept_language
由HTTP头信息所规定的客户所能够接受的语言
HTTP_Referer
用户用来在这里获取页面的URL
HTTPS
指出是否能够为服务器使用SSL模式
HTTPS_CLIENT_CERT_CO
x.509凭证上的公共名称
MMON_NAME
HTTPS_CLIENT_CERT_ISS  x.509凭证的发出者
UER_COMMON_NAME
HTTPS_KEYSIZE  SSL会话期间的会话键大小 例如40位128位
HTTP_User_Agent
客户用以发送请求的浏览器
Path_Info
由客户提供的额外路径信息相对服务器的HMTL根目录,换句话说是可以通过脚本的虚拟路径名称以及紧随其后作为PATH_INFO发送的额外信息访问脚本
Path_Info_Decoded
返回与Path_Info相同的信息但是会解码字符串例如如果URL所引用的视图名称包含了URL所不允许的字符那么就要对这个名称进行编码 这个CGI变量将会解码这个字符串,Path_Info_Decoded 只能够由Domino应用使用
Path_Translated
服务器可以提供PATH_INFO的经过翻译的版本它将会获取路径并且进行虚拟与物理之间的映射
Query_String
在引用这个脚本的URL中 紧随问号之后的信息
Query_String_Decoded
返回与Query_String相同的内容只是对字符串进行解码例如如果URL所引用的视图名称包含了URL所不允许的字符那么就要对这个名称进行编码 这个CGI变量将会解码这个字符串,Query_String_Decoded只能够由Domino应用使用
Remote_Addr
进行请求的远程主机的IP地址
Remote_Host
进行请求的主机名称
Remote_Ident
这个变量将会设置为从服务器所获取的远程用户的名称使用这个变量,只能够用于日志记录
Remote_User
返回经过认证的用户名称的认证方法
Request_Content
只用于代理包含随HTTP POST请求发送的数据数据通常采用URL编码 由使用&符号连接的名称=值对构成 例如FirstName=John&LastName=Doe,Request_Method  能够用于进行请求的方法 对于HTTP 这个方法可以是GET、HEAD或者POST等
Script_Name
正在执行的脚本的虚拟路径用于自引用URL
Server_Name
服务器的主机名称DNS别名或者IP地址它会出现在自引用URL中
Server_Protocol
这个请求使用的信息协议的名称和修订版本
Server_Port
请求所发送到的端口
Server_Software
运行CGI程序的信息服务器软件的名称和版本
Server_URL_Gateway_
服务器进行编辑的CGI规范的版本

7。 出错处理
在Web开发中,公式必须用异常处理方式保护代码
@IsError,特别是涉及DBColumn和DBLookup的地方
7。1 异常处理
所有过程或函数都需要提供完整的异常处理,以便于出现错误时的排除,原则
上只有涉及到非本系统模块时需要屏蔽错误,如和RTX接口,和硬件接口等情况。
在整个代码Declarations块中声明数据库常量
Const DATABASE_NAME = “test.nsf”’ 为了防止代码的互相调用,可以添加前缀,如COMMON_DATABASE_NAME
在所有过程(或函数)的代码描述以后,直接声明一个常量,最后为异常处理代码
Const FUNCTION_NAME = "Initialize"
  On Error Goto EHandle
  ……
  Exit Sub(Function)
  EHandle:
   Msgbox DATABASE_NAME + "-" + FUNCTION_NAME + "-" + Error + "-" + Cstr(Erl)
  End Sub(Function)
结果示例:
test.nsf-Initialize-Object is not set-19
原则上不推荐使用Print显示异常信息,此结果只针对开发者有用,只有需要进行页面跳转时使用print
4.6  为 Web 定制“表单已处理”确认信息  
  Web 用户提交文档后,Domino 使用缺省的“表单已处理”的确认信息回应用户。要重新设置缺省答复,可将计算文本域添加到表单中,给此域命名为 $$Return,并使用 HTML 作为计算值来创建定制的批准。
显示个人化答复
下面的 $$Return 公式返回答复“Thank you”,并附加上用户姓名:
who:= @If(@Left(From; " ") = ""; From; @Left(From; " "));
@Return("<h2>Thank you, " + who + "</h2><br><h4>
<a href=/register.nsf/Main+View?OpenView>Main View</a>");
7.2 显示定制的错误消息
  要定制显示给 Web 用户的错误消息外观,向数据库中添加定制的错误消息表单。如果发生错误条件,且其定制表单存在,则 Domino 使用定制表单来显示错误消息。否则,Domino 使用缺省错误消息表单。添加到数据库的消息表单将覆盖由管理员设置的服务器范围内的消息。
  要在表单和错误条件之间创建关联,创建拥有下列名称之一的表单。然后创建名为 MessageString 的可编辑的文本域来保存错误消息。添加要与错误消息一起显示的其他文本、链接以及其他表单对象。
$$ReturnAuthenticationFailure 不能校验用户名称和口令。
$$ReturnAuthorizationFailure 用户对该数据库没有足够的存取级别。
$$ReturnDocumentDeleted 成功删除文档。
$$ReturnGeneralError 出现了其他错误条件。
链接到另一页面
根据提交文档中的域值,在 HTML 中包括链接到另一页面的 URL。下面的 $$Return 公式根据用户选择的范围返回答复。例如:如果用户选择欧洲,则消息“在意大利访问我们的站点”将显示一个链接,可链接到意大利的 Web 站点(假定公式中的“stdAnswer”和“stdFooter”已预先定义。)。
@If(Region="Asia"; stdAnswer + "<h2>Visit our site in <a href=\"<A href='http://www.japan.lotus.com\">Japanhttp://www.japan.lotus.com/\">Japan</a></h2>" + stdFooter;
Region="Europe"; stdAnswer + "<h2>Visit our site in <a href=\"<A href='http://www.lotus.com\it_ciao/it_ciao.htm\">Italyhttp://www.lotus.com/\it_ciao/it_ciao.htm\">Italy</a></h2>" + stdFooter;stdAnswer + stdFooter);
返回另一页面
要跳转到不同的 Web 页面,可将页面的 URL 用括号括起来放入页面。当用户提交文档时,Web 客户机将显示引用的文档。例如:下面的 $$Return 公式显示 Lotus 日本站点的主页。"[
http://www.japan.lotus.com]"
7.3 定制未找到文档提示消息
1)在onload事件执行如下函数即可
function delstr()
{
var obj = document.getElementsByTagName("h2");
for (var i = 0; i < obj.length; i++)
{
  var getstr=obj
.innerText;
  if (getstr.indexOf("未找到文档")!=-1)
  {
    getstr=getstr.replace("未找到文档","你要想换的字样")
    obj.innerText = getstr;
  }
}
}
这种方法必須要在页面下载完后才能执行,如果网络太慢就不太好了.
2)在表单打用样式表
h2{display:none}
这种方法无法屏蔽表格< td>中产生的未找到文档字样
3)在标签中加一个< tr>< /tr>不完整标签
使未找文档放于< tr>未找文档< /tr>之间
这种方法会产生一条细线
4)在表单中使用@Elements(@DbColumn)公式来取得符合条件的文档数
并根据是否为0来隐藏视图或显示你定制的语句.

7.4 所有数据提交时的数据校验
强制规定校验函数必须为CheckValue(),必须在对应表单的OnSubmit中添加
Return CheckValue ();

8.安全性规则
8.1 基于ACL的安全控制
区段存取
许多文档中的数据有不同的敏感性你可能希望某些用户不能更新或阅读文档中的某些内容而另外一些用户则可以完全控制达到这个目标的一个方法就是将文档分成不同的区段 并且对区段施加区段存取控制。
ACL权限分析
No Access不能存取者
根本不能够访问此数据库,根本不能进行复制;
Depositor存放者     
可以创建文档但不能够阅读编辑或删除包括自己创建的文档在内的所有文档     不能接收到变化;
Reader 读者
能够阅读文档但不能创建编辑或删除文档,能够获得变化 但不能发送变化
Author作者
创建与阅读文档自己的文档,但只能编辑复制新文档。
Editor编辑者
创建阅读与编辑所有的文档以及复制所有新的或变化了的文档
Designer 设计者
可以修改所有的数据库设计元素,可以修改复制公式并且可以创建全文索引,设计者也可以执行允许较低存取级别执行的所有任务。但它不能删除数据库或修改ACL。复制所有新的或变化了的文档,也可以复制对设计的更改设计,但不能复制对ACL的更改。
Manager管理者
可以对数据库做任何操作 可以复制任何变化。
  另外在ACL中有两种缺省的服务器组  LocalDomainServers是本地域中的服务器所形成的组,OtherDomainServers是其他域中的服务器所形成的组,它们通常是其他组织的服务器而本组织的用户可能需要去访问它们
  要防止未注册的用户访问数据库你应该设置Default为No Access 如果Default需要更高的存取权限那么应该在ACL中创建Anonymous项并且将其设置为 NoAccess。
   为了允许来自Web客户的访问,你可能仍然想让匿名用户拥有一些最小的权限来有效地使用数据库例如 你可以授予匿名用户以下权限
    Reader允许访问信息数据库;
  Author允许访问交互式数据库;
  将Default与 Anonymous存取区分开,如果在ACL中没有Anonymous匿名这一项,那么Domino将按缺省的数据库存取级别对匿名用户访问进行设置。
  而这种设置有可能超过了匿名用户访问所需要的级别,存取级别定义如下  :Default缺省 在ACL中没有定义的用户
Anonymous匿名 组织中没有有效Notes标识的用户
8.2 基于文档存取的安全控制
  文档的创建者通过在文档属性对话框的安全设置能够决定谁可以阅读这个文档,可以选择让那些具有读者或更高权限的用户来阅读文档或者只让有限的用户阅读文档。
  文档继承用来创建它的表单的读权限,任何被允许编辑文档的人都可以更改文档的读访问属性
8.3 基于域的安全控制
  每一个文档都有一些特殊的域用来控制对它的访问,这些域是读者域 reader fields、作者域author fields与签名域 signed fields。
读者域
  读者域可以在表单中创建来设置对文档的读访问限制,一个读者域将列出所有允许对文档进行读访问的名字 它可以用来替代或者与表单/文档安全读存取列表一起工作,如果读访问列表与读者域同时存在那么谁能够阅读文档就由它俩共同决定,读者域不允许对数据库没有读访问权限的用户进行访问。不过它能够让那些在数据库ACL中可以正常阅读文档的某些用户不能够进行读访问。
  将一个域设计成读者域并且使它可编辑将允许文档作者看到名字列表列出的名字,可以从地址对话框数据库ACL视图对话框或作者手工输入中获得,有效使用读者域的方法是创建这个域然后列出用户与组来作者可以从中选择。
作者域
  可以在表单中创建作者域来给那些不是文档作者的人以作者的权力从而能够编辑文档,作者域也是要包含一个名字列表并且创建方法与读者域相同,作者域只对那些对数据库有作者权限的用户有效。
签名域
  在表单中创建签名域将允许文档在保存或邮寄时能够附带上数字签名。数字签名能够保证作者的真实性并且保证文档中的数据没有改变,用户标识符中的私有密钥能够生成签名,Notes通过比较数字签名与公用通讯录中的公开密钥来进行合法性验证。
8.4 基于代理的安全控制
1、作为WEB用户运行
  默认情况下,Web用户以代理创建者的权限运行代理。然而在Design选项卡的代理属性中选择“作为WEB用户运行代理”时,可以指定WEB用户代表自己(自己指创建者)运行代理。如果选定这个选项,系统会提示用户输入相关用户名和密码(已登录则不用)。
  然后根据用户名检查数据库ACL中的权限。 仅仅通过Notes客户(不是WEB用户)就可以创建代理。只有共享代理才能运行在WEB客户上。WEB无调度机制,因此运行在WEB上的代理无法在预定义的时间运行。如果在代理创建过程中有设置代理何时运行,则该代理只适用于从Notes客户运行的代理。代理操作对象选项则对所有代理有效。并且代表session.currentusername的不同。
WEB不支持以下四个选项:
*视图中所有未读文档  *视图中所有文档  *已选定的文档   *粘贴的文档
在具体应用上比如设置了自动回复邮件,如果不是作为WEB用户运行,那么回复邮件就会标明发信者是代理签名者而不是真实用户。
2、设置运行时安全性等级 3、查看和运行此代理的缺省权限
以上两项一般设置选择第二安全等级
4、允许有公共权限的用户查看和运行此代理(只要可以访问此数据库的用户都可以查看和运行此代理)