主頁 > 軟體設計 > 軟體開發架構模式淺談:一些思考和實踐記錄

軟體開發架構模式淺談:一些思考和實踐記錄

2021-12-13 08:02:23 軟體設計

目錄

零、背景和問題

一、從表現層的MVC談起

1. MVC在經典三層架構里的位置

2. 業界基于MVC模式的不同實踐

2.1 微軟

2.2 蘋果 & 斯坦福

2.3 Martin Fowler

2.4 Google

2.5 MVC和DDD

2.6 小結

二、實際案例結合

1. 常見的資料結構定義和使用

2. 常見的多復雜卡片的串列場景

3. 一個Kotlin跨平臺場景案例

4. 誰對誰錯的務虛討論

4.1 微軟的MVVM,和Angular的MVW

5. 誰對誰錯的務實案例:VIPER和分層演變

5.1 VIPER架構模式的應用

5.2 VIPER架構模式的演變

5.3 進化

5.4 退化

三、寫在最后,回到問題


零、背景和問題

我個人平時會比較慎用“架構”這個詞,

  • 一方面是覺得業界有很多架構大師和架構模式,而我的認知和實踐有限;

  • 另一方面是因為這個詞看著挺高大上、有點務虛,如果不結合實際場景的具體問題來討論,容易陷入“PHP是最好的語言”這樣的辯論賽中,而不同場景中又有各自的問題,程式員們通過自己的理解和思考、針對實際場景對一些架構模式進行了擴展實踐,以此來解決遇到的問題,也會基于同一個模式延伸出一些派生概念,

兵無常勢,水無常形, —— 鏈接為Google搜索第一條,

所以,我個人的觀點是:以要解決的問題為出發點,去討論我們要采用的架構模式(技術方案),

另外,由于我們是站在很多巨人肩膀上的,討論時可以站在一些軟體設計/開發原則的基礎上,

寫這篇文章,我也是從解決一些問題的目的出發的:

  1. 昨天和團隊同學討論了相關話題,雖然大多數同學在實踐上基本一致,但具體到話術、名詞概念和具體使用的理解和實踐上有些差異(這是很正常的,因為業界對同一個模式的理解和實踐也不同),我結合一些實際編碼場景做了一番陳述,為了避免后續重復大費口舌,所以打算寫下來,以后有需要直接發文章鏈接,

  2. 由于我個人的認知和實踐有限,所以也希望能拋(huan)磚(ying)引(lai)玉(pen),讓我學到更多,

  3. 雖然同一個架構模式在不同業務/技術領域的實施會有區別,但同一個團隊內應該保持一致性,因為這樣有助于日常的code review、功能模塊的交接backup等活動,尤其是有利于使用統一的單測建設方案來保障我們的產品質量,

    1. 實際問題:我最近在開發商家合并發貨的功能,但由于之前基礎發貨功能的界面和邏輯并不是我開發的,所以我在修改原有代碼、支持有非常多細節邏輯的合并發貨能力時,就在擔心對原有發(zhong)貨(yao)能力的影響,而這時候,如果有單測的保障,我就可以更放心地進行功能升級改造了 —— 別說更復雜的合并發貨能力了,而這類訴求在復雜的交易場景里很普遍,

提煉一下我遇到的具體問題:

在由不同開發人員持續迭代、進行功能升級的軟體開發活動中,如何保障具有復雜邏輯的商家經營工具的產品質量,

軟體開發活動是整個流程的核心環節:接收產品和視覺設計需求/變更作為輸入,然后輸出客戶可用的終端產品,

而統一的軟體開發架構模式,則是我們保障軟體開發質量的基礎,(這里就不具體展開WHY了)

由于討論的是具體面向客戶使用的業務場景,少不了客戶操作互動的視圖層(View),所以我從MVC開始談起,

一、從表現層的MVC談起

雖然我平時比較慎用“架構”這個詞,但我平時喜歡隨手拍一些建筑物,

因為建筑之美,會讓我聯想到軟體的架構也應該有美感,畢竟Software Architecture這個概念也是起源于Architecture,

當然,由于軟體的可移植性、可復用性,從某些角度來講,軟體架構相比建筑架構有其更復雜的地方,

這時候,架構這個詞就會給我一種接地氣的感覺:有多少塊磚,每塊磚做什么用、放到哪里去,這塊磚 和 那塊磚怎么黏在一起或互相支撐,

