Posted on 2006-11-22 01:17
大大毛 閱讀(375)
評(píng)論(0) 編輯 收藏 所屬分類:
ASP
??????還是這份短工,雖然用的是ASP,不過俺在工作中還是有所收獲。
??????以前就用ASP,用起來挺順手的,當(dāng)然是在代碼量及邏輯的復(fù)雜度都比較小的時(shí)候感覺還挺好,呵。但是打這份工,接手的任務(wù)是修改一套系統(tǒng)的局部。系統(tǒng)的邏輯現(xiàn)在還挺亂的,不太容易理解,不過通過這段時(shí)間的研究還是學(xué)了不少。
??????這個(gè)ASP系統(tǒng)在結(jié)構(gòu)上實(shí)現(xiàn)了一定的封裝,功能頁面全部使用 Function 來實(shí)現(xiàn)。每個(gè)ASP頁面均由兩部分組成,一個(gè)是外層文件(充當(dāng)模板),另一個(gè)用Function來封邏輯,使用時(shí)在外層的ASP中使用 include 來引入邏輯頁。同時(shí)整個(gè)系統(tǒng)的主干則按功能劃分成了單獨(dú)的功能模塊,模塊利用Function以及Class來實(shí)現(xiàn),最后同樣使用這種拼裝的方式搭起一個(gè)系統(tǒng)的骨架。
??????這種架構(gòu)看起來很不錯(cuò),不過在今天俺寫一張自用的ASP頁面時(shí)發(fā)現(xiàn)了一些問題。
??????我的這張ASP是自己寫自己用的,主要是用于探索庫/表的結(jié)構(gòu)以及發(fā)現(xiàn)數(shù)據(jù)特征。頁面的功能除了提供 SQLServer的操作?外,另外還需要用于查看及分析從 AS400 上獲取的數(shù)據(jù)。項(xiàng)目中與AS400的連接已經(jīng)被封裝成了組件,提取不同的數(shù)據(jù)需要通過組件向 AS400 主機(jī)發(fā)送不同的指令字符串來實(shí)現(xiàn)。由于指令字符串是根據(jù)一個(gè)協(xié)議來規(guī)范,因此合成不同的指令需要使用不同的邏輯。為了將這些復(fù)雜以及單獨(dú)的邏輯加以進(jìn)行區(qū)分,我想過利用現(xiàn)有系統(tǒng)的這種結(jié)構(gòu)來完成,即每個(gè)指令的邏輯被放在一個(gè)單獨(dú)的 Funtion 中,然后根據(jù) 頁面 提交上來的參數(shù)來分別調(diào)用,結(jié)果程序變成這樣 ( 這里使用的是示例代碼 ):

程序原框架
Dim?AS400Code
AS400Code?=?""
AS400Code?=?Request("AS400Code")
'初始化"AS400連接組件"
Dim?IQS
Set?IQS?=?New?IQS
'---------控制器------------
Dim?CodeString,Head
Select?Case?AS400Code
????Case?"PSCA1000"
????????'調(diào)用指令封裝邏輯
????????Call?PSCA1000(CodeString,Head)
????????'調(diào)用?封裝AS400連接?的組件
????????IQS.send(CodeString)
????????'顯示連接組件持有的數(shù)據(jù)集
????????Call?ShowRs(IQS.Rst,Head)
????Case?"PSCA1002"
????????'調(diào)用指令封裝邏輯
????????Call?PSCA1002(CodeString,Head)
????????'調(diào)用?封裝AS400連接?的組件
????????IQS.send(CodeString)
????????'顯示連接組件持有的數(shù)據(jù)集
????????Call?ShowRs(Head)
????Case?Else
????????Response.Write?"尚未支持AS400程式碼:"?&?AS400Code
End?Select
Set?IQS?=?Nothing?
'------------視圖-------------
'顯示功能幫助信息
Function?ShowHelp()
????Response.Write?"<OL>參數(shù)AS400Code:AS400程式碼:"
????Response.Write?"<LI>PSCA1000</LI>"
????Response.Write?"<LI>PSCA1002</LI>"
????Response.Write?"</OL>"
End?Function
'使用二維表以及Head來生成?<table>?元素
Function?ShowRs(Rst,Head)
????'使用Rst來生成一個(gè)?<table>?元素,并利用?Head?來生成表頭列
End?Function?
'---------AS400指令處理邏輯(模型)------------
Function?PSCA1000(ByRef?CodeString,ByRef?Head)
????'根據(jù)復(fù)雜的邏輯來合成CodeString以及數(shù)據(jù)報(bào)表頭
End?Function?
Function?PSCA1002(ByRef?CodeString,ByRef?Head)
????'根據(jù)復(fù)雜的邏輯來合成CodeString以及數(shù)據(jù)報(bào)表頭
End?Function?????????這里提一下,就算是將 AS400指令處理邏輯 全部放在一個(gè)文件,并在當(dāng)前的頁面中使用 Include 包含進(jìn)來,那么整個(gè)功能的框架也是沒有什么變化的。
?????????仔細(xì)看看這個(gè)框架,不難發(fā)現(xiàn)問題所在: 隨著以后所支持AS400指令的增多,框架中充當(dāng)“控制器”的 Select Case 部分將受到嚴(yán)重考驗(yàn)。
???????????????1.大量的Case分支充滿其中,重復(fù)代碼過多;
???????????????2.隨著指令邏輯的增多,指令邏輯將不可避免的放入單獨(dú)的文件中,這樣一旦增加一個(gè)AS400指令就必須更改多個(gè)ASP頁面;
???????????????3.頁面為使用者顯示一個(gè)功能幫助信息,其中需要顯示到所能支持的指令以及指令含義信息,而這些信息又不可避免的需要在主頁面中重復(fù)輸入及更改。
?????????累則思變 :-),想想例如JAVA/NET中的那些設(shè)計(jì),如果能夠利用上,把調(diào)用與實(shí)現(xiàn)分離就OK了。仔細(xì)分析一下上面的代碼不難發(fā)現(xiàn),問題出在“控制器”與“模型”的強(qiáng)耦合上,結(jié)果造成兩者的“同步更新”。
?????????降低耦合,最好使的方法就是在兩者之間加入一個(gè)層 (接口) ,這樣問題即可解決。由于ASP本身并不提供接口這一東東,只能自己來實(shí)現(xiàn)羅。下面是我的解決方法:

