siebel编程

来源:互联网 发布:米奥软件 编辑:程序博客网 时间:2024/05/16 10:44

siebel编程
1.从哪里开始?
流程:
这里写图片描述
要求:在最需要的地方写最少的代码,且只写一次
(1)能配置的不要通过代码来开发;
(2)决定代码放在哪个对象上:
共用代码写在BS/应用程序级,建议使用BS,因为BS可以被工作流进程调用,但工作流进程不能调用自定义的应用程序级别的方法。
如果某个方法处理的是特定BC上的数据,那么写在这个BC上,这样可以避免在使用该BC的Applet上多次复制类似代码。
applet Server script的使用:查询、插入、更新和删除操作;访问本条记录之外其他记录的数据。
applet browser script的使用:与用户交互;与桌面应用程序交互;对当前记录的验证与处理。
(3)定代码放在哪个事件上:
对BS而言有两大类事件,分别是Pre-event类事件和reactive类事件。
Pre-event的使用:只是想执行某些验证,不会更改除了当前记录以外的任何记录的值,如PreQuery, PreSetFieldValue, PreWriteRecord等;
reactive的使用:记录更改后还想做进一步操作,如writeRecord;
对于applet而言,大部分applet浏览器端代码一般写在Applet_PreInvokeMethod事件中,在这个事件中开发人员可以捕获applet触发的方法,如用于和用户的桌面、用户、applet外观交互的代码。但不建议将所有方法的代码都写在Applet_PreInvokeMethod事件中,而是用来创建自定义方法,并调用这些自定义方法。
(4)添加错误处理模版。在撰写任何代码前先在合适的地方添加错误/异常处理策略,主要是添加错误处理模版应用于事件中。
(5)添加方法主体。将方法主体代码添加在错误处理框架中,这样你就能捕获任何运行时错误。
(6)测试。
2.编码命名规范:

1)数据类型命名规范数据类型名                       变量命名前缀Integer 整型                     I                String 字符形                     SBoolean 布尔型                    BFloat 浮点型                      f

(2)不同作用域范围变量的修饰符

作用域                                   修饰符全局作用域(仅适用于Siebel VB)              G_模块/实例范围                             M_ 或者 i_函数或者局部作用域                         不需要修饰符或者l_

3.一定要为代码添加必要的注释
4.将代码放在合适的事件中:

级别       事件                      常用用途               应用程序级 BusComp_PreSetFieldValue      字段级别的验证         应用程序级 BusComp_PreWriteRecord        记录级别的验证         应用程序级 BusComp_PreQuery              代码用来控制SearchSpecs伴随事件   BusComp_SetFieldValue         字段触发的动作伴随事件   BusComp_WriteRecord           记录触发的动作

5.在频繁触发的事件处理器中使用快速代码
6.使用运行时BS还是编译后的BS
(1)运行时BS:不会编译到.srf文件中,代码保存在数据库中,可以随时更改它,由于运行时都是使用最新的BS定义,适合于编写逻辑经常变化的BS代码或需要在不发布新.srf文件的情况下发布BS。缺陷是任何具有访问商务服务管理员视图的人都可以看见代码,这可能会导致安全性问题。
(2)编译后的BS:在Siebel Tools中定义的,适用于需要更高安全性和不怎么更改的功能。需要编译,并且通过一个新的.srf来应用更改。优点是具有更高的安全性,且装载的速度更快。
7.使用合适的调试技巧
(1)使用alert(不会停止代码的执行)或RaiseErrorText(会停止代码的执行)方法来弹出消息框;
(2)使用Trace或者自定义方法将信息写入文件;
(3)使用Siebel的Debugger功能;
(4)使用对象管理器级别的日志功能(object manager level logging)。
8.从存储库中移除没有用的代码
(1)移除下面这些代码:被注释的代码;设置为inactive (禁用)的代码;从不调用的代码。
(2)移除空方法
9.在所有的代码中包括错误处理
 Try 块:包括你要执行的逻辑;
 Catch块:捕获错误;
 Finally块:执行任何清理工作,比如销毁对象引用。
10.合适的使用RaiseError 和 RaiseErrorText
MsgBox只能用于Siebel 6.x或更早版本。
RaiseError 和 RaiseErrorText会产生一个服务器端代码异常,使代码的执行在此处终止。
所以,任何必须执行的代码必须放到调用这些方法的前面。
11.使用异常信息:
(1)异常包括两种信息:
 错误描述。描述哪里错了。
 堆栈跟踪信息。按照执行顺序列出的直到产生异常地方的方法名称。
