復用的著相
著相是佛家用語,指的是執著于外相偏離了本質。
仙劍奇俠傳中有一個故事。講的是一個成精了的佛珠。想要讓更多的人向佛,于是施法,讓這些人失去了記憶,只想一心禮佛。使人向佛,本來是好事,但強人所難,脫離了本質,便是著了相,也可以說反而是入了魔。
這個小故事告訴我們,在認知的世界里,我們很容易被表象所欺騙,忽略了本質。為此,佛家發明了這么一個名詞來專門指出這種現象。
復用也是一樣。復用本來是通過消除重復的方式。得到一系列可以復用的組件。從而在未來的開發工作中,更快速的響應需求變化,也就是所謂的提升響應力。
然而很多復用的結果,會造成代碼是變少了,改起來卻更難了。復用是增加了,可讀性卻下降了。考慮到軟件開發是一個團隊協作的工作,而我們這個行業的離職率又能到百分之二十之多。難以學習的代碼確實是難以維護的,盡管你可以抱怨接手的人無能,但總之是降低了響應力,也就違背了復用的本質。
什么情況下會出現這樣的場景呢?主要是因為視角的單一,只從自己單一的視角看到了重復而不是在做全局優化。這個說法可能稍微有些抽象,那我說幾個相對具體的情況。
當我們只關注功能視角的時候
需求有很多的描述視角,可以只在功能角度描述,比如“網站要有任務卡,任務卡上有文字版學習內容,視頻講解、也有作業題。”也可以加入業務視角,比如“學生要報名特訓營,才能參加特訓營。學生進入特訓營后,就看到了任務卡列表。學生在任務卡上閱讀學習資料,閱讀完學習資料后做題來驗證他是否學到,做完后提交交由助教審閱。”當我們只看功能視角的時候,可能會忽視業務上的不同,變的在功能角度過分抽象,***當業務變化的時候,反而響應速度比較弱。
一個簡單的后臺,我們看起來所有東西長得都一樣,不過是列表頁面,添加頁面修改頁面,再加點兒刪除什么的功能。說穿了都是crud,干脆我把這事弄成一一個組件好了,每個頁面只需要簡單配置一下,就可以出來自己的一套增刪改查頁面。
這種視角完全沒有考慮到,不同的實體,它們其實所在的業務是不一樣的,關心它們的人也是不一樣的。***,彼此的演化方向也總會出現一些不同,你把它定義成一種東西,對于我每做一個修改,都要背負著其他所有實體的特異性。于是就逐漸拖慢了我改變的速度,降低了響應能力。
無謂的自動化
有追求的程序員一定會考慮提升工作效率,通過一些自動化的手段來縮短流程,提高效率。不過有時候,這種追求也會有害。
在我們的系統里有一個面包屑功能,就是典型的“頁面A / 頁面B / 頁面C”那種面包屑。團隊成員提出,一個個頁面寫面包屑好煩啊,干脆做一個根據URL生成面包屑的功能吧。乍一看好像提高了效率,但實際上URL上的名詞和你想顯示在面包屑上的名字是可能出現不同的。
比如在我們的場景里,我們提供一個任務卡的預覽功能,你的面包屑可能是“xx后臺 / xx 訓練營管理界面 / xx卡預覽”,而學生正式使用任務卡的時候,他可能是 “ 學習中心 / xx 訓練營 / xx卡 ”。而他們的url里可能都會出現'/programs/$pid/tasks/$tid'。同樣的program、task翻譯出來的文字完全不同。你為了支持這點不同,又要擴展一些額外功能來做這種區分,做來做去,可能還不如直接寫來的方便,至多抽幾個常量來簡單的消除一下重復。
當我們只從代碼上看重復性的時候
這個我就不舉例子了,其實很多犯這個錯誤的人都是重構的支持者,不過學藝不太精。因為如果你仔細看的話,重構里好多懷味道都有一個跟他對立的懷味道,比如發散式變化和霰彈式修改。如果我們只看代碼就會違背復用的本質——更好的響應變化。
這個跟我說的***個場景,只關注功能視角是類似的問題,這個可能更具象一點,只關注代碼。
無視上下文的時候
這個可以看作是只有功能視角的一種情況,很多功能我們覺得有重復性,提升成一個概念,然而其實根本是兩個東西,他們只是剛好叫一個名字。
比如過去很多軟件里,是有一個統一的用戶組概念,不管你在哪個業務上下文里,你都需要擴展這個用戶組的概念來管理用戶的權限。這個帶來的結果就是用戶組變得越來越臃腫,每次修改都要改一下別的組的功能。在我們的網校數字平臺里,學生學習有學習小組,老師出題有出題小組,這兩個小組業務完全不一樣,這個時候如果都用統一的用戶組來管理的話,那就勢必會造成無謂的耦合,損害響應力。
這些故事告訴我們,我們不是在真空里去做復用。我們做的軟件都是有它的商業目的。我們的工程實踐也都是為商業目的服務的。當我們說tech@core的時候,讓我們說技術就是業務的時候。誠然,他給技術人員帶來了更多的權利,然而權利越大,責任也越大。技術人員也需要跳出技術,具備更多的業務視角和體驗視角。而不僅僅是沉浸在技術得自high當中。才能真正的發揮出各種實踐的價值。
【本文是51CTO專欄作者“ThoughtWorks”的原創稿件,微信公眾號:思特沃克,轉載請聯系原作者】