程序新的框架(分離的感覺真好)
'注意這里:?--新增了一個(gè)?CodeDic?容器,它就是俺設(shè)計(jì)的接口
Dim?CodeDic
Set?CodeDic?=?Server.CreateObject("Scripting.Dictionary")
<!--#include?file="As400Code.asp"-->
'-----------
Dim?AS400Code
AS400Code?=?""
AS400Code?=?Request("AS400Code")
'初始化"AS400連接組件"
Dim?IQS
Set?IQS?=?New?IQS
'---------控制器------------
Dim?CodeString,Head,myFun
If?CodeDic.Exists(AS400Code)?Then
????Set?myFun?=?GetRef(AS400Code)
????Call?myFun(CodeString,Head)
????IQS.send(CodeString)
????Call?ShowRs(Head)
Else
????Response.Write?"尚未支持AS400程式碼:"?&?AS400Code
End?If
Set?IQS?=?Nothing
'------------視圖-------------
'顯示功能幫助信息,看似代碼增多了幾行,不過俺再也不用改它了
Function?ShowHelp()
????Dim?Code
????Response.Write?"<OL>參數(shù)AS400Code:AS400程式碼:"
????If?CodeDic.Count?<?1?Then
????????Response.Write?"現(xiàn)在尚無指令支持"
????Else
????????For?Code?In?CodeDic
????????????Response.Write?"<LI>"?&?Code?&?":"?&?CodeDic.Item(Code)?&?"</LI>"
????????Next?
????End?If?
????Response.Write?"</OL>"
End?Function?
'使用二維表以及Head來生成?<table>?元素
Function?ShowRs(Rst,Head)
????'使用Rst來生成一個(gè)?<table>?元素,并利用?Head?來生成表頭列
End?Function
'=========As400Code.asp=============
'---------AS400指令處理邏輯(模型)------------
'注意這里:由模型向接口注冊(cè)
CodeDic.Add?"PSCA1000","PSCA1000指令的說明信息"
Function?PSCA1000(ByRef?CodeString,ByRef?Head)
????'根據(jù)復(fù)雜的邏輯來合成CodeString以及數(shù)據(jù)報(bào)表頭
End?Function?
CodeDic.Add?"PSCA1002","PSCA1002指令的說明信息"
Function?PSCA1002(ByRef?CodeString,ByRef?Head)
????'根據(jù)復(fù)雜的邏輯來合成CodeString以及數(shù)據(jù)報(bào)表頭
End?Function??????????呵呵,就是這么簡單。
?????????中間層(接口):
???????????????這里我使用了一個(gè)容器來充當(dāng)中間層,當(dāng)然這里為了省事在容器的使用上并沒有完全實(shí)現(xiàn)接口的功能。我這里向容器提交的 Key 是AS400指令處理函數(shù)名; Value 是外層頁面上需要的對(duì)應(yīng)幫助信息。如果想完全實(shí)現(xiàn)接口的話,應(yīng)該這樣用容器: key--功能名;value--處理函數(shù)名;這樣一旦處理邏輯發(fā)生變動(dòng),只需更新對(duì)應(yīng)的 value 即可。
?????????模型:
???????????????這里有點(diǎn)變動(dòng),程序功能添加的控制權(quán)由原先的“控制器”轉(zhuǎn)向“模型”,因?yàn)樵谶@里它更容易變動(dòng)一些。而且讓它只與充當(dāng)中間層的容器打交道。
?????????視圖:
???????????????同樣的,也只讓它與中間層打交道。
?????????控制器:
???????????????這里變動(dòng)最大,諸多不爽的 Select Case 分支被拿掉,控制器僅僅與中間層打交道。利用 VBScript 提供的 GetRef( funName ) 獲取函數(shù)指針,來實(shí)現(xiàn)邏輯功能的動(dòng)態(tài)調(diào)用。
?????????每次需要新增AS400指令邏輯處理功能時(shí),只需向As400Code.asp添加一個(gè)功能處理函數(shù),并將其注冊(cè)到容器即可實(shí)現(xiàn)整體功能的更新。
?????????兩個(gè)框架經(jīng)過對(duì)比不難看出其優(yōu)點(diǎn),新的框架在新增功能時(shí):
???????????????1.避免了重復(fù)的調(diào)用代碼;
???????????????2.僅僅修改一處地方。