<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>

          程序員過關(guān)斬將--錯誤的IOC和DI

          共 6848字,需瀏覽 14分鐘

           ·

          2021-05-15 22:06

          什么是IOC?

          什么是DI?

          IOC和DI有什么關(guān)系?

          作為程序員,天天擼代碼,怎么能不知道IOC和DI呢。很多面試官也喜歡問這兩個概念,雖然概念很簡單,但是可以從面試者的回答當(dāng)中,大體的可以估算到面試者的功力,那IOC和DI到底是何方神圣呢?讓我們來一步一步扒掉它的外衣!!

          說到IOC和DI,必須要提一下軟件設(shè)計的六大原則

          單一職責(zé)原則

          一個類應(yīng)該只有一個發(fā)生變化的原因

          開閉原則

          軟件實體應(yīng)該是可擴(kuò)展,而不可修改的。也就是說,對擴(kuò)展是開放的,而對修改是封閉的。這個原則是諸多面向?qū)ο缶幊淘瓌t中最抽象、最難理解的一個。

          里氏替換原則

          所有引用基類的地方必須能透明地使用其子類的對象,換句話說,子類在任何引用基類的地方都可以替換成子類。

          依賴倒置原則

          這個原則說的詳細(xì)一點其實可以概括為兩點:

          1. 高層模塊不應(yīng)該直接依賴于底層模塊,應(yīng)該依賴于抽象
          2. 抽象不應(yīng)該依賴于具體實現(xiàn),具體實現(xiàn)應(yīng)該依賴于抽象
          接口隔離原則

          程序不依賴于不使用的接口,換句話說,一個程序只依賴于它需要的接口。

          我在之前的很多文章中也多次提到,要想系統(tǒng)保持高擴(kuò)展性,始終離不開對業(yè)務(wù)的深刻理解和抽象

          論系統(tǒng)設(shè)計的高可擴(kuò)展性

          IOC

          控制反轉(zhuǎn)(Inversion of Control,縮寫為IoC),是面向?qū)ο缶幊讨械囊环N設(shè)計原則,可以用來減低計算機(jī)代碼之間的耦合度

          以上是IOC最典型的概念定義,其中“控制”這個詞具有很泛的概念,比如:控制對象的初始化,控制程序的流程,控制資源的生命周期...等等,反轉(zhuǎn)就和表面意思一樣比較好理解,就是反過來。控制和反轉(zhuǎn)綜合起來呢,可以概括為:

          對于程序的行為,把控制權(quán)交給其他人

          確實不好理解,因為上面這句話是我自己總結(jié)的,說實話,我自己咋一聽到都理解不了。還是舉個栗子吧:

          最常見并且最常用的莫過于類的使用,如下代碼:

          class A
          {
              public void XXOO(){

              }
          }

          class Main
          {
              A a=new A();
              a.XXOO();
          }

          上面的代碼我想在我們平時的coding過程中非常多,那有什么問題嗎?還是那句話,從功能性的角度來說,只存在正確和錯誤的觀點,但是從非功能性的角度來說,每個人有每個人的見解。有的人不喜歡代碼中中到處充斥著New的味道,有的人卻喜歡掌控自己的代碼(因為自己寫的New,自己最清楚)。

          至于軟件編寫的對與錯,并沒有一個明確的規(guī)范去說明,但是軟件從小到大,從簡單需求到越來越多的需求,把軟件開發(fā)過程中一些不爽的詬病提取出來并解決,就是軟件質(zhì)量提升的一個度量角度。

          言歸正傳,上面的代碼以多數(shù)程序員的角度來說,不喜歡到處有New這個關(guān)鍵字,就好像New多了會出Bug一樣!!為什么好多架構(gòu)師不推薦到處有New的味道?我認(rèn)為并不是代碼美不美觀,能不能裝X的問題,是因為軟件架構(gòu)層次中強(qiáng)依賴的關(guān)系。

          那怎么破除強(qiáng)依賴呢?

          DI(依賴注入)

          與IOC不同,DI是一種具體的編碼技巧。但是,它并非為了解決New的問題而生,而是為了解決軟件架構(gòu)層面的問題而生,其實,從大多數(shù)使用場景來說,DI確實可以看做是實現(xiàn)IOC的一種解決方案。

          有的架構(gòu)師說,依賴注入就是把類放到容器當(dāng)中,然后解析這些類的實例。我不否認(rèn)原理上確實是容器來負(fù)責(zé)管理有依賴關(guān)系的模塊或者類(接口),但是依賴注入在依賴關(guān)系上其實在為了解耦和多態(tài)。

          說到這里,突然想起一件小事,作為高大上工作的開發(fā)者,都已經(jīng)跨入21世界20多個年頭了,還在圍繞著數(shù)據(jù)庫進(jìn)行coding,在沒有表的情況下居然沒辦法開展工作?我并不排斥圍繞數(shù)據(jù)庫進(jìn)行設(shè)計編碼,因為很多統(tǒng)計類的需求確實需要這樣,但是大多數(shù)業(yè)務(wù)不應(yīng)該是圍繞業(yè)務(wù)來開展編碼嗎?沒有數(shù)據(jù)庫就不能進(jìn)行coding是不是該改一改了?

          依賴注入會在架構(gòu)的擴(kuò)展點出現(xiàn),一個好的軟件架構(gòu),永遠(yuǎn)會在需要擴(kuò)展的地方提供自定義入口,說直白一點,任何一個系統(tǒng)都應(yīng)該在會變化的地方進(jìn)行抽象。舉一個簡單例子:一個支付系統(tǒng)會存在多種支付方式:微信、支付寶、銀聯(lián)等等。這些不同的支付方式其實就可以看做是系統(tǒng)的變化點,應(yīng)該把這個地方進(jìn)行抽象,并花大量精力去好好設(shè)計。

          重點問題

          那么問題來了:如果我沒有使用面向接口(interface)進(jìn)行開發(fā),代碼的分層一律都是以類(Class)來組織的,類似于以下代碼:

           var ret = await UserService.SetDefaultUserPlan(para.UserId, para.UserPlanId);

          那我的類UserService是否也應(yīng)該進(jìn)行依賴注入呢?類似于以下代碼(DI框架可能不一樣,但是原理都是相同的)

           services.AddSingleton<UserService, UserService>();

          我想這個問題,每個人也都有自己的見解。有很多人認(rèn)為,DI解決的是到處充斥著New味道的問題,每個類都應(yīng)該進(jìn)行DI操作,這樣的代碼才夠“簡潔,漂亮”。

          是嗎?

          針對于以上觀點,我其實有話要說。還是本質(zhì)問題的討論,DI到底要解決軟件開發(fā)中的什么問題呢?是New的問題嗎?不,是解耦、擴(kuò)展、依賴的問題。

          說道這三個非功能性的指標(biāo),其實和上邊講的幾大軟件設(shè)計規(guī)則息息相關(guān),無論是什么樣的軟件系統(tǒng)都擺脫不了業(yè)務(wù)變化的命運(yùn)。有的程序員最害怕這種變化,因為一旦發(fā)生業(yè)務(wù)變化,他就要改動大量的代碼,接連會產(chǎn)生大量的Bug,進(jìn)而會加大量的班。

          其實,面對變化的時候,如果發(fā)生以上情況,我們應(yīng)該反思自己是不是沒有把業(yè)務(wù)的變化點分析清楚。還是拿支付業(yè)務(wù)為例,假如系統(tǒng)開始只有微信支付,可能你的代碼很像以下這種

           public void Pay(int amount)
                  {
                      //微信支付
                      WXPay.Pay(amount);
                  }

          隨著時間推移,公司業(yè)務(wù)發(fā)展壯大,產(chǎn)品上要支持支付寶支付,你的代碼很大概率會變成這樣

           public void Pay(int payMode, int amount)
                  {
                      if (payMode == "微信支付")
                      {
                          //微信支付
                          WXPay.Pay(amount);
                      }
                      else if (payMode == "支付寶支付")
                      {
                          //支付寶支付
                          AliPay.Pay(amout);
                      }
                  }

          如果隨著業(yè)務(wù)繼續(xù)發(fā)展,產(chǎn)品上又陸續(xù)加入了很多支付方式,你的代碼就會變成以下這種方式

           public void Pay(int payMode, int amount)
                  {
                      if (payMode == "微信支付")
                      {
                          //微信支付
                          WXPay.Pay(amount);
                      }
                      else if (payMode == "支付寶支付")
                      {
                          //支付寶支付
                          AliPay.Pay(amout);
                      }
                      else if (payMode == "XX支付")
                      {
                          //支付寶支付
                          XXXPay.Pay(amout);
                      }
                      else if (payMode == "YY支付")
                      {
                          //支付寶支付
                          YYPay.Pay(amout);
                      }
                      .
                      .
                      .
                  }

          大量的if-else,很多人稱之為“壞代碼”味道(其實這樣的代碼每個公司都有)。通過這個例子其實大家已經(jīng)看出來了,支付方式這是一個業(yè)務(wù)的變化點,應(yīng)該在這個業(yè)務(wù)點上做抽象了。這個時候所謂的面向接口編程正是解決之道,其實也可以理解為程序的多態(tài)性:

           interface IPay
              {

                  void Pay(int amount);
              }

          然后每次新加一種支付方式,去實現(xiàn)這個接口,然后利用DI操作一下。在業(yè)務(wù)發(fā)生變化的過程中,根據(jù)某種策略來實現(xiàn)對應(yīng)的支付方式即可。

          在這個例子中,利用DI技術(shù)不僅解決了依賴倒置原則,更解決了系統(tǒng)擴(kuò)展性的問題。回到開頭的問題,為了解決New的美觀問題,到底應(yīng)不應(yīng)該使用DI呢?其實我不推薦

          寫在最后

          關(guān)于上邊的問題,歡迎來噴,畢竟知識需要討論才能進(jìn)步




          挺帶勁!通過 Nginx 來實現(xiàn)封殺惡意訪問


          如何給妹子優(yōu)化 Windows ?


          瀏覽 46
          點贊
          評論
          收藏
          分享

          手機(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>
                  日韩中文足交系列 | heyzo91 | 久热久 | 欧美成人免费在线视频 | 亚洲超级高清无码第一在线视频观看 |