MVC誕生至今已經超過40年了(Since 1979),10多年前就得到過很廣泛的討論和實踐,穿越時空到今天肯定有其反脆弱性和內在核心價值,

雖然如今乍看起來好像已經過氣、被討論過千百遍了,但仍然有很多程式員會有不同理解和看法,或多或少,

這是很正常的,上面也提到了部分原因,這里具體再展開下,

1. MVC在經典三層架構里的位置

MVC是一種通用架構模式,早期PC時代應用在桌面客戶端,后來在Web時代變得流行(我以前寫PHP也用過相關MVC框架),如今在移動互聯網時代也得到廣泛應用,

上面這三個場景的應用,都是面向客戶的,需要互動表現的,

從MVC命名中的View(視圖)也可以看出,MVC模式應用在軟體系統架構里的表現層,

在微軟官方檔案里,也明確把MVC放在Web Presentation Patterns下,

我之所以沒有在上圖中對M-V-C添加箭頭線條,是因為在這一點上,不同程式員也有不同理解和實踐,(2)

這是第一個需要明確的點:MVC架構模式在多層系統架構里的應用范圍,

左側 業務表現層-業務服務層-基礎服務層 是移動端三層架構模式,未涉及到 C/S 互動;右側是Web B/S場景的三層架構模式,

因為有些應用會比較簡單,根本不需要業務服務或基礎服務層,純粹靠一個MVC(或者VC)就能交付出一個Mobile/Web App;

而且在一些業務系統里,Web前端/桌面客戶端/移動App 也可能會被簡化為 大前端/大終端表現層;

所以可能基于不同資訊,不同程式員對此會有不同認知,

但隨著用戶終端應用的重要性和復雜度的提升,已經從簡單應用發展到復雜多團隊協同的平臺型或航母級應用,僅靠一個MVC來完成交付是不合適的,

也可以反過來想,程式員應該把以下代碼放在客戶端代碼的哪一層:

  • 對web引擎的擴展邏輯,

  • 通信協議的結構定義,以及相應的socket連接和通信代碼,

  • 一個業務相關且UI無關的平臺開放能力,

  • Crash捕獲、卡頓監控、日志埋點等功能實作,

  • ……

2. 業界基于MVC模式的不同實踐

前面提到不同程式員對MVC模式的理解和實踐存在差異,

業界大廠亦然,

比如蘋果、微軟,在自身實踐MVC模式或者向開發者提供相關檔案時,也一樣有不同的說法,

2.1 微軟

上圖是微軟2014年的檔案描述,

微軟2021年10月份更新的檔案中使用了下圖:

可以看出微軟在MVC的實踐上:

  1. Controller可以參考View和Model,

  2. View可以參考Model,

  3. 這里的Model傾向于是Passive,

值得注意的是,微軟在檔案里寫到:

  • 強型別視圖通常使用 ViewModel 型別,旨在包含要在該視圖上顯示的資料, 控制器從模型創建并填充 ViewModel 實體,

  • 控制器不應由于責任過多而變得過于復雜, 要阻止控制器邏輯變得過于復雜,請將業務邏輯推出控制器并推入域模型,

2.2 蘋果 & 斯坦福

上圖分別是蘋果和斯坦福10年+前給的MVC模式圖,之所以把它們放在一起,是因為斯坦福這張圖也是他們iOS開發課程上的課件,基本也是基于Apple的官方檔案來的,

不過這份官方檔案已經是Retired Document,并宣告不一定是目前的最佳實踐:

Important: This document may not represent best practices for current development. Links to downloads and other resources may no longer be valid.

是的,上圖應該產出于移動互聯網方興未艾的時候,隨著移動互聯網蓬勃發展,“最佳實踐”被一路多種挑戰 —— MVC也被戲稱為Massive View Controller,如何重構Massive View Controller為Lighter View Controller也成為了一個專題,

上面兩張圖呈現出:

  1. Controller參考View和Model,做update操作,

  2. Model通過KVO和(廣播)通知來觸達Controller,驅動Controller做出回應,

  3. View通過DataSource、Delegate、Target-Action等方式解耦、弱依賴Controller,由Controller對各種用戶操作、UI渲染訴求做出回應,

  4. View和Model之間是隔離的,

微軟和蘋果的異同點

  • 相同點:Model包含 所需的資料結構封裝,以及相應資料操作的方法定義,即Data + CURD,

  • 差異點:微軟給的圖中,View可以參考Model,而蘋果給的圖中不行,

