[獨自murmur]下判斷式時,應找出真正的因

  • 2599
  • 0

摘要:[獨自murmur]下判斷式時,應找出真正的因

這個題目,是在code review的時候,很常看到的問題。
而且會是致命的問題,但是卻很難說明清楚。

舉個最常聽到的例子來說,
「天雨路滑」,因為下雨,所以地上是濕的。
轉換成程式,大概就是類似:

if(IsRainy)
{RoadState=RoadStateType.Wet;}
else
{RoadState=RoadStateType.Dry;}

上面這例子應該沒啥問題,重點來了,
「天雨+路滑+撐傘」這三個東西搞在一起,就可能有人code寫錯了。

錯誤的例子:

if(IsRainy)
{RoadState=RoadStateType.Wet;}
else
{RoadState=RoadStateType.Dry;}

if(RoadState==RoadStateType.Wet)
{OpenUmbrella();}

這邊為什麼錯?我們用現實的情況來解釋,就看得出為什麼不合理了。

因為下雨,地上就會濕,因為地上濕,所以要撐傘?
不對吧,撐傘的原因,應該是因為下雨,而不是因為地上濕。
地上濕的原因可能會多種,可能有人潑水,地上會濕。可能有人在洗玻璃、洗車,地上會濕。

因此,當你要判斷「是否要撐傘」時,不能拿「下雨」會產生的結果來判斷,而是應該拿「是否下雨」來當作判斷的條件。

很多junior programmer碰到被challenge程式寫法邏輯有問題時,通常都是這種情況。
因為他們會認為,「我的程式跑起來是對的,為什麼你說我錯」,
或是「根本不會因為其他情況導致地上是濕的,所以只要地上是濕的,就代表下雨,就代表要撐傘」。

我再舉個常見的例子,
我曾經看過一段CODE,
是按了存檔的按鈕之後,要把資料存進去DB。但是寫法是下面這個樣子:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
           SaveDB();
        }

    }

相信寫過程式的人都會覺得這段CODE也太離譜了吧。
沒錯,就是這麼離譜,
因為
存檔button會submit -> submit會postback-> postback會觸發Page_Load() -> IsPostBack會變成true
所以把SaveDB()寫在Page_Load()用IsPostBack判斷,是合理的。

當你告訴他,其他功能也可能會觸發postback時,他卻跟你說,
我這隻規格上只有這個button會觸發postback」,真的會想把他的頭扭斷。

如果這例子大家覺得可笑,
那我再舉另外一個例子,

畫面上有兩個Panel擺放著Insert與Edit要用的區塊,分別叫做PanelInsert與PanelEdit好了。
這兩個區塊只固定會顯示其中一個。
Panel外有一個存檔button,固定要顯示,但是當Edit時,要執行Edit的功能,Insert時要執行Insert的功能。

開關panel的code可能是這樣寫:

if(Status==StatusType.Insert)
{
  PanelInsert.visible=true;
  PanelEdit.visible=false;
}

elseif(Status==StatusType.Edit)
{
  PanelInsert.visible=false;
  PanelEdit.visible=true;
}

但是問題來了,存檔呢?
相信我,我看過太多的code是寫成這樣:

if(PanelInsert.visible)
  {InsertDB();}
elseif(PanelEdit.visible)
  {EditDB();}

這樣寫的邏輯,跟上述的錯誤例子不是一樣嗎?
正確的寫法應該是:

if(Status==StatusType.Insert)
  {InsertDB();}
elseif(Status==StatusType.Edit)
  {EditDB();}

請回頭檢查看看自己的code裡面,是否有判斷條件是使用「樣式」來做判斷的,
通常那就是犯了這類型的錯誤,
「樣式」的呈現,通常是某個判斷後產生的結果,而非其他判斷式的「因」。


blog 與課程更新內容,請前往新站位置:http://tdd.best/