太多的if,太多的痛苦

2021-04-16 23:02:29 字數 3218 閱讀 1690

太多的if

-擴充套件服務需要重構及其他討論

chenfuzhong 2008-12-15

剛剛被安排開發擴充套件服務的通知存款模組時,心裡誠惶誠恐。一是我對業務不了解;二是擴充套件服務包含太多的

if**塊,難於理解。

當我接到開發通知存款的任務時候,很鬱悶!業務需求沒有人講解,企望能從**中倒推業務規則。但未能所願,**中包含太多的

if語句。太多的可能程式執行路徑,根本無法全部理解。可讀性不說,怎麼能擴充套件和維護呢。聽說通知存款指令跟×××指令一樣的規則,再笨也要懂得照貓畫老虎吧。因此,不假思索就在有×××指令的

if語句中也加入通知存款的判斷。

在擴充套件服務**中,很多交易必須做預提交來檢查使用者輸入的資料是否正確。而且很多交易使用的是同乙個預提交介面,這樣導致有很多

if判斷語句。隨便在

web層發乙個預提交請求到擴充套件服務,從日誌列印的方法棧中瀏覽**。第乙個方法有13個

if,第二個方法有

8個方法,第三個有

11個方法。這只是乙個隨機發的請求呼叫棧。統計了一下,好幾個檔案有效**行數都在

900左右,有乙個檔案

if語句達到

252個。基本上方法中都是

if**塊。

**結構大致上如下:

public object

統一入口( )  

if(交易型別2 || 交易型別3 || 交易型別4)  

.....

其他規則( ); 

return null;

}public void

交易規則方法1( )

if(交易型別2) }

從**中可以看出,如果我們想輕鬆擴充套件乙個交易型別並且重用原來**其他一些外圍功能,如日誌等,是很難的。首先你必須要理解所有的業務需求和程式可能執行的路徑才能做修改。按照排列組合原理,前面說的那個擴充套件服務的請求**可能執行的路徑至少是2的

32次方!雖然有點誇張,我的意思是**理解起來非常費勁。如果增加乙個交易型別

5,需要呼叫

「交易規則方法1」和

「交易規則方法

2」又不需要呼叫

「其他規則方法

」 ,那麼必須增加乙個if-

else

語句來處理。**的可能執行路徑變成了之前的兩倍了,後面來開發新功能的和維護的人痛苦指數可想而知了。

很多時候我們是在用物件導向的語言寫結構化的**,或者說是基於物件的**。在我看來不管是物件導向程式設計還是結構化程式設計,只不過是**的不同組織形式而已。不過,正因為不同,效果是顯而易見。物件導向是個易懂難用東西,因此開始的時候總覺得很高深。其實我們小學時就已經學習過了。相信大家肯定見過這樣的考題:請找出「輪船、飛機、火車、公雞」中跟其他三項不同的一項。這些不過是生活中常見的抽象分類總結問題,對我們來說已經不是什麼難題了,但我們在開發中卻總是捨近求遠。回到前面的例子,我們無需做多麼優良的設計,只要按照剛剛說的抽象分類總結方法,**也將有極大的改善。首先,我們可以將所有交易抽象出來作為一種型別,規則作為另外一種型別;再次,顯然交易型別跟規則型別是一對多的關係。這就很清楚了,交易型別知道它自己被多少規則約束。當增加一種新的交易型別時,我們只要通過各種途徑(如

ioc等)得到這個新型別的物件即可,利用多型,無需

if語句,也無需擔心會影響其他交易型別的規則校驗,這個物件自己知道怎麼做它該做的事情。可見,多一點思考這種回報是值得的!

寫到這裡是不是覺得擴充套件服務需要重構呢?我還沒有接到命令去重構它,關於如何重構的話題請看

martin fowler

的《重構》。下面我們來分析出現這種狀況的原因及其他一些思考。

面向介面程式設計,是的,沒錯!只是我們常常誤會和用錯。像我,以為面向介面程式設計等同於物件導向程式設計。有時候很困惑,到底什麼樣的企業應用才算是真正的物件導向應用。很多經典的書都提倡好的

