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

来源: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
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...