主頁 > .NET開發 > [.net] 關于Exception的幾點思考和在專案中的使用(一)

[.net] 關于Exception的幾點思考和在專案中的使用(一)

2021-04-08 08:07:45 .NET開發

關于exception的基本語法和作用,這里不再贅述,下面記錄一下我在專案中關于Exception的一些思考,

一,使用Exception,而不是Error Code

在初始設計專案的時候,有時候我們為了明確錯誤型別,定義如下結構:

enum ErrCode
{
    Ok,
    ArgumentErr,
    OtherErr1,
    OtherErr2
}

class SomeClass
{
    public ErrCode DealSomething()
    {
        //.....
        return ErrCode.Ok;
    }
}

class CallerClass
{
    public void CallSome(SomeClass some)
    {
		ErrCode err = some.DealSomething();
        
		if(err == ErrCode.Ok)
        {
            //....
        }
        else
        {
            //.....
        }
    }
}

使用ErrCode并不是說完全不可以,比如在Web Api呼叫中回傳ErrCode就是不錯的選擇,

1,吃掉例外

但是在其他情況,使用ErrCode會讓使用者痛苦不堪,因為每次呼叫都要小心謹慎的處理和判斷ErrCode,否則就特別容易吃掉例外

對比如下程式片段:

使用ErrCode使用Exception
class SomeClass
{
    public ErrCode DealSomething()
    {
        //.....
        return ErrCode.SomeErr;
    }
}
class CallerClass
{
    public void CallSome(SomeClass some)
    {
		some.DealSomething();
		giveMoney();
	}
}
class SomeClass
{
    public void DealSomething()
    {
        //.....
        if(somthingWrong)
        {
        	throw new SomeException(...);
        }
    }
}
class CallerClass
{
    public void CallSome(SomeClass some)
    {
		some.DealSomething();
		giveMoney();
	}
}

 

左側使用ErrCode因為不小心沒有接受處理ErrCode,導致后續代碼繼續執行;

而使用Exception,即使沒有處理,也不會執行后續代碼,并且拋出等待上層使用者處理,

此外,Exception還有其他眾多好處,比如Stack Trace資訊,跨process等等,

所以Exception的本質就是現成的錯誤處理(error-handling)機制,就不要再去使用自定義的ErrCode了,

二,Exception在專案中的使用

既然明確使用Exception作為我們的錯誤處理方案,那么具體怎么使用呢?

1,使用細化的Exception

首先要避免以下寫法:

class Dal
{
    public void Add(Entity entity)
    {
        //....
        if(somthingWrong)
        {
            throw new Exception("add wrong");
        }
        //...
    }
}

這種寫法的問題在于,呼叫者無法明確Exception的原因,型別,僅僅依靠檔案或者message去理解,當專案越積越多的時候,就是漫天相同的Exception亂飛,日志里充滿了各種神奇的message的時候,

我們可以采取多維度細化Exception:型別、錯誤種類,具體原因,

使用具體型別化的Exception,比如ConnectionException, TimeoutException, 即為每種錯誤定義一個Exception型別,

這種方法想必大家都很清楚,但是如果一個模塊里有十幾種錯誤,而你又有十幾個模塊呢?

對于這種情況有兩種處理方法,

  • 按內部外部劃分

    如果一個例外需要模塊外部呼叫者接收和處理的,那么就定義一個具體的Exception型別,比如ConnectionException,TimeoutException;

    如果一個例外是模塊記憶體自處理的,那么只用同一個InnerException(或者其他名字)加上其他資訊來區分,(是不是又聞到了ErrCode的味道,沒錯),

    這種方法經常在很多開源類別庫中看到,

  • 一個模塊定義一種Exception型別,Exception與ErrCode相結合

    剛說過ErrCode不能用,這里又提到,大家別誤會,仔細往下看,

    比如如下代碼:

    class ErrCode
    {
        public int Code { get; set; }
        public string? Name { get; set; }
        public string? Message { get; set; }
    }
    
    class DalException : Exception
    {
        public ErrCode Code { get; }
        
        public DalException(ErrCode errCode, Exception? innerException = null):base(errCode.Message, innerException)
        {
        	Code = errCode;    
        }
    }
    

    ErrCode已經不簡簡單單是一個enum了,而是有更大的用處,

    這樣每一個模塊都擁有自己Exception型別,每一種錯誤型別又能得到有效的分類,

    這種方法經常在公司專案的業務模塊、基礎框架模塊里用到,