一些問題和思考

  • View有箭頭指向Model,這里的參考關系是指什么?是View持有Model.Data資料物件,還是View呼叫Model.CURD方法,

  • Controller的本意是Controing Logic,那除了ViewController外,是否還可以有其它的XxController,比如DataSourceController、EventHandlerController?

  • 從命名上看,既然ViewController 既有View 又有Controller,那為什么把它放在 C里面,而不放在V里面呢?比如當我們在iOS/Android開發中引入MVVM模式后,ViewController或Activity屬于M-VM-V的哪部分呢,代碼放在哪個目錄下呢?

  • 我有類名使用ViewModel后綴就代表我使用MVVM模式了嗎?目前看,上述微軟檔案里不這么認為,

2.3 Martin Fowler

作為

  1. 《重構 : 改善既有代碼的設計》、《企業應用架構模式》等著作的作者,

  2. 敏捷軟體開發宣言創作者之一,

  3. MVVM模式誕生地 —— 微軟 —— 參考參考的技術專家,

Martin Fowler畫的MVC模式圖如下:

和上面微軟、蘋果給的圖,又不一樣了 *_*

2.4 Google

谷歌相關的描述則是:

2.5 MVC和DDD

Martin Fowler和《領域驅動設計》作者Eric Evans也討論過MVC中Model的設計理念:

  • 貧血模型:將Model分為簡(pin)單(xue)的Model資料物件,和處理操作資料物件的Service/Manager/BizLogic等,

    • 示例:為aPerson修改name,則由 CitizenService.changeNameOfPerson( aPerson ) 這種方式來實作,

  • 充血模型:將對應領域的處理邏輯放到領域模型中,使得這個領域模型更飽(chong)滿(xue),

    • 示例:aPerson要刷牙,則由 aPerson.brushTeeth() 來實作,

    • 補充:充血模型更有面向物件編程的味道,尤其是搭配交易領域等業務場景,更有體感,不過稍微細想一下,可能就會發現DDD對設計的要求會更高,從而對研發周期和質量保障提出了新的要求,并且可能引起對現有系統的大規模重構,(盒馬的DDD實踐)

也就是說,大到MVC各個模塊的依賴參考關系,細到Model中的代碼設計方式,業界都有不同的理念和實踐,

2.6 小結

先拋開具體模塊的代碼設計方案,基于以上幾種業界大廠或大佬的描述,我小結了以下這張圖:

問題一:如何解決MVC中Controller的膨脹臃腫問題?

要回答如何解決,需要先思考為什么膨脹,

問題二:View能否參考Model?

  • 要回答能否參考,需要先定義參考關系是什么,

    • 是持有物件,還是呼叫CURD介面操作物件,

    • 又或者這兩者沒有必要區分,因為持有的物件本身就可能帶CURD介面,

  • 參考上面相關資料,目前(1)微軟2021年檔案支持可以參考;(2)蘋果/斯坦福2011年檔案反對,

  • 在DinamicX研發模式中,模板View持有data資料物件在內部進行填充和渲染,

問題三:存在View -> Model,那么是否可以反過來存在 Model -> View?

和問題二在描述上相反但又有關聯,如果對問題再進一步提問的話:

  • 使用 -> 參考關系,是為了解決什么問題?

  • 使用 -> 參考關系,會產生什么問題?

如同文章開頭所說,以上問題結合具體場景來展開,盡量從務虛到務實,

二、實際案例結合

1. 常見的資料結構定義和使用

程式 = 資料結構 + 演算法,

—— Nicklaus Wirth,Pascal之父,圖靈獎獲得者

這句話乍看起來可能會有點面向程序設計的感覺,但OOP中的物件其實也是由資料+方法組成,而FP則更不用說了,

在編碼開發活動中,會存在以上3種資料結構定義和使用方式:

  1. 原生資料結構,比如list/array、map/dictionary、tuple等,

  2. 類似MyContact的資料結構定義,由服務端回傳的資料進行轉化,并可能根據業務邏輯按需加上一些標志位給Controller消費,

  3. 類似ContactViewModel這樣的純粹為視圖View服務的資料結構定義,

補充:

(1)MyContact 和 ContactViewModel 只是特意區分的命名,實際上 MyContact 也可以是純粹為視圖View服務的資料結構定義,(2)但是,合適的命名有助于幫助我們思考和編碼,從表達上呈現出我們的傾向和重點,

