關於編碼規範和如何寫出易讀代碼的心得

編寫出規範,易讀,優雅的代碼能夠大大方便代碼的維護,推薦相關書籍——代碼整潔之道。

目錄

一、變量名

1.名字和變量的意義要一致;

2.一個變量,不能當成倆個變量來使用

二、方法

1.只關注一件事,那就是這個方法名所賦予的事

2.參數個數要少,這樣耦合性就低,規範要求是少於5個

3.行數不易過多,50行左右,最多不過100行,一般超過100行,說明方法內部有代碼需要整合成另一個方法,當然,賦值超過100行不算

4.方法內位於同一抽象層級

三、實體類

四、模型類

五、服務類

六、Controller類

七、mapper或者dao類


一、變量名

1.名字和變量的意義要一致;

2.一個變量,不能當成倆個變量來使用

場景:在一個方法內,程序員發現有一個字符串變量只有在最開始或者某一段中使用到時,爲了充分利用這個變量,不再重新聲明新變量,而是一直對該變量進行操作。

    private String getTempString(String type)
    {
        if ("xxx".equals(type))
        {
            return "";
        }
        
        String temp = "xxxxx";
        
        //下面全是對temp字符串進行操作,type已經沒有用了
        return temp;
    }

對於上面那種情況,可能少部分程序員發現type只有在最開始用到了,而之後從來沒有使用,那麼他可能會選擇不聲明temp變量,而使用type來操作,這個時候,雖然你減少了局部變量的個數,但是變量的意義在這個方法內確有不同的意義了,那麼對於後來維護代碼的人來說,這是很痛苦的,並且這個方法的意義就是獲取temp字符串,你返回一個type字符串,雖然可能最後的值相同,但是對於第三者來說,會覺得很矛盾。比如,上面的代碼寫成這樣:

    private String getTempString(String type)
    {
        if ("xxx".equals(type))
        {
            return "";
        }

        type = "xxxxx";

        //下面全是對temp字符串進行操作,type已經沒有用了
        return type;
    }

二、方法

1.只關注一件事,那就是這個方法名所賦予的事

2.參數個數要少,這樣耦合性就低,規範要求是少於5個

3.行數不易過多,50行左右,最多不過100行,一般超過100行,說明方法內部有代碼需要整合成另一個方法,當然,賦值超過100行不算

4.方法內位於同一抽象層級

舉個例子,如下:

    private void deleteSomeThing(String user, String startTime, String endTime)
    {
        if (user.length() > 5)
        {
            user = user.substring(0, user.length() - 5);
        }

        Date startDate = simpleDateFormat.parse(startTime);
        Date endDate = simpleDateFormat.parse(endTime);

        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        /**
         * xxxxxxx
         * xxxxxxx
         * xxxxxxx
         * 一系列對user,startTime,endTime的操作,然後最後得到一個刪除條件
         */
        String condition = "xxxxxx";
        //最後通過mapper或者dao操作數據庫刪除數據
        mapper.deleteSomeThingByCondition(condition);
    }

像這種,直接在一個方法內,寫了太多的操作,如果邏輯複雜一點,行數就會飆升,代碼可讀性也變得很差;如果修改如下:

    private String getUserCondition(String user)
    {
        if (user.length() > 5)
        {
            user = user.substring(0, user.length() - 5);
        }
        //xxxxxxxx
        //xxxxxxxx
        //xxxxxxxx
        String userConditon = "xxxxx";
        return userConditon;
    }

    private String getTimeCondition(String startTime, String endTime)
    {
        Date startDate = simpleDateFormat.parse(startTime);
        Date endDate = simpleDateFormat.parse(endTime);

        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(startDate);
        //xxxxxxxx
        //xxxxxxxx
        //xxxxxxxx
        String timeCondition = "xxxxxx";
        return timeCondition;
    }

    private String mergeCondition(String userCondition, String timeCondition)
    {
        String allCondition = "xxxxx";
        return  allCondition;
    }

    private String getConditions(String user, String startTime, String endTime)
    {
        String userCondition = getUserCondition(user);
        String timeCondition = getTimeCondition(startTime, endTime);
        String condition = mergeCondition(userCondition, timeCondition);
        
        return  condition;
    }
    
    private void deleteSomeThing(String user, String startTime, String endTime)
    {
        mapper.deleteSomeThingByCondition(getConditions(user, startTime, endTime));
    }

其實,如果能夠實現,每個方法抽象層級相同,那麼方法的其他規範就很容易滿足,像上面這種修改,通過抽象層級的劃分,每個方法的行數一定會很少,參數也不會很多。雖然多出了很多方法,但是每個方法幹什麼都能一清二楚,並且可能不需要你閱讀方法內的代碼,你只需要看方法名就知道作用了。不過這個列子比較極端,拆分了很多方法,具體需要如何拆分,拆分多少個方法視情況而定,比如整個操作代碼行數都不過50行,那麼全部寫在一個方法內也可以。

那麼再回到抽象層級來講,以這個列子爲例,

第一層:deleteSomeThing(String user, String startTime, String endTime)

deleteSomeThing方法內部層級只有mapper層,和條件變量(可以把getConditions返回值返回給一個條件變量,然後mapper傳入這個變量),因爲當你要刪除某些數據的時候,最直觀的就是,調用mapper,刪除滿足條件的數據,至於,這個條件是什麼,怎麼獲取,這個層級是不關心的;

第二層:getConditions(String user, String startTime, String endTime)

這個層級只需要返回條件給上一層調用,不需要操作參數來合成條件(當然,如果邏輯簡單,也可以在這一次層級操作參數),所以他只關心條件本身,不關心條件如何操作。這個方法內部就只有各種已經處理好的條件變量。

第三層:

getUserCondition(String user)
getTimeCondition(String startTime, String endTime)
mergeCondition(String userCondition, String timeCondition)

這三層都是操作參數以返回目標條件格式,所以,這三層關心的就是對參數的操作。

三、實體類

至於數據庫交互,與數據庫表或者文檔中的字段一一對應,不多不少;在新增數據,更新數據時使用該類。

四、模型類

與前端交互,前端需要哪些屬性,模型類中就應該有哪些屬性。

其實大部分情況系,模型類和實體類的屬性字段相差不大,或者說可能一模一樣,那麼在這種情況下有必要分實體類和模型類嗎?答案是肯定的,之所以有這兩個層級,就是爲了將保存數據和前端交互分隔開。考慮一種情況,當前實體類和模型類字段一模一樣,那麼不久之後因爲業務的變更,模型類字段突然發生了大改變,但是保存的數據還是和之前一直,那麼,如果最開始不區分實體類和模型類,都用同一個類,這個時候這個類的定義就會模糊了,因爲這個類的字段是數據庫表中的字段和前端需要的字段的融合,而且因爲修改了這個類,可能會對於數據的保存和查詢都產生影響。但是如果一開始就區分了,那麼只需要修改模型類,對保存數據這部分是沒有任何影響的。

五、服務類

提供一組功能,完成某個模塊的所有功能,主要是對業務邏輯的處理

六、Controller類

與前端交互,只負責對前端數據的傳遞,接收和返回,不參與數據的處理、加工

七、mapper或者dao類

只與數據庫交互,儘量不參與數據的加工。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章