系統的混亂並非業務本身之複雜,我們並不擅長處理『簡單』

来源:https://www.cnblogs.com/88223100/archive/2023/01/21/We-are-not-good-at-dealing-with-simplicity.html
-Advertisement-
Play Games

一群高智商青年在餐廳吃飯,餐桌上一個瓶蓋標識為鹽的瓶子里裝得是胡椒粉,而標識為胡椒粉的瓶子里裝得卻是鹽,他們想出了一個充滿才氣的方案來完成對調--僅需要一張餐巾紙、一根吸管和兩個空碟子。當他們叫來服務員,準備炫耀他們的天才想法時,只見服務員什麼也沒說,只是拿起鹽瓶和胡椒粉瓶,互換了瓶蓋…… 在我們... ...


前言

一群高智商青年在餐廳吃飯,餐桌上一個瓶蓋標識為鹽的瓶子里裝得是胡椒粉,而標識為胡椒粉的瓶子里裝得卻是鹽,他們想出了一個充滿才氣的方案來完成對調--僅需要一張餐巾紙、一根吸管和兩個空碟子。當他們叫來服務員,準備炫耀他們的天才想法時,只見服務員什麼也沒說,只是拿起鹽瓶和胡椒粉瓶,互換了瓶蓋…… 
在我們軟體工程中,同樣一件事情可以有很多種解決方案,我們翻開那繼承下來的祖傳代碼,系統堆疊了太多它不需要或者它不適合的動態擴展、規則引擎、條件分支等等。原本並不複雜的業務最終得到的還是一片混亂,是我們的做法還是太過簡單嗎,或許本質上是我們並不擅長處理『簡單』。

 

本質複雜度與偶然複雜度

All software construction involves essential tasks and accidental tasks.
-- Frederick P.Brooks,Jr 《No Silver Bullet》
譯:所有軟體構建都包含其本質部分與偶然部分。

業務的複雜

Frederick P.Brooks,Jr 在1975年寫下了軟體界的一本著作 The Mythical Man-Month,國內也巧妙的譯為人月神話。書中提到軟體的複雜度包括本質複雜度和偶然複雜度。本質複雜度就是在解決問題時,無論如何都必須要面對的複雜度;而偶然複雜度,是由於選用的做事方法不當,導致額外增加的複雜度。
我們不否認在交易場景、訂單場景、支付場景等,可能天然存在非常複雜的業務邏輯,但同樣也並非所有的系統都像淘寶天貓一樣複雜。隨著業務的分拆,組織職能的劃分以及微服務的普及,我們面臨的問題與場景越來越小越來越聚焦。業務的複雜性天然存在,當我們看著那捉摸不透宛如天書的功能代碼時,我們試問一下自己的業務是否真的有那麼複雜。

 

系統的混亂

Despite all their heroics, overtime, and dedication, they simply aren't getting much of anything done anymore. All their effort is now consumed with managing the mess.
-- Robert C.Martin 《Clean Architecture》
譯:不管你們多敬業、加多少班,在面對爛系統時,你仍然會寸步難行,因為你大部分的精力不是在開發需求,而是在應對混亂。 
我們經常遇到一個簡單的業務訴求,但在老系統上支持就異常艱難。“在人離開的時候,自動把門關上”,但你永遠不知道這個房間到底有多少門,同樣你也莫名其妙會遇到,某些門關上後窗又碎了。
軟體工程最大的成本在於維護,系統的混亂並非業務本身之複雜,簡單的模塊我們同樣可能搞砸。為了未來可擴展,為了未來更靈活,我們不斷YY著所謂的未來,卻讓現在越來越糟。

 

我們以複雜應對簡單

訴求有時非常簡單,但我們又豈會“甘於做一個執行器”,我們認為這背後一定有更深刻的業務訴求,一定有更本質的商業問題,一定有更底層的層次邏輯。於是我們擺擺手說道:這可沒那麼簡單~

TMF的擴展實現

TMF是業務中臺面向可復用可擴展架構的核心,在平臺與業務分離,業務與業務隔離上可以起到重要作用。當我們發現有中國商家需求的同時還存在在海外商家業務,我們立馬抄起了TMF來設計我們的擴展與編排。最終代碼上線3年,也只有可憐的2個實現。無數的後人需要花更多的時間來理解與維護這段曾經的“高光設計”。 
當出現第3個擴展訴求時,有人發現不應該用這麼重的框架,於是寫了一個簡單的策略模式來支撐,而原有的TMF代碼又不敢動,於是在可憐的3個擴展實例里還並存著2套擴展框架。再接下來又引申出了另一個課題,去TMF。或許真正需要的,只是3段簡單的if-else。

 

PD五顏六色的黑

