零基礎ASP.NET Core WebAPI團隊協作開發

sylla發表於2019-07-17

零基礎ASP.NET Core WebAPI團隊協作開發

相信大家對“前後端分離”和“微服務”這兩個詞應該是耳熟能詳了。網上也有很多介紹這方面的文章。我這裡提這個是因為接下來我要分享的內容和這個有些關聯。

 

隨著前端應用場景的繁榮,使用者體驗需求的提高,原先傳統的後端渲染頁面返回給前端展示的模式面臨挑戰。後端工作除了處理資料邏輯還得適應介面UI的業務,越來越不堪負重。前端的重要性逐漸體現出來,在這種情況下使用前後端分離模式開發的逐漸增多。

 

前端框架(比如Vue/Angular/React)的發力,大廠的推廣使用,前後端分離已經很成熟。包括傳統資訊化這塊以前使用傳統WebMVC模式的開發BS應用有些都逐步轉為前後端分離模式。特別是開發人員分工之後專注做好各自的工作,效率更高,做出來的產品也就更好。

 

一、應用場景

1瀏覽器端(Vue/Angular/React+服務端API

2桌面客戶端(mfc/winform/wpf+服務端API

3移動客戶端(各種App/App內建瀏覽器)+服務端API

4、其他終端(大資料展示平臺/報表展示平臺)+服務端API

 

客戶端越來越強調輕量化,互動體驗,不在滿足於能用。服務端端只管提供API資料,這樣業務邏輯大多在服務端處理,隨著需求增加服務端的模組會越來越多。但是有些介面是共用的,有些是根據業務變動的,還有的API新舊版本過渡更新替換等等是服務端api要考慮的事情。設計好API開發框架面靈活應對這麼多場景就很有必要了。

 

原先可能會做一個單體式應用,把所有用到的介面都加進去。但這樣粒度很粗,如果某個場景下只使用了部分介面,那也得把這整個應用部署,無法做到按需新增。還有就是可能要修改其中部分方法,需要整體重新編譯釋出。這都存在可能影響其他模組的風險。

服務端任務量大了,怎麼分工?這個時候單體明顯已經不適用了。這裡就引出了微服務。對微服務可能每個人有不同的理解,但有一點是有共識的,就是把一個大的單體式應用根據功能模組拆分,這樣粒度細分之後很多介面就可以共用。之後的修改增加都是可以按需釋出部署,區域性出現問題不會影響整體。

 

這個服務的粒度怎麼拆分也是需要慎重考慮的問題。除了功能拆分還得考慮人員匹配。

案例場景:一個系統有10個子系統(模組),每個子系統(模組)又有10個功能,每個功能再具體又可能有20左右的方法程式碼。

 

這個案例,最後大概有2000個方法程式碼。

如果開始安排10人的團隊開發,中途因為專案緊急再增加了10個人進來,總共變成了20人,專案組怎麼做才能快速適應這種人員變動。

有時候不是人越多越能做好事情,在人員增加情況下除了增加溝通協調成本,實際情況會遇到新加的人蔘與進來的門檻很高,不能快速著手展開工作,有時候還會出現不知道從何入手的困境。這就是因為拆分的不合理,任何的改動可能會影響到他人。這樣雖然為了趕進度加人了,但實際的效果卻不是很理想。

 

二、功能拆分分析

怎麼拆分這有兩個極端例子

1、粒度最粗,全部在一個解決方案(極端例子,類似單體式應用,適合一人開發)

2、粒度最細,細分到每個方法一個解決方案(極端例子,實際肯定不會這樣做)

 

實際專案中功能拆分就是在這兩個極端情況之間找適合的平衡點。具體拆分到多大的粒度,這個就只能是根據具體專案情況具體分析了。但是微服務可能是建議往細的方向拆。

如果是專案型的會發現如果拆的太細,上線一套系統要帶N個介面,運維實施都很麻煩;如果是做平臺型的產品可能就是有限的幾套系統,不會隨著專案鋪開太多定製化。也就沒有了專案型裡面的經常部署實施等繁瑣的問題。

比如上面的案例,一般都是先根據子系統拆分,具體到每個子系統,有一人或多人開發也有後期臨時加入的情況。每個子系統一套介面還是比較合適的。

 

實際情況專案型比較多,考慮實施運維情況拆分的粒度不會太細,讓實施去部署太多業務介面會把他們逼瘋。如果有和我類似情況的下面的方案提供了一種解決辦法。開發時候可以橫向任意擴充套件,新加入的人員分配任務清晰,不用擔心有耦合衝突。釋出部署也不會因為粒度太細,增加部署工作量。總結就是外掛式開發,微服務部署。

 

我們都知道vs裡面建立一個解決方案,兩三個開發人員在同一個解決方案裡面開發,只要協調好還行,如果再加入人員,參與的開發人員一旦多了,就算分工好做各自模組,但還是會存在一個些衝突,比如增加檔案,增加引用等等都會引起專案檔案或者解決方案檔案衝突問題。而且這種情況程式碼許可權還不好細分控制。

 

最好的方式是每個開發人員做的事情都在自己的解決方案裡面,只要是公共使用的引用協調好大家使用統一的版本,其他的自己完全可控,完全不用擔心影響他人,或者他人的修改影響自己。

 

大家可以看下這個 https://github.com/dotnet/corefx/tree/master/src如圖1。

 

1

 

這是dotnet基礎庫的原始碼,每個基礎類庫都是單獨一個解決方案維護,隨便點一個進去看下,如圖2

 

2

每個類庫都有獨立解決方案檔案。

 

微軟肯定有更好的方式去管理,但從這裡可以看出,獨立開發維護的優勢。

 

三、介面專案準備

 

前面分享過一篇《零基礎ASP.NET Core MVC外掛式開發》的文章,那邊文章其實也就是強調團隊開發的時候能做到儘量獨立,可以橫向擴充套件,專案靈活變動增加開發人員可以快速參與,開發之後能彙總到一個個的子系統,最後完成整體開發。在這裡API的開發也可以使用類似方案,因為API沒有檢視部分,處理起來MVC簡單。

 

接下來重點介紹該方案在API開發中的使用。開始這部分內容之前先簡單介紹我這邊API專案開發總結的兩個共性問題:

1、使用swagger顯示API文件(nuget 引用 Swashbuckle.AspNetCore

因為API是沒有試圖的,為了視覺化,以及方便測試,使用swagger作為API的展示介面。具體使用看下面提供的demo程式碼

 

2、使用版本控制API版本號(nuget 引用Microsoft.AspNetCore.Mvc.Versioning

版本控制對API也是同樣重要,看BAT大廠提供的API都是有版本控制的,要向他們看齊。實際應用中,程式不可能維持一套最新,有時候新舊版本需要過渡,所以需要有版本來區分。這裡使用微軟提供的版本控制。具體使用看下面提供的demo程式碼

 

 

這兩個使用這裡就不細說了,穿插下面主題做些簡單介紹,具體看案例demo就可以。

 

四、介面外掛式開發

 

回到我們的主題,這裡重點介紹下一個子系統(模組)任務拆分與人員分工

 

專案組接下一個專案,一般有個開發組長,著手模組劃分並且開發任務分工

組長(公共部分介面+核心功能模組介面)

組員1:細分的模組外掛1介面

組員2:細分的模組外掛2介面

組員3:細分的模組外掛3介面

......

......

 

對於的解決方案結構,具體命名自己可以根據喜好自己自定義。

 

Agile.ModuleName.API  如下圖3

Agile.ModuleName.Plug1.API 圖下圖4

Agile.ModuleName.Plug2.API

Agile.ModuleName.Plug3.API

......

......

 

 

3

 

4

 

Demo使用的是vs2019Asp.net core 2.1

 

注意:如果一個模組裡面介面比較多,一個解決方案裡面不適合團隊開發。所以對這種介面功能比較多,拆成各個外掛方便團隊開發,最後釋出的時候合併到一起。但是如果這個模組介面不是很多,就沒必要過度設計為了外掛化而拆開。

 

每個獨立開發的都是vs裡面建立的標準ASP.NET Core WebAPI專案,這裡主專案和各個外掛專案沒有從屬關係,完全平等API專案開發,最後只是可以匯合到主專案作為一個站點發布交付。各自獨立除錯執行各自開發功能模組,測試沒問題釋出彙總到主專案,部署執行,之後哪個介面問題只需要找到對應的模組修改,完全隔離開,不用擔心修改會影響其他正常使用的模組。

 

 

主專案解決方案結構,如圖5

 

5

 

v1v2裡面的是有版本控制的,放在外面的就不需要版本控制。

還有Extensions資料夾裡面兩個類也是為了版本的顯示做處理,具體看Startup.cs裡面程式碼,如圖6

 

6

 

搭建好之後,主專案執行,選擇v1版本顯示如圖7

 

7

 

如果選擇v2,顯示如圖8

 

8

 

通過上面兩個切換,應該看到不管選擇v1還是v2下面不受版本控制的都會顯示。

 

 

如果把圖4的程式碼註釋掉,看下執行效果,如圖9

 

 

9

顯示就這樣,不能根據swagger選擇,直觀的顯示是v1還是v2。這個就是RemoveVersionFromParameterReplaceVersionWithExactValueInPath兩個類的作用。

 這兩個類的程式碼如下

public class RemoveVersionFromParameter : IOperationFilter
    {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            if (operation.Parameters.Count > 0)
            {
                var versionParameter = operation.Parameters.FirstOrDefault(p => p.Name == "version");
                operation.Parameters.Remove(versionParameter);
            }
        }
    }


public class ReplaceVersionWithExactValueInPath : IDocumentFilter
    {
        public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
        {
            swaggerDoc.Paths = swaggerDoc.Paths
                .ToDictionary(
                    path => path.Key.Replace("v{version}", swaggerDoc.Info.Version),
                    path => path.Value
                );
        }
    }

 

到這裡主專案API執行正常,接下來看下外掛專案API

外掛1專案結構,和主專案類似,如圖10

 

10

單獨執行下這個外掛1專案,效果如圖11

 

11

 

這裡作為外掛API專案同樣有一點要注意,不要出現和其他外掛或者主專案同名的路由(versioncontrolleraction三個完全一樣,分工之後各自命名規範估計這種情況也不會出現,主要還是注意避免合併之後路由重名問題)。

 

這裡先把外掛1編譯的dll放到主專案的執行目錄來,如圖12

 

12

 

並且在主專案的Startup.cs裡面增加這段程式碼,如圖13

 

13

 

執行看下效果,如圖14

 

14

 

匯合成功,外掛1API能展示出來,測試也正常,測試就不截圖了。

同理,外掛1,外掛2...等等也是一樣處理。開發階段,各自開發的功能都是可以獨立除錯執行的。有沒有主專案對各自開發的不影響。

 

 

 

 

五、問題總結

 

如果外掛專案裡面引用了一個第三方的程式集,如圖15

 

15

 

引用一個測試類庫,在Plug1NoVerControllerGet方法裡面寫一個測試程式碼,如圖16

 

16

在外掛專案單獨測試,執行正常。

再把外掛1相關檔案拷貝到主專案,這時候多了個外掛專案自己引用的OtherLib.dll,如圖17

 

17

 

正常執行,如圖18

 

18

 

測試下剛才外掛1裡面用到OtherLib類的介面,看效果如圖19

 

19

 

汗,居然報錯了,提示FileNotFoundException,但是看上面的錯誤資訊截圖提示找不到OtherLib.dll檔案。OtherLib.dll這個檔案明明在這個目錄有的。查了相關資料都說是.net core的載入機制變了,但還是沒理解透徹,不知道.net core3.0會不會解決這個問題。希望有大神看到可以解惑下這個問題。不過這裡我使用一種方式可以解決這個報錯,在主程式這裡加這段程式碼。在註冊外掛專案之前,遍歷所有dll,做一次載入就可以了。如圖20

 

20

 

需要在註冊外掛之前,把所有dll檔案這樣載入一遍,就可以了。

再執行,測試就正常了,如圖21

 

21

 

 

六、釋出執行

各個獨立開發的外掛API,各自獨立開發除錯正常之後,釋出出來。

好了,外掛1,外掛2...等等各自都開發好了,各自模組除錯沒問題,最後彙總到主的專案來,基本也就沒什麼問題了,並且還可以作為一個站點部署。

這裡的一個站點只是一個介面服務,不要理解成一個系統就這一個介面服務,雖然可以這樣做,但不建議,部署還是各個子系統一個服務,這樣數量也不會很多。這裡是指在開發階段對一個子系統(模組)的N個介面做開發方面的分工獨立開發除錯。

子系統(模組)有N個介面,開發分工如下:

主外掛,外掛1,外掛2,外掛3...

全部彙總到主外掛的釋出目錄,或者手動拷貝,最後提供一個完成的子系統介面釋出版本,目錄如圖22

 

22

 

同樣命令列執行,或者宿主到iis,這裡命令列執行,如圖23

 

23

 

瀏覽器開啟,如圖24

 

24

 

直接swagger測試各個介面,正常。

獨立外掛化開發,微服務釋出部署。

 

希望你看了之後有點收穫,程式碼程式下面附件提供

Demo程式

相關文章