"There are only two hard things in Computer Science: cache invalidation and naming things."

—— Phil Karlton

2. 常見的多復雜卡片的串列場景

這個場景可以部分回答問題一:為什么Controller會膨脹,以及如何解決,

其它部分答案則落在復雜頁面場景的多delegate、target-action、notification-observer等視圖互動回應的處理邏輯上,

我認為,蘋果/斯坦福之前反對View參考Model,就是導致MVC變成Massive View-Controller的一個原因,

另一個原因我認為是工具鏈只提供了ViewController這樣的Controller模板,隱式教導開發者都在這里寫代碼,

這也可能是因為十幾年前移動互聯網還沒發展起來,移動App的復雜度低,所以蘋果提供了在當時簡單夠用的方案,

當只能由Controller 持有-> Model的時候,那么在多復雜卡片的串列場景中,必須由Controller來更新每個View的屬性/狀態,

  1. MyViewController需要為ContactCell更新它的各種相關屬性,類似的還有AddressCell、PackageCell等,

  2. MyViewController在更新AddressCell展示前,可能還需要先為它計算出合適的富文本展示內容,

  3. MyViewController需要回應不同Cell的點擊互動行為,包含但不限于按鈕點擊、輸入框變化、富文本跳轉、鍵盤起落等,

  4. MyViewController需要回應CollectionView/TableView的DataSource/Delegate各種方法實作,

  5. MyViewController需要回應Model層的變更通知,或者是另外一個ViewController拋過來的廣播通知,

  6. ……

然后MyViewController就爆炸了,

針對這種場景,我的解法是:

  1. 通過讓View->Model,基于工廠模式,把組件化Cell基于資料更新的布局邏輯交給View負責,如contactCell.configUIWithModel( contactModel ),這樣有點類似上面DDD提到的充血Model,具備高內聚的特點,帶來好處:

    1. 和微軟說的減輕控制器負擔、推入域模型類似,通過把資料驅動布局的代碼推入組件域內,減輕了MyViewController的負擔,

    2. 利于做這部分組件化Cell的UI測驗,

    3. 利于這些組件化視圖復用到其它場景,比如交易管理場景的訂單卡片可以復用到搜索場景中,不用在SeachViewController里復制粘貼一大堆代碼,只需要從Model取一個資料物件丟給組件化Cell即可,

    4. 工廠模式下,產品的刷漆、烘干、印花等操作會在內部完成,不會丟一個模型讓客戶去自己貼logo,MVC的每一部分都可以用不同的設計模式來組合實施,實作解耦或動態靈活的目標,

  2. 基于ViewController,拆分出不同職責的擴展,比如MyViewController+Delegate專門復雜回應代理事件處理,

  3. 定義出其它型別的Controller,比如MyDataSourceController,專門為TableView提供資料源,可以類比參考Android中ListView的Adapter+ViewHolder,

到這里已經回答了問題一和問題二,

更多解法可以參考上面提到的微軟給的建議,以及lighter view controllers,

這里采用了 VIew -> Model,用來參與解決Massive View-Controller的問題,并且讓View更容易復用和做UI測驗,帶來了好處,

這里對微軟提的

“控制器不應由于責任過多而變得過于復雜, 要阻止控制器邏輯變得過于復雜,請將業務邏輯推出控制器并推入域模型”

再進一步討論下,

我的理解和舉例:

  1. 存在一個輸入框,讓用戶提交物流單號,

  2. 用戶在輸入程序或者完成輸入后,由View通過delegate模式路由給Controller做校驗,而Controller可能還要進一步依賴Model去做更完整的校驗(如網路請求到服務端,因為物流單號的規則很多而且可能動態更新),

  3. 當Controller責任過多、代碼膨脹、過于復雜時,就將物流單號這塊業務邏輯推入 物流(單號)域模型中,即由View直接通過delegate模式交給 LogisticsModel來做校驗,

  4. 也是 View -> Model ,

不一定對,拋(huan)磚(ying)引(lai)玉(pen),

那么,存在VIew -> Model,有什么壞處嗎?

3. 一個Kotlin跨平臺場景案例

這里不具體展開講Kotlin及其跨平臺相關內容,只是描述從MVC模式做跨平臺遷移時遇到的問題,