2,使用Exception.Data

上面的代碼段,大家是否有點驚訝,哥們兒,你把Message直接干到ErrCode里面固定起來,是不是有點激進啊,

其實這也是在實際開發中,總結出來的經驗,盡量不要放任程式員們零散的去寫各種Exception的Message,

但是我們可以用Exception.Data來實作更多場景,

比如下面代碼段:

static class ExceptionFactory
{
    public static DalException OnMigrateError(int oldVersion, int newVersion, string sql, string cause)
    {
        DalException ex = new DalException(ErrCodes.MigrationErr);
        
        ex.Data["OldVersion"] = oldVersion;
        ex.Data["NewVersion"] = newVersion;
        ex.Data["Cause"] = cause;
    }
}

class SomeCls
{
    void Migration()
    {
        //.....
        throw ExceptionFactory.OnMigrationErr(oldVersion,)
    }
}

這樣為每種錯誤固定了具體需要記錄的資訊,其中cause就是讓程式員記錄當下的原因,當然了,你可以重寫OnMigrateError來記錄另外一種場景,

把例外Exception具體需要的資訊,記錄在Data這個Dictionary中, 而不是寫到Message中的好處,是有助于今后進一步的處理,比如結構化日志,

當然這帶來了一個需要關注的問題,就是對Exception.Data的顯式處理,因為Exception.ToString()方法,并不列印Data,

在記錄日志方面,如果你使用 Serilog, 那么推薦你使用 Serilog.Exceptions, 他對Exception.Data十分友好,

 

至此,我們在細化Exception上,以此遞進的使用了 型別---> ErrorCode ---> 具體cause

 

3,集中化管理

漫天飛的Exception,不明所以的處理方案,都需要用規則來解決,但是規則需要時刻牢記,所以最靠譜的還是用代碼結構來解決,

首先建立ErrCodes靜態類,然后建立ExceptionFactory類,這樣業務代碼里拋出例外都具有throw ExceptionFactory.XXException()這樣的形式,

//所有的錯誤代碼
internal static class ErrCodes
{
    public static ErrCode MigrationErr { get; } = new ErrCode(1, nameof(MigrationErr), "Error happens in Migration.");
    //........ other errors
}

//所有的Exception都由此生成
internal static class ExceptionFactory
{
    public static DalException OnMigrateError(int oldVersion, int newVersion, string sql, string cause)
    {
        DalException ex = new DalException(ErrCodes.MigrationErr);
        
        ex.Data["OldVersion"] = oldVersion;
        ex.Data["NewVersion"] = newVersion;
        ex.Data["Cause"] = cause;
    }
    //.....其他場景
}

這樣,code review時,只要看到有程式員在代碼中自己 new XXException,那么就督促他在ExceptionFactory里尋找合適的例外場景或者自己添加,

隨著專案積累,即使例外、錯誤種類眾多,大家也只需在ErrCodesExcepionFactory兩個類中,總結歸納,重構,

4,參考代碼

具體的代碼,上傳在 Github, 歡迎探討和指正,

三,預告

在下一篇,我將要探討下關于捕捉例外的話題(這么簡單?),

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/273588.html

標籤:.NET技术

上一篇:[Azure Devops] 使用 Azure Pipelines 實作 CI

下一篇:WPF教程九:理解WPF中的物件資源

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more