都知道發(fā)燒不是因?yàn)轭~頭被熱水燙過(guò),肚子疼通常也不會(huì)是因?yàn)槎亲邮軅?其實(shí)調(diào)程序也是如此.
找錯(cuò)誤的時(shí)候不該只從錯(cuò)誤的地方區(qū)找,有可能在遙遠(yuǎn)的地方的問(wèn)題,導(dǎo)致了這里的錯(cuò)誤.
也不要去相信那些從來(lái)沒出過(guò)錯(cuò)的地方,就是不會(huì)錯(cuò)的,從來(lái)不錯(cuò)只表示它過(guò)去沒錯(cuò),不表示現(xiàn)在也是對(duì)的.
今天一個(gè)同事的程序就遇到這個(gè)問(wèn)題,一個(gè)自定義表格控件,用了很久了,突然今天發(fā)現(xiàn)在一個(gè)窗體上操作著操作著就綁不出來(lái)數(shù)據(jù).
重新進(jìn)入窗體又可以了,郁悶了很久,單步調(diào)試了幾個(gè)小時(shí)(因?yàn)椴恢涝趺粗噩F(xiàn)這個(gè)錯(cuò)誤,反正就是"某些操作"以后會(huì)錯(cuò)),把所有的
代碼邏輯都過(guò)了好多次,可是就是找不出錯(cuò)在哪,只知道就是在某些地方經(jīng)過(guò)以后,就再也不可能出來(lái)數(shù)據(jù)了.
晚上沒轍了,明天要用的,就這個(gè)地方過(guò)不去,于是扔給我?guī)兔? 我重復(fù)操作幾次,掌握到大致的出錯(cuò)地方,然后就在重點(diǎn)區(qū)域,如綁定操作
的附近設(shè)了斷點(diǎn),運(yùn)行了幾次次,發(fā)現(xiàn)代碼沒有錯(cuò),Sql語(yǔ)句返回正確,表格綁定方法也沒有問(wèn)題,返回true,就是數(shù)據(jù)再也不出來(lái).
觀察到表格的腳部對(duì)數(shù)據(jù)的條數(shù)統(tǒng)計(jì)是正確的,只是上面不顯示數(shù)據(jù). 監(jiān)視了表格控件的一些主要的屬性,意外地發(fā)現(xiàn),表格中表示
當(dāng)前頁(yè)索引的屬性值是-1,顯然這是問(wèn)題所在,搜索了一下,發(fā)現(xiàn)窗體中沒有對(duì)這個(gè)屬性賦值的操作.那-1又是怎么來(lái)的? 重新進(jìn)入窗體
屬性值出現(xiàn)正確的0,然后做會(huì)改變這個(gè)值的操作(翻頁(yè),在表格組件內(nèi)部實(shí)現(xiàn)) 發(fā)現(xiàn)都正常,然后再嘗試那些有可能產(chǎn)生錯(cuò)誤的操作,
試了好幾次,終于有一個(gè)地方,操作以后變成了-1,-1以后就永遠(yuǎn)-1了. 當(dāng)一個(gè)操作導(dǎo)致表格中沒有數(shù)據(jù)的時(shí)候,表格的頁(yè)索引就變成-1
腦海中馬上明白發(fā)生了什么事了,bug在表格控件內(nèi)部. 馬上也猜出產(chǎn)生這個(gè)錯(cuò)誤的原因. 原來(lái)表格本身保持了這個(gè)屬性的狀態(tài),這樣
在多次綁定數(shù)據(jù)的時(shí)候,如果第一次綁定了N頁(yè),第二次綁定了M頁(yè)(N>M+1),并且在第一次綁定以后,翻到了第P頁(yè)(N>P>M),那么在第2次
綁定的時(shí)候這個(gè)狀態(tài)依然是P,而實(shí)際上數(shù)據(jù)卻并沒有那么多,會(huì)拋出NullReferenceException的異常,于是猜測(cè)表格控件的設(shè)計(jì)者考慮到這個(gè)情況,
于是,對(duì)此做了處理,當(dāng)遇到這個(gè)情況時(shí)強(qiáng)制令 P=M-1 (因?yàn)橐粋€(gè)索引是0開始,一個(gè)是1開始,所以-1). 但是他卻忽略了同時(shí)M=0的情況.
在M=0的時(shí)候,P就出現(xiàn)了-1 .由于這個(gè)第-1頁(yè)是沒有意義的,也是原控件設(shè)計(jì)者所沒有考慮到的情況. 就發(fā)生了上述那些奇怪的總數(shù)
統(tǒng)計(jì)正常,而數(shù)據(jù)不顯示(因?yàn)楦静淮嬖诘?1頁(yè)的數(shù)據(jù)),由于上面沒有數(shù)據(jù),又引起了翻頁(yè)功能的不可用,因此也不可能把這個(gè)-1
給修改回來(lái),于是就不管怎么綁數(shù)據(jù),怎么操作,都一直-1下去了...
反編譯了原控件,從IL中證實(shí)了我的猜測(cè)完全和實(shí)際情況一致. 于是解決問(wèn)題就變成非常簡(jiǎn)單了.
另外有一點(diǎn),控件中對(duì)一些異常,有必要throw出來(lái)給外面一層,雖然說(shuō)如果外面沒有處理會(huì)造成程序崩潰,但是要是把所有沒有意料到
的異常都用一個(gè)空的catch塊把它殺死在控件內(nèi)部,其實(shí)更加危險(xiǎn),造成程序的不可預(yù)料性,而且又難以查找.所以這里有一個(gè)平衡的問(wèn)題.
這還是看設(shè)計(jì)者的經(jīng)驗(yàn),具體問(wèn)題具體分析.
浙公網(wǎng)安備 33010602011771號(hào)