我們也曾經遇到這樣的需求,為了方便銷售更好的篩選客戶,產品提出增加各式各樣標簽共計80餘個,並且支持標簽與標簽間,可以靈活的讓用戶選擇取交集還是取並集。最終我們發現,銷售名下客戶的中位數是8個,也就是說大部分銷售1~2頁可以翻完自己名下的所有客戶,當時我們也戲稱,標簽設計得比客戶還多。
部(hen)分(duo)產品經理沒有思考核心的問題到底是什麼,在淺層次瘋狂堆疊功能,美其名曰業務需要不斷試錯,實則缺少思考,缺少對問題根因的理解與判斷。在複雜這條路上越走越遠,也讓真正的簡單越來越難。

‘複雜’的光環與‘簡單’的暗淡

Simplicity has been difficult to implement in modern life, because it is against the spirit of a certain brand of people who seek sophistication so they can justify their profession.
-- Nassim Nicholas Taleb 《Antifragile:Things That Gain from Disorder》
譯:在現實生活中,簡單的做法一直難以實現,因為它有違某些努力尋求複雜化,以證明其工作合理性的人所秉持的精神。
為什麼大家更偏向複雜而遠離簡單,除了缺少思考,找不到問題的核心解以外,還有一個重要原因就是為了所謂的“證明自己”。Nassim Nicholas Taleb在 Antifragile:Things That Gain from Disorder 中提到一個觀點:在現實生活中,簡單的做法一直難以實現,因為它有違某些努力尋求複雜化,以證明其工作合理性的人所秉持的精神。
如同DDD在中小系統所帶來的災難一樣,根本原因更多是因為大家並不願意承認自己的系統是中小系統,自己所承接的業務是偏向簡單的業務。最終導致簡單的模塊賦以複雜的束縛,最終效率被工具本身所制約。
曾經我們有一個搜索器增量推送的訴求,當時用的blink來支持,blink支持海量數據處理,分散式集群能力等等。而我們本身並沒有海量數據,也沒有超高併發,最終上線後不僅用不上blink超強的能力,還因為blink的性能調優、自定義函數異常、類型轉換異常、資源申請及降級,以及為新人帶來的認知負荷等等,帶來了更大的不便。後面通過手寫JAVA,調用搜索器增量推送SDK的方式進行重構,簡單清晰,查問題成本也更低。當然,將blink畫到PPT里,那確實還挺高大上的。
‘複雜’總是伴隨著光環,當我們解決一個複雜問題後,我們會得到更多人的肯定,向大家證明和展示自己的實力。而簡單往往更‘暗淡’,如同上文提到的互換瓶蓋,大家並不會因此認可服務生的能力,甚至覺得也沒什麼大不了。如此往複,讓大家更青睞複雜,更遠離簡單。

『簡單』其實更複雜

Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple。
-- Steve Jobs
譯:簡單比複雜更難,你必須儘力理清思路才能做到簡單。
手機的HOME鍵是極簡主義的一個代表,據說小圓點的設計靈感是受到馬桶的啟發,用一個按鈕清除所有。
簡單並不代表容易,簡單意味著非聯接,而非聯接並不簡單。在降低複雜度上,軟體設計有一個核心理念叫“解耦”,核心思想是分離關註點,只有你聚焦的內容少了,你才不會覺得複雜。

KISS原則

Keep it Simple and Stupid
-- Robert S. Kaplan
譯:保持簡單和笨拙
KISS原則是Robert S. Kaplan提出的一個理論,Kaplan並非是一個軟體學家,他是平衡積分卡 Balanced Scorecard 創始人,而他所提出的這個理論對軟體行業依然適用。把事情變複雜很簡單,把事情變簡單很複雜。我們需要儘量讓複雜的問題簡明化、簡單化。
KISS原則的實現看似簡單,但實則並不容易。以最簡單的做法完成任務,但不斷引入複雜度並腐化系統的做法,被John Ousterhout教授稱之為「戰術龍卷風」。當你不斷打著KISS原則的旗號,以最簡單的做法堆疊功能時,最終會得到一個終極複雜體。軟體設計是一門藝術,前人的經驗可以給我們提供前進的方向,但我們也一定要時刻有自己的判斷。

 

UNIX的藝術

圖片

1974年UNIX系統在Communication of ACM上發表,正式向外界披露了UNIX系統。UNIX的成功也誕生了諸如Linux、BSD、Solaris、MacOSX等多個UNIX變種。UNIX奠基人之一的Doug Mcllroy曾經說,UNIX的設計理念就是一個程式只做一件事,並做好。 
All the philosophy really boils down to one iron law, the hallowed ‘KISS principle’ of master
engineers everywhere.
-- Eric Steven Raymond 《The Art of Unix Programming》
譯:所有的UNIX哲學濃縮為一條鐵律,那就是各地編程大師們奉為圭臬的KISS原則。 
UNIX的哲學根本,就是一部在持續踐行KISS原則的卓越工程。『維護如此重要而成本如此高昂,在寫程式時,要想到你不是寫給執行代碼的電腦看的,而是給人--將來閱讀維護源碼的人,包括你自己』-- The Art of Unix Programming

 

遺失的奧卡姆剃刀

