代碼檢查(6)
Posted on 2008-10-29 22:20 非魚 閱讀(3057) 評(píng)論(0) 編輯 收藏 所屬分類: 面向?qū)ο笤O(shè)計(jì) 、Java技術(shù)6. 使用具體的類定義變量
使用具體的類來(lái)定義變量,可能導(dǎo)致代碼中存在抽象問(wèn)題。這里所說(shuō)的變量包括靜態(tài)變量、實(shí)例變量、本地變量、方法的參數(shù)和返回值。
更加具體一點(diǎn)說(shuō),在組織內(nèi)部的代碼中,如果存在一個(gè)類繼承關(guān)系,并且這個(gè)類繼承關(guān)系中的具體類被用來(lái)定義變量,則這里有問(wèn)題的可能性比較高。我們定義抽象類或接口的目的就是抽象使其脫離易變的實(shí)現(xiàn)細(xì)節(jié),如果抽象了穩(wěn)定的接口而不在變量定義中使用它,那還有什么意義呢?
使用具體類定義變量的問(wèn)題就在于,這通常綁定了實(shí)現(xiàn)類而缺乏抽象,難以適應(yīng)未來(lái)需求的發(fā)展,難以維護(hù)而增加成本。
相對(duì)來(lái)說(shuō),使用具體類定義本地變量的影響是最小的,在可以控制的范圍之內(nèi);使用具體類定義實(shí)例變量和靜態(tài)變量,如果變量是private的,基本也在可控的范圍內(nèi)。
如果實(shí)例變量和靜態(tài)變量package、protected或public的,需要特別的當(dāng)心。這時(shí)候?qū)嶋H上已經(jīng)向外界(當(dāng)前類之外)隱含的“發(fā)布”了這些變量,它們可能已經(jīng)不在你的控制范圍之內(nèi)了。由于封裝的不嚴(yán)密并且直接泄漏了具體的、不穩(wěn)定的實(shí)現(xiàn),極易導(dǎo)致代碼在維護(hù)過(guò)程中的失控,并且給測(cè)試帶來(lái)了困難。如果沒(méi)有特別的理由,這樣的代碼是一定要修正的。修改變量的可見性是最好的方式,這要求對(duì)變量的使用情況進(jìn)行檢查(現(xiàn)代的IDE一般都支持Find Usage),如果這些變量已經(jīng)被類外部的代碼使用了,修改的工作量會(huì)大大增加,同時(shí)修改可見性也需要對(duì)最初的設(shè)計(jì)進(jìn)行重新評(píng)估;這樣把具體類修改成抽象類或者接口就成為了退而求其次的解決方案。如果時(shí)間允許,二者同時(shí)進(jìn)行是最好的,長(zhǎng)遠(yuǎn)來(lái)看也是最低成本的。
使用具體類定義方法的參數(shù)和返回值也不好,這樣做的危險(xiǎn)程度是中等的。這使對(duì)象之間的通信契約建立在了相對(duì)具體的層次上,缺乏抽象而難以適應(yīng)變化,自然也帶來(lái)了維護(hù)成本的增加。但契約的修改比直接對(duì)“隱私”的侵犯稍好一點(diǎn),并不會(huì)帶來(lái)對(duì)內(nèi)部實(shí)現(xiàn)的大規(guī)模、不可控的破壞。當(dāng)然,如果在代碼檢查中發(fā)現(xiàn)了這樣的問(wèn)題,也要盡可能修改。
在代碼檢查工具的實(shí)現(xiàn)上,對(duì)具體類定義本地變量、實(shí)例變量、靜態(tài)變量、方法參數(shù)和返回值的檢查可能是分離的。這樣我們也有機(jī)會(huì)對(duì)檢查的詳細(xì)程度進(jìn)行定制。我個(gè)人的觀點(diǎn)是,除本地變量之外的情況是一定要檢查的。
對(duì)于第三方產(chǎn)品來(lái)說(shuō),也應(yīng)該盡量使用抽象類和接口來(lái)定義變量。不然你就把自己放在了一個(gè)比較危險(xiǎn)的境地了。而且,部分代碼檢查工具,可能并不會(huì)檢查這樣的情況。
使用具體的類來(lái)定義變量,可能導(dǎo)致代碼中存在抽象問(wèn)題。這里所說(shuō)的變量包括靜態(tài)變量、實(shí)例變量、本地變量、方法的參數(shù)和返回值。
更加具體一點(diǎn)說(shuō),在組織內(nèi)部的代碼中,如果存在一個(gè)類繼承關(guān)系,并且這個(gè)類繼承關(guān)系中的具體類被用來(lái)定義變量,則這里有問(wèn)題的可能性比較高。我們定義抽象類或接口的目的就是抽象使其脫離易變的實(shí)現(xiàn)細(xì)節(jié),如果抽象了穩(wěn)定的接口而不在變量定義中使用它,那還有什么意義呢?
使用具體類定義變量的問(wèn)題就在于,這通常綁定了實(shí)現(xiàn)類而缺乏抽象,難以適應(yīng)未來(lái)需求的發(fā)展,難以維護(hù)而增加成本。
相對(duì)來(lái)說(shuō),使用具體類定義本地變量的影響是最小的,在可以控制的范圍之內(nèi);使用具體類定義實(shí)例變量和靜態(tài)變量,如果變量是private的,基本也在可控的范圍內(nèi)。
如果實(shí)例變量和靜態(tài)變量package、protected或public的,需要特別的當(dāng)心。這時(shí)候?qū)嶋H上已經(jīng)向外界(當(dāng)前類之外)隱含的“發(fā)布”了這些變量,它們可能已經(jīng)不在你的控制范圍之內(nèi)了。由于封裝的不嚴(yán)密并且直接泄漏了具體的、不穩(wěn)定的實(shí)現(xiàn),極易導(dǎo)致代碼在維護(hù)過(guò)程中的失控,并且給測(cè)試帶來(lái)了困難。如果沒(méi)有特別的理由,這樣的代碼是一定要修正的。修改變量的可見性是最好的方式,這要求對(duì)變量的使用情況進(jìn)行檢查(現(xiàn)代的IDE一般都支持Find Usage),如果這些變量已經(jīng)被類外部的代碼使用了,修改的工作量會(huì)大大增加,同時(shí)修改可見性也需要對(duì)最初的設(shè)計(jì)進(jìn)行重新評(píng)估;這樣把具體類修改成抽象類或者接口就成為了退而求其次的解決方案。如果時(shí)間允許,二者同時(shí)進(jìn)行是最好的,長(zhǎng)遠(yuǎn)來(lái)看也是最低成本的。
使用具體類定義方法的參數(shù)和返回值也不好,這樣做的危險(xiǎn)程度是中等的。這使對(duì)象之間的通信契約建立在了相對(duì)具體的層次上,缺乏抽象而難以適應(yīng)變化,自然也帶來(lái)了維護(hù)成本的增加。但契約的修改比直接對(duì)“隱私”的侵犯稍好一點(diǎn),并不會(huì)帶來(lái)對(duì)內(nèi)部實(shí)現(xiàn)的大規(guī)模、不可控的破壞。當(dāng)然,如果在代碼檢查中發(fā)現(xiàn)了這樣的問(wèn)題,也要盡可能修改。
在代碼檢查工具的實(shí)現(xiàn)上,對(duì)具體類定義本地變量、實(shí)例變量、靜態(tài)變量、方法參數(shù)和返回值的檢查可能是分離的。這樣我們也有機(jī)會(huì)對(duì)檢查的詳細(xì)程度進(jìn)行定制。我個(gè)人的觀點(diǎn)是,除本地變量之外的情況是一定要檢查的。
對(duì)于第三方產(chǎn)品來(lái)說(shuō),也應(yīng)該盡量使用抽象類和接口來(lái)定義變量。不然你就把自己放在了一個(gè)比較危險(xiǎn)的境地了。而且,部分代碼檢查工具,可能并不會(huì)檢查這樣的情況。