這里的ViewController/Activity放在哪里,也和上面的一個問題相呼應,

雖然D-KMP主張通過全新構建工程寫代碼的方式來實踐,但從實際情況出發,絕大多數現有系統都會是以單點嘗試、漸進式的方式來落地,或發展、或回撤,

那么,如上圖所示:

  1. 如果在既有MVC代碼結構中,View -> Model,在這種漸進式遷移場景下,就需要修改View來適配新的ViewModel,

  2. 如果 View 不參考 Model,則是由 Controller來做膠水層設定更新視圖(命令式UI),

  3. 后者的好處是,保持View的獨立性,只需要修改這個業務場景對應的單個Controller即可,因為View具有可復用性,可能在另外還沒準備遷移/改變的模塊里也有使用,

所以,此處不建議 View -> Model,

那么,誰對呢?

4. 誰對誰錯的務虛討論

當有程式員要從MVC引申到MVP或者MVVM的時候,通常開頭的一句話就是 MVC的問題是C容易變臃腫,

我個人認為,

  • 架構是一個名詞(n.)+動詞(v.),

    • 架構(n. & v.)是為了幫助 開發者在交流時有一致的理解、在業務需要時能夠便于擴展、在出問題時能夠快速定位等等(對抗熵增),具體還是看采用這個架構的得失,要解決什么問題或帶來什么好處,然后帶來什么成本或付出什么代價,

    • 架構(v.)通過分配每部分代碼的職責并為他們取名(好比iOS/Android開發工程師這樣的崗位名稱,讓別人一看就知道是做什么的),然后幾個名字加在一起 形成了架構模式這個抽象概念,

    • 從具體到抽象,然后再由這個抽象概念去指導程式員實踐寫代碼,促進了架構的傳播,比如MVC、MVP、MVVM、MVI、MV-Whatever,VIPER,Redux and more……

  • 有時候并不一定是架構模式的錯,還有可能是平臺/框架在讓架構模式自傳播時采用的具體方案出了點問題,又或者是開發者自己寫代碼的問題,

  • 有時候架構模式之間也不是互斥的,也可以在不同場景下互補,比如在MVC里,每個業務表現模塊不一定要有三個元素齊聚,甚至也可以 VC-M-VC 共用一個M(可參考斯坦福iOS開發課程內容),

有一個實際的業務場景是這么實踐的:

MVC和MVVM在一個業務場景里相結合,

4.1 微軟的MVVM,和Angular的MVW

上面的Kotlin跨平臺圖,除了涉及到 View -> Model 的參考關系是否應該存在的討論,還涉及到了Declarative-UI和MVVM架構模式等概念,其中M和上面的DDD討論一樣,采取了具體的Repository模式來承載,

MVC、MVP 和 Declarative-UI 這三個名詞概念都有幾十年歷史了,其中宣告式UI在近十年又開始火了起來;

而MVVM則有十幾年歷史,

微軟在2005提出了MVVM概念,那么微軟會不會認為 MVVM 存在誰對誰錯的問題呢?

在我閱讀完幾篇很贊的微軟官網的文章后,我的感覺是微軟很謙虛和海納百川,并不會很教條式,

比如:

  • 在微軟MVC官方檔案中,建議強型別視圖使用 ViewModel 型別,旨在包含要在該視圖上顯示的資料, 控制器從模型創建并填充 ViewModel 實體,也就是MVC里也可以用ViewModel,

  • 微軟認為自己在2005年提出的MVVM架構模式,有些內容和Martin Fowler在2004年提出的PM(表現層模型)概念一致,

  • 微軟認為在架構模式上存在著不完全實作或組合實作的情況,也不會跑去說谷歌Android的ViewModel不符合他提出來的規范,

給我的感覺就好像Angular一樣:

I hereby declare AngularJS to be MVW framework - Model-View-Whatever. Where Whatever stands for "whatever works for you".

當然,微軟也給出了他關于MVVM的一些描述:

  • V和VM是一對多的關系,即View 1:n ViewModel,相比于 MVC里 Controller 1:n View,顯然MVC的C更容易膨脹,所以上面也提到了使用多Controller方案,

  • V參考VM,VM操作M,而VM不需要參考V(和MVP不同),VM作為V的背景關系,包含V所需用來展示的資料,回應V被用戶觸發的事件,

  • V對M無感知,反過來 M 對 V和VM 也無感知,整體是松散解耦的模式,

  • 當VM的屬性值發生變化時,通過資料系結方式傳達給V,這就需要有機制支撐,有對應的機制MVC也能做資料系結,