j2ee

應用首先物件導向的,並將面向介面程式設計作為口號,如《

without ejb

》。我一直覺得企業應用無非是對資料庫增、刪、改、查而已。也許正因為如此我們的**看起來沒有那麼物件導向。最近學習

groovy

動態語言,發現

grails

很適合做這個事情,乙個命令就可以生成增、刪、改、查的功能。也許這是有道理的,僅僅是增、刪、改、查難道需要物件導向嗎?大師

martin fowler

總結了好多企業架構模式供我們使用。左乙個介面右乙個介面,各層之間均要介面作為門面,導致乙個小功能都要幾個檔案才能完成。雖然大處是抽象了,但究竟我們的實現類變化的概率有多大呢?加上繁瑣的配置(如

spring

),我們寧願多加幾個

if語句也不想增加幾個檔案和一堆配置項。於是出現了動態語言和「約定優於配置」。聽說大師

martin fowler

已經投向動態語言的懷抱,而我們這些小嘍囉才對他的企業架構模式有點體會又開始迷茫起來。

可見,即使從大處定義了介面也不能幫助我們的應用成為物件導向。換個角度看看,企業應用真的不過是增、刪、改、查功能,它複雜那是因為有一大堆業務規則加以這些功能上。增、刪、改、查可以不要物件導向,但業務規則不能不要。難道動態語言聰明到幫我們抽象業務規則?我並不反對動態語言,而且我正在學習

groovy

和grails

,我只是想說物件導向還得我們自己對業務規則進行抽象分類總結才可以。

總結一下為什麼出現那麼多

if和為什麼不夠物件導向。注意,並不是說物件導向就不需要

if語句了。

首先,企業應用不可否認大多數都是增、刪、改、查,於是我們很多時候是圍繞這些基本功能來開發。再加上架構模式的條條框框和我們的懶惰,乙個

if又乙個

if慢慢進入到**中,剛開始還可以接受,到一定的時候就會有點像騎虎難下的感覺。因此,我們應該在門面介面下面物件導向我們的**(這是我的觀點),具體的做法是分析業務,抽象業務規則而已,也就是給業務建模。

其次,並不是我們沒有理解什麼是物件導向,而是任務往往很緊,沒有時間來分析和思考。老闆才不管你怎麼實現呢,他關心的是什麼時候可以做出來。這個是值得管理者好好思考的問題。

最後,為他人著想,你的**是否可閱讀,別人復用是否很容易,足以。

總之,除了**中含有太多的

if需要重構外,還有其他地方如:

indto

的繼承關係、

outdto

的繼承關係、使用者選單、頁面提示等都需要乙個完好的規劃,才能在以後的維護和開發中減少開發人員的工作量或是痛苦指數。

愛得太多付出太多的女人不幸福

你是這樣的女人嗎?不懂得愛惜自己 經常把自己的利益放在一邊,目的是為了保住你的愛情或婚姻 不喜歡他的性格和缺點卻只能忍受,並認為只要自己足夠有魅力,足夠愛他,他就會為你改變 渴望 幫助 他,怎樣的付出都不嫌棄,不嫌浪費時間,不嫌代價高 願意等待,期盼,害怕他不高興,願意努力取悅他 害怕感情出問題,因...

鑰匙不要太多!

在vdb中,辛辛苦苦找到了sqltableeditor這把鑰匙 卻發現要建立乙個表需要 void createtable sqltable sqltable sqltable 如何來?我的天!sqltableeditor就不能有乙個newsqltable name 嗎?辛辛苦苦找到sqltable,...

TIME WAIT數量太多

我個人估計還是有一些場景會有問題。again,使用tcp tw reuse和tcp tw recycle來解決time wait的問題是非常非常危險的,因為這兩個引數違反了tcp協議 rfc 1122 其實,time wait表示的是你主動斷連線,所以,這就是所謂的 不作死不會死 試想,如果讓對端斷...