《代碼整潔之道》 之第七章 錯誤處理

要點簡介

  • 為什么要使用異常而不是返回碼(if-else)
  • 主流語言對待受檢異常和非受檢異常態(tài)度和處理方式
  • 拋出異常的注意事項
  • 如果不想使用異常(不打斷流程)應該怎么處理
  • null值的處理

一、判斷和異常的取舍問題

剛寫Java代碼時,我也有一個疑問,就是為什么要有異常這個東西。比如要訪問一個文件,如果文件不存在完全可以通過if-else進行判斷。
現(xiàn)在,其實有了更深的理解。就是簡單的if-else其實也可以。但是在復雜情況下,如:代碼段7.1,有很多狀態(tài)需要判斷的時候,代碼就會顯得雜亂無章。
正常情況下,if-else應該用于表現(xiàn)程序邏輯,業(yè)務代碼。但是按照下面的寫法,業(yè)務代碼和錯誤判斷(包含很多前置檢查)就有可能混為一談。不好區(qū)分。

代碼段7.1
public class DeviceController {
    public void sendShutDown() {
        DeviceHandle handle = getHandle(DEVl);
        // Check the state of the device
        if (handle != DeviceHandle.INVALID) {
            // Save the device status to the record field
            retrieveDeviceRecord(handle);
            // If not suspended, shut down
            if (record.getStatus != DEVICE.SUSPENDED) {
                pauseDevice(handle);
            } else {
                logger.log("Device suspended.Unable_to_shut_down" );
            }
        } else {
            logger.log("Invalid handle for: " + DEVI.toStringO);
        }
    }
}

所以,下面 代碼段7.2 所示就會更簡潔和優(yōu)雅.異常檢查和業(yè)務邏輯相互獨立.

代碼段7.2
public class DeviceController {
    public void sendShutDown() {
        try {
            tryToShutDown();
            /*以及很多業(yè)務代碼*/
        } catch (DeviceShutDownError e) {
            logger.log(e);
        } catch (OtherError e) {
            logger.log(e);
        }
    }
}

二、推薦使用不可控異常(unchecked Exception)

目前,C#、C++、Python、Ruby都不再(或從未)支持或受檢異常。因為其違反了開放\閉合原則,即如果在某層次方法里面拋出了受檢異常,那么其上層除非catch住,否則都要重重拋出此異常。完全的耦合了。
所以現(xiàn)在的建議是:
一般應用開發(fā)僅考慮拋出unchecked Exception,關鍵代碼庫,則可考慮checked Exception

三、拋出異常的注意事項

你拋出的每個異常,都應當提供足夠的環(huán)境說明,以便判斷錯誤的來源和處所。在Java中,你可以從任何異常里得到堆棧蹤跡(stacktrace);然而,堆棧蹤跡卻無法告訴你該失敗操作的初衷。應創(chuàng)建信息充分的錯誤消息,并和異常一起傳遞出去。在消息中,包括失敗的操作和失敗類型。如果你的應用程序有日志系統(tǒng),傳遞足夠的信息給catch塊,并記錄下來。

另外,補充一點,拋出異常之前,應該記錄日志,否則你可能無法找到異常的拋出地點。如代碼段7.3

代碼段7.3
if (record.getStatus != DEVICE.SUSPENDED) {
        log.error("原因-異常");
        throw new BusinessException("message","Detail");
    } 

四、可不可以不使用異常呢

五、不要返回和傳遞null值

5.1不要返回null值

不要返回null值的原因:
(1)返回null值會導致程序中充滿對null的判斷;
(2)如果不注意對null的判斷,則會導致很不友好的空指針異常;
針對這個問題也搜了一下,辯證的看到處理方法:
(1)對于集合和數(shù)組作為返回值,使用長度為零的數(shù)組或者空集合,而不是null;
(2)字符串作為返回值,使用空字符串來代替null;
(3)當空對象與其他返回對象有一樣的行為和意義時,使用空對象;
關于這一條的理解目前,我還沒理解到,這里暫時做一個標記,期望后續(xù)可以理解

例如,有一個方法返回一個迭代器。一個空的迭代器可以定義為NullIterator并實現(xiàn)Iterator接口,他的next方法永遠返回null,他的hasNext方法永遠返回false。這樣,使用這個方法返回值的代碼就不要進行null判斷,因為NullIterator的行為與其他迭代器一樣。

(4)針對這個規(guī)則的例外任何在邏輯上表示查找(search或者get)的意思時,應該返回null;代碼段7.4 說明了為什么應該例外處理;

代碼段7.4
User getUserById(String id){
   User user = dao.getUserById(id);
   if(user == null)
      return new User();
   return user;
}

5.2不要傳遞null值

不傳遞null值的意思,即不要在方法調用時,將參數(shù)設置為null。這將會帶來更不可預料的后果。
但是如果程序中如果卻需要對null值進行判斷,可以拋出InvalidArgumentException或者使用斷言來處理(而不是僅僅忽略null值)。

代碼段7.5
    public double xProjection(Point p1, Point p2) {
        if (p1 == null || p2 == null) {
            throw InvalidArgumentException ("Invalid argument for MetricsCalculator.xProjection");
            }
            return (p2.x - pl.x) * 1.5;
        }
    }
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,503評論 0 13
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,623評論 18 399
  • 一、Java 簡介 Java是由Sun Microsystems公司于1995年5月推出的Java面向對象程序設計...
    子非魚_t_閱讀 4,538評論 1 44
  • 勇敢的面對生活 漸漸失去了年輕的銳利 被生活磨平了棱角 甚至失去面對未來的勇氣 時常為過去懊悔惋惜 為將來焦慮不安...
    白色野薔薇閱讀 176評論 0 0
  • 1.Angularjs單選框相關 http://www.itdecent.cn/p/8d644980ef96 2....
    ZZES_ZCDC閱讀 550評論 0 0

友情鏈接更多精彩內容