基于上述描述我畫了下圖:

總體來說,MVVM是基于事件驅動的、以資料系結機制為支撐的松散解耦架構模式,

  • 它的前提是有系統/平臺的機制支撐,

  • 相比MVC,它的優勢是視圖控制邏輯不太會膨脹,代碼單元更容易被測驗,在可讀性、可維護性上更好,

  • 它可能帶來的成本/問題是入門上手較難,簡單場景下使用容易過度設計,復雜場景下出問題除錯比較麻煩,

考慮到ViewController在該場景的薄膠水特質,以及也參與視圖展示和用戶回應,所以我把它放在V里,

5. 誰對誰錯的務實案例:VIPER和分層演變

關于誰對誰錯/誰好誰壞,可以再來看一個案例,

5.1 VIPER架構模式的應用

從下圖可以看到ViewController也被放到View里了,而且連接詞用的是 and / or ,

我之前寫過MVC、MVP、MVVM、VIPER等架構模式下的代碼,完全實作或不完全實作,

有一次,我在某個業務表現模塊里應用VIPER,然后定義了一個XxxNetworkInteractor類,用來負責做網路請求,

5.2 VIPER架構模式的演變

后來隨著業務場景的變化,一個業務模塊可能需要對接多套網關服務,

XxxNetworkInteractor就要做抽象隔離,消除業務邏輯對多套網關請求的感知,并且應用到其它業務模塊,

這就有點像 VPER - I - VPER 模式 —— 多個業務模塊對 Interactor 進行了復用,

5.3 進化

  • 隨著對接網關數的增加、網關能力的增強,XxxNetworkInteractor也配套建設了更多能力,

  • 隨著使用XxxNetworkInteractor的模塊越來越多,不同業務的一些通用訴求和處理邏輯也隨之增加,

  • 隨著XxxNetworkInteractor的功能越來越強大,代碼越來越多,逐漸需要抽離出一個單獨模塊,不管是從提高編譯速度,還是從封裝暴露等角度,

XxxNetworkSDK.framework誕生了,

5.4 退化

再后來,隨著技術和業務的變化,底層網關服務ATop成為了領域范圍內的事實標準,之前遇到的問題也消失了,而XxxNetworkSDK又帶來一些成本,比如要配套ATop的能力升級進行迭代維護,

所以,XxxNetworkSDK此時可以退出歷史舞臺,讓業務模塊直接面向ATop編程,這樣既降低了維護成本,又帶來了一定的包大小收益,

三、寫在最后,回到問題

不管是務虛的討論,還是務實的案例,或者是微軟和Angular的“whatever works for you”的觀點,

結論是沒有誰對誰錯、誰好誰壞,只有實際場景下要解決的核心問題,

兵無常勢,水無常形, —— 鏈接為Google搜索第一條,

那么,回到想要解決的問題:

在由不同開發人員持續迭代、進行功能升級的軟體開發活動中,如何保障具有復雜邏輯的商家經營工具的產品質量,

我的想法是以可測性作為手段,來保障功能升級改造或代碼重構后,可在合理時間范圍內得到充分回歸驗收,保障相關組件、模塊或整體產品的質量,

具體的方案實施上,因為是以可測性為重要關注點,再結合目前的技術方向,我會傾向于采用MVVM,

  • MVVM的架構模式在理解和認知上比較成熟,便于實施和傳播,并通過模式的名稱來體現要強調的關注點:可測性,

  • MVVM可以更好地結合Kotlin跨平臺、SwiftUI+Combine等技術方向,

  • MVVM完全版的上手門檻和簡單場景的過度設計問題,可以通過采用不完全版MVVM來解決,

    • 不完全版的MVVM可以cover適用于簡單場景的MVC,近似于 超集-子集 關系,

    • 雖然也可以通過多Controller的方式來解決MVC膨脹問題,但MVC的命名在實踐中就容易讓程式員榷訓掉可測性這個關注點(也可能是我個人理解和實踐不夠正確),

  • 復雜場景的除錯問題、更多可測性的實踐,需要再摸索下,也希望得到相關分享和指點,

完,

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

標籤:其他

上一篇:TCP 三次握手 四次分手

下一篇:華為網路配置(策略路由)

標籤雲
其他(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)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more