Entities should not be multiplied beyond necessity.
-- William of Ockham 《Occam's Razor》
譯:如無必要,勿增實體。
奧卡姆剃刀也稱為奧康定律,最先並非在軟體界提出而是在哲學界。保持事情的簡單性,抓住根本,去掉無關內容,是奧卡姆剃刀的核心觀念。在軟體設計中,每一次的抽象,都是在放大本質因素,消除無關因素。奧卡姆剃刀的缺失,也讓我們的系統越來越複雜,我們總能發現有很多奇奇怪怪可有可無的代碼,散落在系統各處,增加這些代碼可能只需要幾分鐘,但移除這些代碼花費的精力與承擔的風險,卻數倍於此。

Maven的SNAPSHOT

Maven的SNAPSHOT設計是我覺得非常棒的一個設計,當版本號為1.0時,是正式版,當版本號是1.0-SNAPSHOT時,是快照版,直接通過名字進行區分,簡單清晰。
或許有人認為這比較粗暴,如果快照版後續還存在更多變種,那支撐起來會非常不優雅,應該用一個欄位或屬性來單獨表示正式版還是快照版,這樣更規範更易擴展。
過早的優化是萬惡的根源,或許他的擔憂是對的,但很慶幸當初Maven創始人沒這麼乾,將簡單延續了下來,事實也證明,它真的很美。

 

因為信任所以簡單

因為信任所以簡單,是阿裡的一個價值觀。有次周末打車去公司,師傅問你們不記錄相關線路和內容,如果有人打車跑別處去玩了怎麼辦,我回答因為信任所以簡單。我見過很多公司,為了約束員工,設定過非常繁雜的規則。而往往上有政策下有對策,公司與員工內耗在這無盡的拉扯中。
把握住問題的本質--信任。真實不裝,互相信任,沒那麼多顧慮猜忌,問題就簡單了,事情也就因此高效。

 

寫在最後

小時候打撞球,見到能翻袋,下底,長桿的人真厲害,幻想自己有一天能厲害到怎樣難的球都能打進。長大後發現,真正厲害的人,母球永遠不會輕易停在難打的地方。有能力解決複雜問題的人,我們給予掌聲,而能夠持續保持簡單保持純粹,應該得到更高的贊許。
參閱書籍:
1、《Antifragile:Things That Gain from Disorder》:https://book.douban.com/subject/34978407/
2、《The Art of Unix Programming》:https://book.douban.com/subject/1229959/
3、《The Mythical Man-Month》:https://book.douban.com/subject/6039354/
4、《Clean Architecture》:https://book.douban.com/subject/26915970/

 

作者|聶曉龍(率鴿)

本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/We-are-not-good-at-dealing-with-simplicity.html


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

-Advertisement-
Play Games
更多相關文章
  • 作者:京東物流 王北永 姚再毅 李振 1 背景 目前,ducc實現了實時近乎所有配置動態生效的場景,但是配置是否實時生效,不能直觀展示每個機器上jvm內對象對應的參數是否已變更為準確的值,大部分時候需要查看日誌確認是否生效。 2 技術依賴 1)Jsf:京東RPC框架,用作機器之間的通訊工具 2)re ...
  • 2023-01-20 一、SpringMVC處理響應數據 1、處理響應數據方式一 (1)語法:使用ModelAndView對象作為返回值類型,處理響應數據 (2)底層實現原理 ①數據共用到request域 ②跳轉路徑方式:轉發 (3)示例代碼 @RequestMapping("/testModelA ...
  • 常見的網路IO模型有4種:同步阻塞IO、同步非阻塞IO、IO多路復用以及非同步非阻塞IO。 RPC會採用IO多路復用的機制來管理網路通信。 ...
  • 寫在前面 在開發的過程中,大多數人都需要對代碼進行測試。目前對於c/c++項目,可以採用google的gtest框架,除此之外在github上搜索之後可以發現很多其他類似功能的項目。但把別人的輪子直接拿來用,終究比不過自己造一個同樣功能的輪子更有成就感。作為“linux環境編程”系列文章的第一篇,本 ...
  • 基於 LGT8F328P LQFP32 的 Arduino Mini EVB, 這個板型資料較少, 記錄一下開發環境和燒錄過程以及當中遇到的問題. ...
  • 介紹一些我常用的ssh工具 1、Xshell ​ Xshell應該是一款家喻戶曉的ssh連接工具,本人有幸也在很長一段時間都在使用Xshell,但是Xshell他是收費的!而且每次關閉後都會有一個提示框,我很不喜歡,而且Xshell的ftp或其他插件都是需要額外自行下載的,對於文件傳輸不太方便,但是 ...
  • JavaScript 中的作用域指的是變數和函數的可訪問範圍。 JavaScript 中,閉包是一個函數對象,它可以訪問定義該函數的作用域里的變數,即使函數已經返回。閉包的特點是,它可以在其相關環境不存在時保留變數。閉包可以被保存到變數中併在以後使用。它具有兩個特征,一是可以訪問外部函數的變數,二是... ...
  • JavaScript 中的 this 關鍵字引用了所在函數正在被調用時的對象。在不同的上下文中,this 的指向會發生變化。可以通過 call, apply, bind 方法來改變 this 的上下文。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...