- 簡(jiǎn)單之美:軟件開(kāi)發(fā)實(shí)踐者的思考
- 倪健
- 4181字
- 2018-12-31 18:20:50
1.3 簡(jiǎn)單的追求
軟件開(kāi)發(fā),尤其是企業(yè)應(yīng)用軟件開(kāi)發(fā),最根本的原則是簡(jiǎn)單化。簡(jiǎn)單可以使表達(dá)準(zhǔn)確、思路清晰,可以實(shí)質(zhì)性地、最大限度地降低軟件開(kāi)發(fā)成本。簡(jiǎn)單化不是天方夜譚,它是可以實(shí)現(xiàn)的。
在討論軟件開(kāi)發(fā)中的簡(jiǎn)單化原則之前,我們不妨先來(lái)認(rèn)識(shí)兩個(gè)人。他們是中國(guó)近現(xiàn)代哲學(xué)史上的兩位大家——金岳霖和馮友蘭
。很有趣,這兩個(gè)人在表述哲學(xué)觀點(diǎn)時(shí),風(fēng)格截然不同。金先生總是喜歡把簡(jiǎn)單的事情表述得很復(fù)雜,而馮先生呢,總是能把復(fù)雜的事情表述得很簡(jiǎn)單。我們來(lái)欣賞兩段文字。
金先生在《論道》的“第8章——無(wú)極而太極”中寫(xiě)道:
道無(wú)始。所謂無(wú)始就是說(shuō)無(wú)論把任何有量時(shí)間以為底始,總有此時(shí)間之前的道;或者說(shuō)從任何現(xiàn)在算起,把有量時(shí)間往上推,推得無(wú)論如何的久,總推不到最初有道的時(shí)候。可是,道既然無(wú)始,為什么又有極呢?如果有極,那極豈不就是道底始!這極是極限的極,是達(dá)不到的極。它雖然是達(dá)不到的,然而如果我們用某種方法推上去,無(wú)量地推上去,它就是理論上推無(wú)可再推的極限,道雖無(wú)有量的始,而有無(wú)量地推上去的極限。我們把這個(gè)極限叫做無(wú)極。
馮先生在《中國(guó)哲學(xué)簡(jiǎn)史》中論述自己對(duì)于哲學(xué)的看法:
哲學(xué),和其他各門(mén)知識(shí)一樣,必須以經(jīng)驗(yàn)為出發(fā)點(diǎn)。但是哲學(xué),特別是形上學(xué),又與其他各門(mén)知識(shí)不同,不同之處在于,哲學(xué)的發(fā)展使它最終達(dá)到超越經(jīng)驗(yàn)的“某物”。在這個(gè)“某物”中,存在著從邏輯上說(shuō)不可感只可思的東西。例如,方桌可感,而“方”不可感。這不是因?yàn)槲覀兊母泄侔l(fā)展不完全,而是因?yàn)椤胺健笔且弧袄怼保瑥倪壿嬌险f(shuō),“理”只可思而不可感。
在這個(gè)“某物”中,也有既不可感,而且嚴(yán)格說(shuō)來(lái),亦不可思者。在第一章中,我說(shuō)哲學(xué)是對(duì)于人生有系統(tǒng)的反思的思想。由于它的反思的性質(zhì),它最終必須思想從邏輯上說(shuō)不可能成為思想的對(duì)象的“某物”。例如,宇宙,由于它是一切存在的全體,從邏輯上說(shuō),不可能成為思想的對(duì)象。我們?cè)诘谑耪乱呀?jīng)知道,“天”字有時(shí)候在這種全體的意義上使用,如郭象說(shuō):“天者,萬(wàn)物之總名也。”由于宇宙是一切存在的全體,所以一個(gè)人思及宇宙時(shí),他是在反思地思,因?yàn)檫@個(gè)思和思的人也一定都包括在這個(gè)全體之內(nèi)。但是當(dāng)他思及這個(gè)全體,這個(gè)全體就在他的思之內(nèi)而不包括這個(gè)思的本身。因?yàn)樗撬嫉膶?duì)象,所以與思相對(duì)而立。所以他思及的全體,實(shí)際上并不是一切存在的全體??墒撬皂毸技叭w,才能認(rèn)識(shí)到全體不可思。人需要思,才能知道不可思者;正如有時(shí)候人需要聲音才能知道靜默。人必須思及不可思者,可是剛一要這么做,它就立即溜掉了。這正是哲學(xué)的最迷人而又最?lèi)廊说牡胤健?/p>
從邏輯上說(shuō),不可感者,超越經(jīng)驗(yàn);既不可感又不可思者,超越理智。關(guān)于超越經(jīng)驗(yàn)和理智者,人不可能說(shuō)得很多。所以哲學(xué),至少是形上學(xué),在它的性質(zhì)上,一定是簡(jiǎn)單的,否則它又變成了簡(jiǎn)直是壞的科學(xué)。它雖然只有些簡(jiǎn)單的觀念,也足夠完成它的任務(wù)。
我本人偏好馮先生的那種簡(jiǎn)單表述。不過(guò),哲學(xué)家的工作,是一種個(gè)人的行為。岳先生的文字盡管復(fù)雜晦澀,但讀者有充裕的時(shí)間去揣摩他的觀點(diǎn)。從這個(gè)角度來(lái)看,復(fù)雜性沒(méi)有太大的問(wèn)題??墒?,在軟件開(kāi)發(fā)的過(guò)程中,復(fù)雜形式的思想交流就有點(diǎn)不可思議了。我們總是希望接觸到最直白的常識(shí)。
要想用最直白的常識(shí)來(lái)交流,把握事物的本質(zhì)是關(guān)鍵。而為了把握本質(zhì),我們首先需要認(rèn)識(shí)事物。
一般來(lái)說(shuō),人們認(rèn)識(shí)事物從簡(jiǎn)單開(kāi)始,經(jīng)過(guò)簡(jiǎn)單認(rèn)識(shí)的不斷堆積,然后在混亂復(fù)雜中摸索,最后又回歸簡(jiǎn)單的認(rèn)識(shí)。這樣的認(rèn)識(shí)過(guò)程同樣適用于軟件開(kāi)發(fā)領(lǐng)域。
因此,在軟件開(kāi)發(fā)實(shí)踐中,我們應(yīng)該有意識(shí)地向認(rèn)識(shí)的最高形式——簡(jiǎn)單化——靠攏。事實(shí)上,簡(jiǎn)單與否,常??梢猿蔀楹饬课覀儗?duì)事物認(rèn)識(shí)程度的一個(gè)標(biāo)準(zhǔn)。我們不妨按照簡(jiǎn)單的標(biāo)準(zhǔn)來(lái)認(rèn)識(shí)一下企業(yè)應(yīng)用軟件。
在我看來(lái),企業(yè)應(yīng)用軟件很簡(jiǎn)單。它主要包括三個(gè)部分:一個(gè)領(lǐng)域模型,一組基于領(lǐng)域模型的計(jì)算,以及用來(lái)和用戶(hù)交互的界面。這是一個(gè)基本的思路。
任何時(shí)候都不要輕易丟棄一個(gè)非常簡(jiǎn)單的原則性想法,同時(shí),在任何時(shí)候都不要固執(zhí)于一個(gè)具體的想法細(xì)節(jié)。
不過(guò),當(dāng)我們把這個(gè)基本思路應(yīng)用到軟件開(kāi)發(fā)實(shí)踐中去的時(shí)候,可能會(huì)發(fā)現(xiàn),還有一些相關(guān)的工作要做。例如,領(lǐng)域模型在工作時(shí)會(huì)涉及信息的使用和存儲(chǔ)。因?yàn)榇鎯?chǔ)的需要,所以要了解數(shù)據(jù)庫(kù)(現(xiàn)在的ORMapping工具使你不用更多地了解它)。
老實(shí)說(shuō),為了恪守簡(jiǎn)單的原則,我們應(yīng)該逐漸進(jìn)入細(xì)節(jié)。在這個(gè)例子中,思考領(lǐng)域模型的時(shí)候不要立即開(kāi)始考慮數(shù)據(jù)庫(kù)的因素??梢宰龅絾幔?/p>
答案是,很多軟件開(kāi)發(fā)人員都做不到。他們總是忍不住會(huì)立即去考慮效率、領(lǐng)域模型中各元素的關(guān)系如何在數(shù)據(jù)庫(kù)中的表達(dá)、ORMapping工具在使用中的一些限制等。
忍不住的結(jié)果就是,他們停留在一個(gè)點(diǎn)上,想了很多方法來(lái)解決他們擔(dān)心的事情。因?yàn)檫@樣的事情總是有很多,所以簡(jiǎn)單的原則總是被違背,而復(fù)雜性總是不期而至。
具有諷刺意味的是,在軟件開(kāi)發(fā)實(shí)踐中,很多設(shè)計(jì)人員提出的針對(duì)性能的解決方案往往是性能的最大瓶頸。
假設(shè)我們恪守了簡(jiǎn)單化原則,同時(shí)有了一個(gè)滿意的領(lǐng)域模型,接下來(lái)的事情就是基于領(lǐng)域模型的計(jì)算。
在系統(tǒng)工作期間,領(lǐng)域模型會(huì)產(chǎn)生很多的實(shí)例,這些實(shí)例擁有自己的數(shù)據(jù)。企業(yè)應(yīng)用軟件的主要工作內(nèi)容基本上就是圍繞這些數(shù)據(jù)做些加加減減的工作。
當(dāng)然,除了加加減減,我們還需要了解一些相關(guān)的知識(shí)。
第一,業(yè)界有很多的平臺(tái)和框架支持加加減減,例如JavaEE、Spring、Seam等。而這些平臺(tái)和框架又提供了一些服務(wù),例如,分布式計(jì)算、事務(wù)服務(wù)、連接池、狀態(tài)服務(wù)(各種上下文)等。我們了解并運(yùn)用這些平臺(tái)和框架,可以減少自己的工作內(nèi)容。
第二,除了平臺(tái)和框架之外,我們可能還需要了解一些支持開(kāi)發(fā)的工具。這些工具可以通過(guò)向?qū)筛鞣N類(lèi)型的項(xiàng)目,可以集成各種服務(wù)器,可以幫助我們開(kāi)發(fā)程序、調(diào)試代碼、發(fā)布應(yīng)用等。
第三,如果還要延伸,那我們可能需要看看業(yè)界的一些流行的概念,比方說(shuō)SOA。
SOA可以幫助企業(yè)來(lái)進(jìn)行系統(tǒng)集成,同時(shí)它也可以幫助企業(yè)用一種全新的、面向服務(wù)的思想來(lái)構(gòu)建系統(tǒng)。
我們不斷地延伸知識(shí),聽(tīng)上去似乎有點(diǎn)復(fù)雜了。但是,這些延伸的知識(shí)不是問(wèn)題的本質(zhì)。我們需要記住的應(yīng)該只是那個(gè)簡(jiǎn)單的原則;我們需要做的其實(shí)只有一件事——基于領(lǐng)域模型的計(jì)算。
想想看,我們需要關(guān)注的只是如何把加加減減做得精到。所以,在陷入各種細(xì)節(jié)性的討論之前,我們應(yīng)該從思想上來(lái)把握問(wèn)題的本質(zhì)。
本質(zhì)的就是簡(jiǎn)單的。所以,我們的目標(biāo)是要讓事情都變得簡(jiǎn)單。這有很多的工作要做,比方說(shuō)如何讓軟件如何與平臺(tái)框架的耦合性降到最低,如何讓軟件的可移植性和可擴(kuò)展性最好等。事實(shí)上,這些讓事情變得簡(jiǎn)單的工作,才是我們思考和努力的方向。相反,在簡(jiǎn)單的事物上,尋求局部的、復(fù)雜的解決方案是一種風(fēng)險(xiǎn)極高的做法。
認(rèn)識(shí)上需要追求簡(jiǎn)單,實(shí)踐中也該同樣如此。
的確,軟件開(kāi)發(fā)實(shí)踐存在一定的復(fù)雜性。這是因?yàn)椋瑢?shí)踐中遇到的背景知識(shí)是廣泛的。這些背景知識(shí),通常不會(huì)在一本或幾本參考書(shū)中找到答案。例如,當(dāng)你需要開(kāi)發(fā)一個(gè)Linux版本的通信系統(tǒng)的時(shí)候,需要具備很多相關(guān)的知識(shí)。否則,會(huì)遇到很多困難。
我有過(guò)類(lèi)似的經(jīng)歷。當(dāng)時(shí)接到了一個(gè)任務(wù):
我們要準(zhǔn)備一個(gè)運(yùn)行在VMWARE中的應(yīng)用系統(tǒng)DEMO。這個(gè)DEMO將被部署在WAS(已部署WPS
)上,系統(tǒng)運(yùn)行時(shí)調(diào)用部署在WPS上的業(yè)務(wù)流程接口,業(yè)務(wù)流程的節(jié)點(diǎn)上會(huì)調(diào)用公司的規(guī)則引擎,規(guī)則引擎被封裝成EJB部署在WAS上。所有的部署過(guò)程使用自動(dòng)化腳本。
整個(gè)任務(wù)的時(shí)間是一周。如果你不了解VMWARE、WAS、WPS、規(guī)則引擎、EJB、SHELL SCRIPT、JACL和應(yīng)用系統(tǒng)本身等,你該怎么做?沒(méi)有答案。估計(jì)只能像我們一樣瞎蒙吧。
相關(guān)背景知識(shí)的積累需要一個(gè)長(zhǎng)期的過(guò)程。在這個(gè)過(guò)程中,主要的工作就是收集信息。
收集信息是一項(xiàng)艱巨復(fù)雜的任務(wù)。但是,對(duì)軟件開(kāi)發(fā)來(lái)說(shuō),這項(xiàng)任務(wù)是過(guò)程性的任務(wù),而不是我們的目標(biāo)任務(wù)。
可是,我總是很遺憾地發(fā)現(xiàn),很多軟件開(kāi)發(fā)人員都被這個(gè)過(guò)程性的任務(wù)蒙蔽了雙眼。他們中的一部分,始終徘徊在信息收集的門(mén)外(因?yàn)闊o(wú)法掌握足夠的信息而無(wú)力解決問(wèn)題),他們中的另一部分,在積累了豐富的信息之后,盡管已經(jīng)不自覺(jué)地站到了一個(gè)更高的層次(可以用思想來(lái)指導(dǎo)行動(dòng))上,但是主觀上,他們?nèi)匀话研畔⑹占倪^(guò)程當(dāng)作了軟件開(kāi)發(fā)的本質(zhì)內(nèi)容。
之所以在這里談?wù)撘恍┛此莆⒉蛔愕赖牟町?,是因?yàn)槲曳浅T诤跛枷胗^念上的差異。在我看來(lái),出發(fā)點(diǎn)的不同,導(dǎo)致的結(jié)果可能完全兩樣。
這也是我不斷強(qiáng)調(diào)在軟件開(kāi)發(fā)思想上要堅(jiān)持簡(jiǎn)單化原則的原因。
其實(shí),信息量的多寡,根本不能反映軟件開(kāi)發(fā)能力的本質(zhì)差異。我們說(shuō)必要的知識(shí)積累是軟件開(kāi)發(fā)的起點(diǎn),但是軟件開(kāi)發(fā)的本質(zhì)在于創(chuàng)造,所以運(yùn)用信息的能力才是關(guān)鍵。
從這個(gè)角度來(lái)看,很多軟件開(kāi)發(fā)組織對(duì)軟件開(kāi)發(fā)技能的認(rèn)識(shí)其實(shí)都是錯(cuò)誤的。這些組織看重信息量,而忽視信息的使用方法。這也是我們?yōu)槭裁纯偸怯龅綇?fù)雜混亂的軟件架構(gòu)的原因之一。
如果你的企業(yè)正在招聘人才,請(qǐng)關(guān)注應(yīng)聘者解決問(wèn)題的思路和看待問(wèn)題的層次。信息量既不是生產(chǎn)好軟件的前提,也不是生產(chǎn)好軟件的必要條件。以后的章節(jié)中,我還會(huì)進(jìn)一步論述這個(gè)觀點(diǎn)。
讓我們?cè)倩氐胶?jiǎn)單化的話題。簡(jiǎn)單化有什么好處呢?
越簡(jiǎn)單越準(zhǔn)確。
用例的撰寫(xiě)就是一個(gè)明證:不需要修飾語(yǔ),不需要副詞,不需要語(yǔ)氣詞和助動(dòng)詞。有效的用例只保留主謂賓,沒(méi)有任何內(nèi)涵和外延干擾意思的表達(dá)。用例簡(jiǎn)單到只有常識(shí)和術(shù)語(yǔ),幾乎不可能帶來(lái)歧義。
對(duì)于團(tuán)隊(duì)特征更明顯的企業(yè)應(yīng)用軟件開(kāi)發(fā)來(lái)說(shuō),簡(jiǎn)單化還是準(zhǔn)確溝通的最好保證。
越簡(jiǎn)單思路越清晰。
我曾經(jīng)看過(guò)這樣的系統(tǒng),它包含了很多概念和分層。一次調(diào)用會(huì)涉及數(shù)不清的接口,跨越數(shù)不清的框架、模塊、公共組件和“小發(fā)明”。一定需要這樣的結(jié)構(gòu)嗎?不需要。這樣的結(jié)構(gòu)只會(huì)使后期的演化和維護(hù)變得異常困難,由此帶來(lái)了巨大的隱形開(kāi)發(fā)成本。雖然我們不差資源和智慧,但能簡(jiǎn)單為啥不簡(jiǎn)單呢?
理想中的簡(jiǎn)單化是僅保留所有必須保留的,使通過(guò)簡(jiǎn)單化建立的一切,最有利于知識(shí)共享和持續(xù)演化。這兩個(gè)目標(biāo)看似容易,其實(shí)不容易。它需要成熟的簡(jiǎn)單化思想,需要持之以恒地恪守原則,需要簡(jiǎn)單化技能的訓(xùn)練。
還有一個(gè)問(wèn)題。
在軟件開(kāi)發(fā)實(shí)踐中,初始狀態(tài)通常都是簡(jiǎn)單的。但是,隨著時(shí)間的推移,軟件開(kāi)發(fā)開(kāi)始變得復(fù)雜和混亂。這是為什么呢?很簡(jiǎn)單,這是因?yàn)檐浖_(kāi)發(fā)人員丟棄了簡(jiǎn)單化思想和恪守簡(jiǎn)單化原則的精神。
很有趣。如果你曾經(jīng)在生產(chǎn)企業(yè)應(yīng)用軟件的企業(yè)中呆過(guò),那么,你總是會(huì)發(fā)現(xiàn)這樣的丟棄行為。
回憶一下,你曾經(jīng)經(jīng)歷過(guò)輕率決策嗎?你曾經(jīng)經(jīng)歷過(guò)非技術(shù)型妥協(xié)嗎?你曾經(jīng)經(jīng)歷過(guò)無(wú)責(zé)任參與嗎?如果你曾經(jīng)經(jīng)歷過(guò),那么告訴你,那些都是打破簡(jiǎn)單化原則的“最好”方法,也是使軟件開(kāi)發(fā)變得復(fù)雜和混亂的根本原因之一。
- GitLab CI/CD 從入門(mén)到實(shí)戰(zhàn)
- Spring開(kāi)發(fā)者的Quarkus實(shí)戰(zhàn)
- App草圖+流程圖+交互原型設(shè)計(jì)教程
- Docker源碼分析
- MATLAB 2018從入門(mén)到精通
- DevOps:企業(yè)級(jí)CI/CD實(shí)戰(zhàn)
- 程序員的制勝技
- 這就是MCP
- iOS移動(dòng)開(kāi)發(fā)從入門(mén)到精通
- Android5.0新特性實(shí)戰(zhàn)
- 程序員度量:改善軟件團(tuán)隊(duì)的分析學(xué)
- 軟件架構(gòu)的藝術(shù)
- BERT基礎(chǔ)教程:Transformer大模型實(shí)戰(zhàn)
- CATIA V5 從入門(mén)到精通(第二版)
- Spring in Action(第二版)中文版