<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          dotNET Core:編碼規(guī)范

          共 4641字,需瀏覽 10分鐘

           ·

          2020-09-15 02:47

          在項目開發(fā)過程中,由于時間緊、任務(wù)重,很容易導(dǎo)致面向功能編程。實現(xiàn)相同的功能,代碼可以寫的很優(yōu)雅,也可以寫的很晦澀和復(fù)雜。現(xiàn)在的工作,都需要進(jìn)行團(tuán)隊協(xié)作,代碼就需要有一定的規(guī)范進(jìn)行指引,因為我們需要寫出讓人可以輕易讀懂的代碼,而不僅僅是機(jī)器。

          規(guī)范沒有絕對的標(biāo)準(zhǔn),遵循大部分人都認(rèn)可的一種方式就可以了,保持統(tǒng)一。比如在 dotNET Core 中,我們可以參考下 dotNET Core 的源碼,最終制定一個適合團(tuán)隊的規(guī)范即可。

          下面是我理解的正確的一些規(guī)范:

          基本準(zhǔn)則

          1、命名的規(guī)范分為兩種:Pascal(大駝峰)和駝峰(小駝峰),示例如下:

          ? Pascal:UserName
          ? 駝峰:userName

          2、命名要有意義,需要看到名稱知其含義。少用拼音和匈牙利命名法。

          示例
          Int price=20;
          UserInfo userInfo=GetUserInfo(userId);
          Int p=20;×
          Int intPrice=20;×

          3、對于類的成員變量,用this關(guān)鍵字,增強(qiáng)代碼可讀性。
          4、對于基類的成員變量,用base關(guān)鍵字,增強(qiáng)代碼可讀性。

          名稱規(guī)范

          好的名稱可以讓我們減少很多不必要的注釋,可以讓代碼閱讀者很容易就理解代碼的意思。但命名不是一件容易的事情,在命名的時候,通常伴隨著我們對代碼邏輯的思考。比如:如果你不能給一個函數(shù)很準(zhǔn)確地命名,那可能這個函數(shù)的職責(zé)不單一,做的事情太多,才導(dǎo)致一個名稱很難概括,意味著代碼可能需要重構(gòu)。好的命名是我們寫好代碼的基礎(chǔ)。

          命名空間

          命名空間采用Pascal命名法:

          namespace?Fw.Application{}
          namespace?Fw.SmartFlow.Acitivity{}

          實際工作中,我們會將很多邏輯上屬于同一類的文件,在物理上分成不同的目錄,這時建議修改命名空間為相同的命名空間。

          類采用Pascal命名法:

          public?class?UserService{}

          類是對屬性和方法的封裝,類有很多的種類:

          • 跟數(shù)據(jù)庫表對應(yīng)的實體類

          • 處理業(yè)務(wù)邏輯的業(yè)務(wù)類

          • 提供擴(kuò)展方法的擴(kuò)展類

          • 接口層的數(shù)據(jù)傳輸類

          不同的種類可以約定俗成地進(jìn)行一些名稱的約束,比如擴(kuò)展類用 Extension 結(jié)尾、接口層的使用 Request、Response 結(jié)尾,等等,這樣在閱讀代碼時就知道什么類的職責(zé)是什么。

          接口

          接口采用大寫I+Pascal命名法:

          public?interface?IUserService{}

          方法

          方法采用Passcal命名法:

          public?string?GetUserName(){}

          方法的命名需要比較具體,越抽象的名稱越難以理解。例如,InitData() 就是一個不太好的名稱,改成 InitConfiginfo() 會更好些。另外,方法的命名在同一類型的語義下要保持一致,在一些項目中看到查找類的方法,有 GetXXX、QueryXXX、FindXXX 等等。五花八門的方式會提升閱讀的成本。

          變量

          變量分為:類變量、靜態(tài)類變量、只讀變量、靜態(tài)只讀變量、方法變量。

          類變量:

          private?string?_userName;

          類變量只能使用 private 修飾符,如果需要暴漏出去,或是給子類使用,使用屬性來進(jìn)行封裝。

          靜態(tài)類變量、只讀變量、靜態(tài)只讀變量:

          private?static?readonly?ResourceManager?_resourceManager;
          public?static?readonly?IRouter?Instance?=?new?MockRouter();

          ? 修飾符為 private: _ + 駝峰命名法;
          ? 修飾符為 public: Pascal 命名法;
          ? 修飾符為 protected:Pascal 命名法;

          方法變量:

          bool?isCheck;

          常量:

          常量采用Pascal命名法:

          public?const?string?AuthorizationFilter?=?"Authorization?Filter";

          屬性:

          屬性采用 Pascal 命名法:

          public?BasicApiContext?DbContext?{?get;?}

          參數(shù)

          參數(shù)采用駝峰命名法:

          public?List?GetBizAppList(string?userId,DeviceType?deviceType)

          注釋規(guī)范

          注釋是一把雙刃劍,當(dāng)代碼中存在大量的注釋的時候,我們第一反應(yīng)會先看注釋,并會默認(rèn)注釋中寫的內(nèi)容是對的,真實情況是注釋往往會給我們錯誤的指導(dǎo)。有兩個原因:

          • 當(dāng)代碼邏輯發(fā)生變化時,只修改了代碼,注釋沒有調(diào)整;

          • 不同的人員都對注釋進(jìn)行編輯,慢慢注釋會變得和代碼不匹配。

          Martin Fowler 在他的經(jīng)典書籍 《重構(gòu)》 中也提到過多的注釋是一種壞味道的體現(xiàn),他認(rèn)為,當(dāng)你覺得需要寫注釋的時候,應(yīng)該先想想是不是可以進(jìn)行重構(gòu)。那是不是程序中就不應(yīng)該出現(xiàn)注釋呢?當(dāng)然不是,我認(rèn)為下幾種情況是需要寫注釋的:

          • 時間緊急,臨時寫的一些 ”爛代碼“,需要寫注釋,說明原因,一般需要加上 TODO ;

          • 復(fù)雜算法類的方法,可以寫注釋說明邏輯;

          • 寫的是偏底層的類庫,對外暴露的方法需要寫注釋,調(diào)用方能方便在智能提示中顯示;

          • 如果你的能力寫不好代碼,那還是先把注釋寫上吧。

          異常規(guī)范

          • 異常的目的是用來報告錯誤,這也是他的唯一目的,所以避免在返回值中來返回錯誤信息,所有的地方都應(yīng)該使用拋異常的方式來報告錯誤;

          • 使用拋異常的方式可以防止錯誤的操作繼續(xù)執(zhí)行;

          • 要能夠預(yù)估到會出現(xiàn)什么異常,知道是什么類型的異常,才 Try 住做相關(guān)的處理;

          • 最終用戶友好和對開發(fā)者友好;

          • 暴漏問題比隱藏問題要好,隱藏問題只會導(dǎo)致更嚴(yán)重的問題。

          詳細(xì)的異常處理可以參考之前的文章:

          • dotNET:怎樣處理程序中的異常(理論篇)?

          • dotNET:怎樣處理程序中的異常(實戰(zhàn)篇)?

          空行規(guī)范

          空行規(guī)范是一個很簡單的規(guī)范,就是在每個方法中,代碼應(yīng)該按照不同邏輯的邏輯塊進(jìn)行分割顯示,雖然簡單,但如果不注意,還是會對代碼的閱讀帶來很大的障礙。下面看看 dotNET Core 的源碼 CreateDefaultBuilder 方法:

          public?static?IHostBuilder?CreateDefaultBuilder(string[]?args)
          {
          ????var?builder?=?new?HostBuilder();

          ????builder.UseContentRoot(Directory.GetCurrentDirectory());
          ????builder.ConfigureHostConfiguration(config?=>
          ????{
          ????????config.AddEnvironmentVariables(prefix:?"DOTNET_");
          ????????if?(args?!=?null)
          ????????{
          ????????????config.AddCommandLine(args);
          ????????}
          ????});

          ????builder.ConfigureAppConfiguration((hostingContext,?config)?=>
          ????{
          ????????var?env?=?hostingContext.HostingEnvironment;

          ????????config.AddJsonFile("appsettings.json",?optional:?true,?reloadOnChange:?true)
          ??????????????.AddJsonFile($"appsettings.{env.EnvironmentName}.json",?optional:?true,?reloadOnChange:?true);

          ????????if?(env.IsDevelopment()?&&?!string.IsNullOrEmpty(env.ApplicationName))
          ????????{
          ????????????var?appAssembly?=?Assembly.Load(new?AssemblyName(env.ApplicationName));
          ????????????if?(appAssembly?!=?null)
          ????????????{
          ????????????????config.AddUserSecrets(appAssembly,?optional:?true);
          ????????????}
          ????????}

          ????????config.AddEnvironmentVariables();

          ????????if?(args?!=?null)
          ????????{
          ????????????config.AddCommandLine(args);
          ????????}
          ????})
          ????.UseDefaultServiceProvider((context,?options)?=>
          ????{
          ????????var?isDevelopment?=?context.HostingEnvironment.IsDevelopment();
          ????????options.ValidateScopes?=?isDevelopment;
          ????????options.ValidateOnBuild?=?isDevelopment;
          ????});

          ????return?builder;
          }

          想想看,上面代碼中如果去掉空行會讀起來是什么樣的感受?

          日志規(guī)范

          在一個完整的系統(tǒng)中,日志非常的重要。在 dotNET Core 中自帶了日志功能,當(dāng)然我們也可以使用第三方的 NLog、Serillog 等。

          這些日志框架都提供日志級別功能,比如:INFO、DEBUG、WARN 和 ERROR 等,這些級別對程序出錯時的排查非常有用,所以在記錄日志時一定不要都使用 INFO 或者都使用 ERROR 了。

          除了級別,日志的類型有這么幾類:

          • 操作日志

          • 業(yè)務(wù)日志

          • 錯誤日志

          操作日志

          系統(tǒng)中所有的操作的都記錄下來,包括登錄、數(shù)據(jù)的增刪改等,主要用來做審計,數(shù)據(jù)異常操作時的追責(zé)等。

          隨著時間的推移,日志的數(shù)據(jù)量會越來越大,所以需要考慮存儲的方式,比如階段性地將歷史日志進(jìn)行存檔。

          業(yè)務(wù)日志

          用戶在界面中輸入數(shù)據(jù),點擊一個按鈕,程序中會進(jìn)行一系列的處理最終返回結(jié)果給用戶,在這個過程中對一些關(guān)鍵的業(yè)務(wù)信息進(jìn)行記錄,可以在系統(tǒng)出現(xiàn)問題時方便排查和追蹤。

          錯誤日志

          錯誤日志的主要目的就是排錯,所以記錄的信息一定要是對排錯有幫助的信息,盡可能地記錄詳細(xì),比如整個堆棧信息、調(diào)用鏈等。比如,你去進(jìn)行錯誤排查時,發(fā)現(xiàn)記錄的信息是”未將對象引用到對象的實例“,你依然不知道錯誤的原因是什么。

          總結(jié)

          談及代碼的時候,都會去聊架構(gòu)、模式,這些固然重要,但編碼習(xí)慣和規(guī)范也不可小視。一份產(chǎn)品的代碼怎樣才能變得越來越好,這需要團(tuán)隊每個人成員共同的努力,一個人掉鏈子,很容易就形成破窗效應(yīng),導(dǎo)致壞味道越來越多。

          寫好的代碼,是每個有追求的技術(shù)人的使命和職責(zé)。

          希望本文對您有所幫助。

          瀏覽 33
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  非洲婬乱a一级毛片多女 | 亚洲无圣光豆花 | 久久黄色视频免费观看 | 大鸡吧精品网 | 操操网|