前几个项目自己没有写过接口,都是负责前台的控制。来到这个项目上,才开始自己写,我是6月中旬开始做这个项目的,现在11月份,现在在去看6月份写的package,简直有点想吐了。原因有以下几点:
1. 简洁,扼要的说明没有附加。
2. n多功能综合到一起,全部放到一个包里,而不是根据功能模块划分。
3. 没有例外控制。
4. 写法不规范
5. 取值逻辑考虑不周全
针对于第一点,首先,一个让人容易理解你的包的是干唯一方法就是加上必要的注释,这样方便别人,也方便自己,不至于最后自己都看不懂你写的是干什么用的。看下面这个例子(我六月份写的):
e.g:
PROCEDURE ship_bill_insert(
p_business_id IN NUMBER ,
p_site_id IN NUMBER,
p_use_site_id IN NUMBER DEFAULT NULL,
p_business_type IN VARCHAR2,
p_created_by IN NUMBER,
p_creation_date IN DATE,
p_last_updated_by IN NUMBER,
p_last_update_date IN DATE,
p_last_update_login IN NUMBER,
p_address IN VARCHAR2 DEFAULT NULL,
p_enable_flag IN VARCHAR2 ,
p_primary_flag IN VARCHAR2 DEFAULT NULL,
p_object_version_number IN NUMBER DEFAULT NULL
);
想必你看到这个方法,真的不知道如何去使用,连参数的说明都没有,如何去使用呢,不能盲猜吧。
现在写的程序:
CREATE OR REPLACE PACKAGE bf_isp_price_sku_cost_pkg AS
-- Author : Judev Qin
-- Created : 2009-9-30
-- Purpose : 商品结算成本维护
/*==========================================================
参数: p_sku_cost_id IN ID,唯一性索引
p_sku_id IN 商品ID
p_business_type_id IN 业态类型 OEM,QSP,Bexpromo,FME
p_enable_flag IN 是否有效
Created : 2009-09-30 Judev Qin
Modified:
==========================================================*/
--插入一条记录至BF_PRICE_SKU_COST
PROCEDURE insert_sku_cost(p_sku_cost_id NUMBER,
p_sku_id NUMBER,
p_business_type_id NUMBER,
p_sku_cost NUMBER,
p_enable_flag VARCHAR2,
p_created_by NUMBER,
p_creation_date DATE,
p_last_updated_by NUMBER,
p_last_update_date DATE,
p_last_update_login NUMBER
);
这样的程序,如果另一个去使用,岂不是一目了然啊。
针对第二点,一个包封装的就应该是一个功能,这样不仅便于维护,而且风险性降低了,如果所有的功能都放到一个包里,岂不是一个地方出错,整个系统就要崩溃了。就拿我之前写的程序来看,我当时写了一个包,刚开始主要是负责用户,客户注册的模块,后来又加进来了些成本的维护功能,再后来又加一个用户登录的验证,主要是通过dblink从erp测试环境里取值。后来,出现这样的情况,由于erp测试环境数据库出错,导致该方法不能正确取值,导致了前台用户不能登录。可见这种危险性真是大啊,所以一定要分功能建包。
针对第三点,一个健壮的程序都是能够应对各种异常的,并能够正确处理掉。如果没有这些控制,你的程序就是不合格的,是不健康的。看我的程序(六月份的)
eg:
select t.role_category
into l_role_category
from fnd_prv_role t
where t.role_id = p_role_id;
表面上看没有问题,其实是危机重重。首先,有两个疑问,第一,你一定能保证p_role_id有值吗?其二,你一定能保证p_role_id对应的role_category一定有值吗?如果你能保证有,别人调用你api的时候,也保证能完全按照你的想法去做吗?所以还是改下程序吧,(现在)
begin
--utl包对参数验证
select t.role_category
into l_role_category
from fnd_prv_role t
where t.role_id = p_role_id;
exception when no_data_found then
--处理一
when too_many_rows then
--处理二
when others then
--处理三
end;
这样一处理,你就可以无忧无虑的使用了。
针对第四点:最基本的就是参数的写法,IN 参数一般都是 p_xxxx,OUT 参数一般都是x_xxxx,定义的变量l_xxxx,package的名称前缀_pkg,如果写接口的话,都是三个包(pub,pvt,utl)。function和procedure要看具体功能来命名。
针对第五点:这一点其实至关重要,取值逻辑的错误,会导致你劳而无获。之前,在做一个运费计算的api,我当时写了:
。。。
SELECT SUM(QOL.QUANTITY * BSC.OUTER_GROSS_WEIGHT) INTO l_trans_weight
FROM QSP_ORDER_LINE QOL, BF_SKU_CUST_LINE_VL BSC
WHERE QOL.SKU_CUST_ID = BSC.SKU_CUST_ID
AND QOL.QSP_ORDER_HEADER_ID = p_header_id;
。。。
一个老顾问,看到这句话时,提示有问题,自己找了下也没发现什么。后来他告诉我,如果订单头没有订单行,你如何取值啊!所以大家对于取值一定要深思熟虑。