(2)异常处理的目的:
捕获异常;
 使程序更加稳定;
 记录异常信息或者通知用户发生了什么事;
 可能,重新抛出异常;
 可能,设置返回代码。
(3)在eScript中,异常对象通过以下属性(方法)存储错误信息:
 errText属性:exception.errText
当系统在运行时碰到一个错误,或者开发人员使用RaiseErrorText来引发一个异常时,该属性就会包含错误信息。
 toString()方法:exception. toString()
从COM对象或者开发人员通过throw方法抛出的异常中异常信息。
12.将return语句放到合适的地方
finally块中的return语句将会覆盖掉产生的异常信息或者别人抛给它的异常信息,这些异常信息不会传出方法外面。
当finally块中的代码产生异常信息时,这样的异常信息会传到方法外面,但是之前的异常信息却丢掉了。

function illustrateReturnStatement(){    var myVar;    try    {        //executable code goes here        myVar = 1;    }    cache(e)    {        if(defined(e.errText))        {            TheApplication().RaiseErrorText("An exception occurred in the "+" of the "+this.Name()+" object. "+"ERROR: "+e.errText+"“STACK:"+e.toString());        }        else        {            TheApplication.RaiseErrorText("An exception occurred in the "+" of the "+this.Name()+" object. "+"ERROR:"+e.errText+"STACK:"+e.toString());        }    }//end catch    finally    {        //cleanup code goes here    }    return myVar;}

13.使用Top对象来集中浏览器端代码
在客户端代码中,top是到顶层文档的捷径。使用top对象,开发人员可以撰写一个浏览器端代码函数一次,然后从其他的浏览器端对象中调用它。
14.在服务器端代码中何时使用当前上下文,何时使用新的上下文?
当前上下文处理的对象是系统创建用来支持对用户来说可用的数据;

bc = this.BusObject().GetBusComp(“Contact”);
bc=TheApplication().ActiveBusObject().GetBusComp(“Contact”);bc=this;
而新上下文是在代码中初始化的一系列对象,它与用户当前看到的对象或者数据没有什么关系。
bo = TheApplication.GetBusObject(“Contact”);bc = bo.GetBusComp(“Contact”);
使用当前上下文:访问用户正在处理的数据;执行的处理(此处应指处理结果)让用户可见。使用新的上下文:对一个可见的BC执行不可见的查询;在其他的BO上下文中使用一个BC。

15.为变量使用最小的作用域
创建实例级别的变量:
 经常会违反封装的原则;
代码的执行会有交叉;
 没有事件保证这些对象会被销毁;
理解这类变量的作用域或状态比较困难,因为他们是在一个方法中初始化的,而在另外的方法也可以访问。
更好的做法是:当需要的时候声明和使用对象,然后将他们作为参数传递给其他方法。
16.只在需要时初始化对象,创建没有使用的对象实例会影响系统性能
评估条件—–>创建对象—–>使用对象
17.当对象变量不再使用时要销毁它
(1)对象引用包括:COM对象,属性集 (Property Sets),BS,BC,BO,Applet
(2)应按照程序创建应用对象顺序的逆序来释放对象,先释放子对象,再释放父对象。
 Pick/Associate/MVG BC 在父BC之前释放;
 BC在BO之前释放;
 属性集和BS因为他们是相互独立创建的,所以先释放哪个都没有关系。
(3)应该将对象销毁语句放到错误处理语句中的finally块中,这样不管方法是执行成功还是执行失败后退出,对象都会被销毁的。

finally{    ChildObject = null;    ParentObject = null;}

18.使用条件块来运行代码

function BusComp_PreSetFieldValue(FieldName, FieldValue){    switch(FieldName)    {        case “Status”:        //do something        break;        …    }    …}

19.检查返回的对象是不是你想要的
(1)ActiveBusObject方法。该方法返回的是活动Applet对应的BC所对应的BO。
当BC是多个BO的子对象时,那一定要检查返回的BO是不是你想要的。
ActiveBusObject只有在应用程序级代码或者BS中调用才有意义,而在Applet或者BC中你应该使用:this.BusObject() 。
代码示例:

if(TheApplication().ActiveBusObject().Name() == “some name”){    //code here}

(2)ActiveBusComp方法。该方法返回的是与活动Applet相关联的BC。
如果是在BC之外调用该方法,应该检查该方法返回的BC是不是你想要的。
(3)ParentBusComp方法。该方法是根据链接(link)中的子BC返回父BC。总是要检查该方法返回的BC是有效的,且是你想要的。
下面两种情况可能会导致没有可用的引用:
 BC是父BC且它没有父BC,比如在Account BO中的Account BC;
 在BO中建立的父子关系的link已经被移除了或者更改了。
如果ParentBusComp方法没有返回引用,也不会抛出异常。如果在一个为null的对象上调用方法或者引用属性将会引发运行错误。

var lBC_parent = this.ParentBusComp();if(lBC_parent != null && lBC_parent.Name() == “some name”){    //code}

20.在使用字段之前检查字段是活动的
在非活动字段上调用GetFieldValue 或者SetFieldValue方法会导致数据丢失或者逻辑混乱。
只能在ExecuteQuery执行成功后使用ActivateField方法。作为一个独立语句,ActivateField不会暗中激活一个非活动字段。
ActivateField告诉系统在BC上下次执行的SQL语句时包括这个列。

ActivateField(<Name>);ExecuteQuery(ForwardOnly);GetFieldValue(<Name>);

(1)只要满足下面条件之一,那么服务器端代码字段就是活动的:
 系统(保留)字段,如Id, Created, Created By, Updated, Updated By
 BC的LinkSpec属性被设置为TRUE ;
 BC的Force Active属性被设置为TRUE;
 在活动视图中包含了一个Applet定义;
 在活动Applet中该字段被用于计算字段的计算公式中;
 使用方法BusComp.ActivateField (strFldName) 显式激活。
(2)满足下面条件之一,那么浏览器端代码字段就是活动的:
 Id 字段;
 在用户界面上该字段可见。
21.Siebel 7 新方法:ctivateMultipleFields, GetMultipleFieldValues 和 SetMultipleFieldValues。

var lbc_account = this;var lPS_FieldNames = TheApplication().NewPropertySet();//创建lPS_FieldNames 来保存字段名称var lPS_FieldValues = TheApplication().NewPropertySet();//创建lPS_FieldValues 在保存字段值var ls_account_products;var ls_agreement_name;var ls_project_name;var ls_description;var ls_name;//使用SetProperty方法设置值以后,调用方法ActivateMultipleFields,Siebel应用程序就会以参数形式传递属性集。//set up the property set which will be used in all three methods to hold the field names.lPS_FieldNames.SetProperty("Account Products", "");lPS_FieldNames.SetProperty("Agreement Name", "");lPS_FieldNames.SetProperty("Project Name", "");lPS_FieldNames.SetProperty("Description", "");lPS_FieldNames.SetProperty("Name", "");//activate the fields using the property set which has the field nameslbc_account.ActivateMultipleFields(lPS_FieldNames);lbc_account.ExecuteQuery(ForwardOnly);if (lbc_account.FirstRecord()){    //当执行ExecuteQuery以后,调用方法GetMultipleFieldValues 来获取字段值    //retrieve the values. This method acts sort of like a BS in that there is an input property set and an output property set.    //The field values will be in the second property set passed in.    lbc_account.GetMultipleFieldValues(lPS_FieldNames,lPS_FieldValues);    //loop through property set to get values.    ls_account_products = lPS_FieldValues.GetProperty("Account Products");    ls_agreement_name = lPS_FieldValues.GetProperty("Agreement Name");    ls_project_name = lPS_FieldValues.GetProperty("Project Name");    ls_description = lPS_FieldValues.GetProperty("Description");    ls_name = lPS_FieldValues.GetProperty("Name");}//now set new values in the property setlPS_FieldNames.SetProperty("Account Products", "All My Products");lPS_FieldNames.SetProperty("Agreement Name", "Siebel Agreement");lPS_FieldNames.SetProperty("Project Name", "Siebel Project #2");lPS_FieldNames.SetProperty("Description", "This is the description");lPS_FieldNames.SetProperty("Name", "Joey Joe Joe Junior Shabbidoo");//set the field valueslbc_account.SetMultipleFieldValues(lPS_FieldNames);//commit the datalbc_account.WriteRecord();  

22.为查询使用合适的视图模式

with (bcAcct){    SetViewMode(this.GetViewMode());}

23.只查询索引列
24.使用ForwardOnly游标模式
25.在执行查询后检查是否有合法的记录存在

bcContact.ClearToQuery();bcContact.SetSearchSpec(“Id”, sContactId);bcContact.ExecuteQuery(ForwardOnly);//Check to see that a record was actually returned by examining the return of FirstRecord().if (bcContact.FirstRecord()){    //okay to perform data processing…}

26.使用Switch(eScript)或者Select Case语句(Siebel VB)
当需要将某个表达式的值和多个可能性进行比较的时候,最快和最具可读性的方法就是使用switch。
 因为表达式只被求值一次,然后和不同的值进行比较,所以效率更高;
 比一大堆嵌套的if…else if 语句更具可读性,使用switch或者select case语句往往能把多页代码压缩成一页。
27.在If/Else If语句中比较相同的条件

var ls_first = “first”;var ls_second = “second”;if (ls_first == “first”){    //do something……}else if (ls_second == “second”){    //do something else………}

28.使用Associate方法创建中间表(intersection table)记录

var lBC_mvg = this.GetMVGBusComp(“Sales Rep”);var lBC_associate = lBC_mvg.GetAssocBusComp();with(lBC_associate){    ClearToQuery();    SetSearchSpec(“Id”, SomeRowId);    ExecuteQuery(ForwardOnly);    if(FirstRecord())   Associate(NewAfter);}

29.使用动态值
最好使用动态值代替将值硬编码到代码中。这对于那些经常更改的值来说特别重要,因为如果你硬编码的话,编码的任何变化都要重新编译和发布。
代码中经常要用到的值都可以通过TheApplication.GetProfileAttr() 函数来获取。
此外,还可以将值存储在List Of Values表或其他表中,在需要的时候查询,用于在代码中要查询的只有一个动态值或较短的值列表时。

//下面代码中,LOV值是从List Of Values这个BC中查询出来的,然后将他们组合成一个查询过滤表达式。var statusList;var moreRecords;var boLOV;var bcLOV;boLOV = TheApplication().GetBusObject("List Of Values");bcLOV = boLOV.GetBusComp("List Of Values");bcLOV.ClearToQuery();bcLOV.SetSearchSpec("Type","SR_STATUS");bcLOV.SetSearchSpec("Active","Y");bcLOV.ExecuteQuery(ForwardOnly);if (bcLOV.FirstRecord()){    statusList = bcLOV.GetFieldValue("Name");    moreRecords = bcLOV.NextRecord();    while (moreRecords != 0)    {        statusList = statusList + " OR ";        statusList = statusList + bcLOV.GetFieldValue("Name");        moreRecords = bcLOV.NextRecord();    }}else{    statusList = "";}

30.使用逻辑常量还是字面量
最好使用逻辑常量,它使代码更加易读且更加容易升级,使用字面量有可能给升级带来问题。

类型                  逻辑常量              字面量游标模式         ForwardBackward             0 (默认值)                ForwardOnly                 1视图模式         SalesRep View               0                ManagerView                 1                PersonalView                2                AllView                     3                OrganizationView            5                ContactView                 6                GroupView                   7                CatalogView                 8                SubOrganizationView         9新记录位置        NewBefore                  0 (默认值)                NewAfter                    1                NewBeforeCopy               2                NewAfterCopy                3

31.避免使用Exit Function 和 Exit Sub
仅针对Siebel VB,应避免使用Exit Function 和 Exit Sub。
32.将GotoView放到代码的结尾
GotoView语句不会立即退出代码的执行并导航到指定的视图,而是将该语句挂起来直到其他的代码执行完毕,所以最好将该语句放到代码的结尾处。
33.合适的使用DeleteRecord
DeleteRecord 会隐式的将记录指针移到记录集中的下一行。在DeleteRecord 后调用 NextRecord 将会使记录指针移动两次,
也就是说Siebel应用程序会跳过记录集中的一条记录,如果你在一个循环中这样删除记录,Siebel应用程序将会隔行删除记录。
在循环中删除记录的方法(Siebel VB):

While(BC.FirstRecord <> 0)    BC.DeleteRecordWend
原创粉丝点击