2017年末,聊聊現在的三層架構

来源:http://www.cnblogs.com/rocketRobin/archive/2017/10/19/7692572.html
-Advertisement-
Play Games

這幾天在知乎看到了許多關於濫用三層的討論,很多觀點都暗指三層架構這東西太Low了。Low嗎?其實不然。我們覺得三層Low主要是因為三層太簡單了,人們往往不理解三層的思想和目的,濫用三層,加之一些劣質程式員為其加上些自認牛逼的更改搞個五六七八層,代碼寫得又爛,結果看起來就很Low,於是人們就把鍋扣到三 ...


  這幾天在知乎看到了許多關於濫用三層的討論,很多觀點都暗指三層架構這東西太Low了。Low嗎?其實不然。我們覺得三層Low主要是因為三層太簡單了,人們往往不理解三層的思想和目的,濫用三層,加之一些劣質程式員為其加上些自認牛逼的更改搞個五六七八層,代碼寫得又爛,結果看起來就很Low,於是人們就把鍋扣到三層頭上。

  那麼三層的目的是什麼,意義在哪裡呢?其實三層的出發點是“關註點分離”,三層是“關註點分離”思想的一種實現或者說體現。許多用三層的人往往不理解這一點,甚至為了讓項目看起來高大上,還要再多加幾層,再加個Bll介面、Dal介面什麼的,美其名曰N層架構,看到這我想大家都要吐了,太Low了,簡直是太Low。人們已經忘記了為什麼要用三層了,思想已被束縛住。

  那麼怎麼改?不用三層了嗎?那我們用什麼?業務和數據訪問寫一起嗎?當然不,現在三層被唾棄,主要原因是因為三層還是十年前(這隻是個比喻)那個三層,十年和現在寫的代碼和寫代碼的方式變化巨大,用十年前的辦法解決現在的問題,顯然有bug。

  技術日新月異,那年的三層是為瞭解決代碼太多,太混亂,現在呢,前後端分離,數據訪問有ORM,代碼沒那麼亂了,我們的架構也應該跟著改進。比如你的項目里用的EF那麼就可以考慮去掉數據訪問層,因為EF大大減少了數據訪問的代碼(我看eShopOnContainers里就是),以前的一個方法,用EF可能只有一行而已。而我現在用Dapper,代碼量還是有的,因為SQL格式化占行很多,都寫在邏輯里還是不合適。

  大家可以看看微軟的eshorpOnContainers項目的代碼,裡面沒有分層,但是也是按照“關註點分離”的方式分了文件夾,也可以說它只是分了兩層。的確,我們一定要保留層的概念嗎?其實不一定,想想我們過去的多層結構里有什麼層,表示層、業務邏輯層、數據訪問層、通用層、模型層。你看一個基本的多層架構就有5層,好吧,這些都是層嗎?仔細想想其實不是,通用層和模型成是貫穿的,不應該算作層。寫到這裡我去看了我過去寫的採用三層的項目,只看Common一層,我發現,這裡的方法、類都是特定的,特定用於某一層的,比如md5這個只有bll用的到,IsEmail等方法也只有bll用的到。所以我們可以把Common一層刪掉,屬於哪個層的代碼,放回到那一層。比如可以在Dal和Bll里各寫一個 internal  的Common(名字就隨便起啦)類用來包裝屬於這一層的通用代碼,internal保證不會和其它層衝突。我看eShop里也沒有什麼Common之類的項目,只是在一些項目里會有一些類,用來封裝這個程式集本身會用到的東西。

 

  最近看了看IdentityServer4的源碼(很少量),我發現了它和微軟代碼的一些共同處,其中之一就是Services,這裡麵包含了業務邏輯的代碼。這就提示了我們:“是時候拋棄層的概念了”。是不是,其實N層里真正有層級關係的也只是3層而已,即使再加一個Cache層,比如Redis,那這個層是不是也應該只由Bll層來調用才合適呢,所以我們先拋棄層的概念,把原來層的概念拋棄,項目名字改一改,只用三層的基本概念“關註點分離”來設計項目的機構,那麼項目結構就不是層狀的了,而是塊狀的。

  我們把三層的結構改一改:

  這是一個含有Cache(比如可以用Redis)的架構,你看把Bll改成Service,Dal改成Store是不是看起來變得高大上了呢。

  我來解讀一下這個架構設計: Store和Cache只由Service調用,表示層的各種程式負責收集數據、轉換數據、基本數據驗證(模型驗證),說到數據驗證,現在的Web應用的發展方向就是前後端分離,後端基本就只傳個數據,不再負責渲染,這種模型就像是App了,用戶瀏覽網頁其實是我分發個html客戶端給他。而且在驗證數據的時候,現在幾乎沒有不用前端驗證的吧,無論是web和app,那麼後端驗證數據就不用搞一個複雜的結果給前端,只要告訴前端“不對,數據不對”,說個大概就行了,因為正常用戶不會繞過前端驗證,不繞過前端驗證服務端驗證就不會有問題,所以使用簡單的消息告知前端有錯誤。那麼現在表現層的任務就簡單了:收集數據、基本驗證、轉換傳出數據。

  Service模塊繼續承擔以前業務邏輯層的功能,搞搞業務邏輯,比如用戶要數據,Api先搞一搞,看看身份啊,  Id啊什麼的有沒有什麼問題,然後Service先驗證關鍵數據(就是不是基本類型的,和邏輯緊密相關的,比如某個東西存不存在什麼的),然後去Cache搞一搞,沒有再到Store里搞一搞,最後搞點數據給後端Api,Api序列化之後再傳回去。

  其實我們還是分層了,而且就是三層,服務端的三層,變化就是我們明晰了層的意義,一個層也不一定只裝一類代碼,分層的依據也變了,現在是調用關係主導分層,不再是過去的固定模式了。

  你也可以這樣理解,整個程式只有兩層,一層是Api用於暴露給,遠端的Client,Service是一層,處理業務邏輯,Service用Store處理存儲在資料庫中的數據,用Cache處理緩存。而Model將它們聯繫在一起,使其成為一個monolithic程式(對,就是那個談微服務是談到那個monolithic),說到這裡又想說在eShopOnContainers項目里的微服務,那個Web程式在讀取數據的時候是去掉相應的Api通過Http去另一個App去拿取數據。需要Catalog就找CatalogApi要,需要什麼就找什麼Api去要。寫到這裡你應該能想到這篇文章一直在討論的真正的東西“關註點分離”,你可以多種角度去觀察一個項目/產品/網站,用不同的方式去歸類。

  

  你看這個改進的三層架構,如果以模塊的角度看,它就不是三層了,去掉了哪些無用的東西,沒有定式,結構看起來還挺實用。

  一些的架構設計或者其他框架(比如說最容易和三層混淆MVC)的設計都很像三層,因為他們都有體現關註點分離,而且電腦里離不開數據和界面顯示和邏輯。所以大家看起來都有三層的影子,或者說互相像互相,只是應用三層太廣泛了。

  分層就像是橫切,微服務就像是縱切,複雜一點的就是交叉切,整個系統變成一個一個的微粒,難道我們編寫大型應用的最終形態就是微服務? 也許吧。可能當一個系統足夠大的時候,橫切分層就不太管用了,每一層的代碼量也變得巨多,團隊協作也難了。這時候拆分微服務就太恰當了,這幾天看到博客園裡某園有說到:“誰都不會用三層寫Hello world”(大意是這個),他說的對,我們設計架構的時候,要考慮我們系統的體量,太大了就得拆,最終就是拆成顆粒,基本上就是微服務了。但是不大就沒必要,微服務成本也是有的,只有系統大過某一程度(這個程度自己考量,據我觀察這個程度值並不是很高)的時候,微服務帶來的利益才會高出成本,微服務價值才能得到體現。上述中用模塊(塊、顆粒)的概念重新描繪整個架構,我斯認為這是一種像微服務架構靠攏的表現。

  我看eShop的源碼量也很少,我想看看微軟是如何寫項目的,高級程式員的架構是如何設計的,能給我的開髮帶來什麼啟發,所,以希望大家也能去看看。
  縱觀現有的各種框架 mvc mvp mvvm 還有什麼麽其它的,他們的設計方式似乎後符合“關註點分離”這一思想,那麼為什麼?那就得思考關註點分離能帶來什麼?分組開發,專人專事,擅長搞前端的去搞前端,擅長P圖的去P圖。提高每個人的效率,而又能讓整個系統完美的運轉起來,這就是我對於關註點分離的理解。

  話說回來,三層真的用不得了嗎?不知道,我覺得改改還能用,先把“層”的概念放一放,三層的目的是關註點分離,我們可以直接從此來思考架構設計,而不必一定將架構設計成一層一層的。
  鑒於我的理解,我在架構設計中,會關註適用性以及目的,對基本架構做出改變。加勒比海盜中有一句臺詞令我印象深刻:“法典只不過是一些指導,它並不是必須遵守的規定”。我們不能被框架/架構束縛住,普適性原則不是規定,它總是可以變的。

  哦,最後我還建了個上面所設計改進版的項目,貼個圖。註:我還沒有實際應用過這個設計,如果你要參考,那麼請想好了再參考

 

 

 


  歡迎大家加入.NetCore學習交流群 群號:180537383  

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1)POP--面向過程編程(Process-oriented programming ): 面向過程編程是以功能為中心來進行思考和組織的一種編程方法,它強調的是系統的數據被加工和處理的過程,在程式設計中主要以函數或者過程為程式的基本組織方式,系統功能是由一組相關的過程和函數序列構成。面向過程強調的是 ...
  • 以下總結出自己在學習python期間常用的網址或者資源,其中包括很多人的博客,方便自己從這個入口查找資源。 1.https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/ (廖雪峰的官方網站 ...
  • MORE+ 這段代碼執行時會發生錯誤,如題。 原因在於:new.href 使用java 的關鍵字,把new改成news後就不再報錯。 ...
  • java特點; 1.面對象性 2.可移植性/跨平臺性 java組成; jdk(java工具開發工具包) / \ \ jre 指令集合 api和常用java包 (運行環境)(編輯器) / jvm(java虛擬器) java執行過程:java文件〉編輯器(javac)〉class文件〉jvm(解釋執行) ...
  • 題目描述 Farmer John最近為奶牛們的圖書館添置了一個巨大的書架,儘管它是如此的大,但它還是幾乎瞬間就被各種各樣的書塞滿了。現在,只有書架的頂上還留有一點空間。 所有N(1 <= N <= 20,000)頭奶牛都有一個確定的身高H_i(1 <= H_i <= 10,000)。設所有奶牛身高的 ...
  • 什麼是策略者模式? 策略模式是針對一組演算法,將每個演算法封裝到具有公共介面的獨立的類中,從而使它們可以相互替換。策略模式使得演算法可以在不影響到客戶端的情況下發生變化。對演算法的包裝,是把使用演算法的責任和演算法本身分割開,委派給不同的對象負責。策略模式通常把一系列的演算法包裝到一系列的策略類裡面。用一句話慨括 ...
  • 制定 BB 鳥規則時需遵循的規範: • 只包含不可變的規則,而不是籠統的說明• 總是把規則提煉成最簡單的表達• 總是首先說明規則是什麼,再說明“如果不這樣,那麼會如何”• 每個規則必須包含以下詞中的一個——總是、永遠不要、只有、每一個、不要、要 設計系統的規則列表: • 永遠不要給佈局的子內容強加內 ...
  • 1.- DRY: Don’t repeat yourself. DRY 是一個最簡單的法則,也是最容易被理解的。但它也可能是最難被應用的(因為要做到這樣,我們需要在泛型設計上做相當的努力,這並不是一件容易的事)。它意味著,當我們在兩個或多個地方的時候發現一些相似的代碼的時候,我們需要把他們的共性抽象 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...