談軟件職責劃分的重要性

? ? ? ? 軟件職責是一個老生常談的話題。如何劃分一直都有相關(guān)的原則指導進行??烧嬲軌蜃龅秸_,恰當?shù)镍P毛麟角。一方面因為每個人對原則的理解不一致,另外一方面不遵守原則也許短期內(nèi)不會暴露出問題。相反原則的遵守卻并不能帶來立竿見影的好處,迫于項目進度的壓力,原則是可以犧牲的。

? ? ? ? 關(guān)于軟件職責的劃分原則大到架構(gòu)設計,小到類,函數(shù)的設計書籍連篇累牘,本文不準備堆砌這些知識點。鑒于我們大部分書籍示例都是虛擬項目,本文以真實產(chǎn)品項目中的一個具體問題來闡述職責不合理導致的后果,以及由此延伸出的對軟件開發(fā)過程中需求分析,架構(gòu)設計的思考。

? ? ? ? 為了便于理解后文要闡述的問題。首先對涉及的產(chǎn)品和軟件做一個簡要介紹。我們事業(yè)部核心產(chǎn)品是監(jiān)護儀,準確來講是監(jiān)護系統(tǒng),包括中央監(jiān)護站(簡稱CMS)以及床旁監(jiān)護儀(簡稱PM)。床邊監(jiān)護儀的產(chǎn)品形態(tài)非常多,這里僅列舉本文中涉及的兩代監(jiān)護儀,分別簡稱為Tx PM,Nx PM。床旁監(jiān)護儀顧名思義是在床旁直接和病人相連,通過各種傳感器采集和計算諸如ECG,SpO2等生理參數(shù),同時監(jiān)測參數(shù)變化并給出報警。中央站通常是部署在護士站的PC監(jiān)護系統(tǒng),通過網(wǎng)絡與床旁監(jiān)護儀通信。監(jiān)護儀將機器狀態(tài),生理參數(shù),波形以及報警傳輸?shù)街醒胝荆瑢崿F(xiàn)護士或者醫(yī)生不需要到各個病床就能掌握病人生理情況的目的。另外中央站上還可以遠程對床旁設備進行設置操作。不同時期和團隊開發(fā)的床旁監(jiān)護儀和中央站的通信協(xié)議不同,上一代的Tx系列采用CMS+協(xié)議,而新一代的Nx系列采用MD2協(xié)議。

? ? ? 中央站上看到的信息幾乎和監(jiān)護儀界面幾乎是一致的。基于業(yè)務相同的設計理念,新一代N系列監(jiān)護系統(tǒng),中央站和監(jiān)護儀的軟件架構(gòu)平臺"復用"。當然中央站和監(jiān)護儀所采用的操作系統(tǒng)不同,通過一個內(nèi)部開發(fā)的操作系統(tǒng)適配層(MMOS)進行隔離。由于篇幅有限,MMOS中間層不在本文的論述范圍。整個監(jiān)護系統(tǒng)為"分布式"系統(tǒng),交互相對復雜。本文探討的問題涉及其中兩個子系統(tǒng),分別為前端(Frontend)和后端(Backend)。為避免增加閱讀和理解問題的難度,同時基于信息安全考慮,文中僅闡述這兩個子系統(tǒng)。另外牽涉到上一代Tx監(jiān)護儀,本文對中央站和其交互過程一并進行呈現(xiàn)。交互框圖如下:

圖片發(fā)自簡書App

? ? ? ? Tx系列監(jiān)護儀不是分布式系統(tǒng),不區(qū)分前端和后端,為單進程程序。Nx系列監(jiān)護儀的前端與后端作為獨立的進程部署,彼此同樣采用MD2協(xié)議通信。根據(jù)架構(gòu)職責劃分原則,后端負責處理參數(shù),波形,報警,機器模式等監(jiān)護業(yè)務邏輯,前端負責呈現(xiàn)參數(shù),波形,報警文字以及聲光等。前端采用數(shù)據(jù)流的架構(gòu),核心設計思想是系統(tǒng)中存在一個業(yè)務數(shù)據(jù)模型,會定時周期往UI層推送,UI層響應關(guān)注的數(shù)據(jù)變化刷新顯示。

? ? ? ? 如此長的篇幅來介紹項目背景,只為后續(xù)更好的闡述要討論的問題。開發(fā)過程中可能會遇到層出不窮的問題,本文涉及到的不是重大的技術(shù)難題,甚至在進度面前都不能稱之為問題。但是卻非常具有代表性,也側(cè)面反映出軟件開發(fā)之怪狀:簡單的事情不按原則辦,復雜的事情考慮不全面就開始干。

? ? ? ? 本文的反思由測試人員提出的故障而引發(fā)。故障現(xiàn)象為Nx監(jiān)護儀連接中央站的情況下,監(jiān)護儀進入待機模式(中央站和監(jiān)護儀狀態(tài)一致,同處于待機模式),此時監(jiān)護儀因電池電量消耗觸發(fā)電池電量低的報警,而中央站卻沒有觸發(fā)該報警。前文已闡述,中央站和床旁監(jiān)護儀包括報警在內(nèi)的信息要保持一致。

? ? ? ? 當然從臨床場景和風險的角度權(quán)衡,該問題還沒錄入故障庫就"壽終正寢"了。不過因為測試人員找到我分析故障原因,才有幸看到如下代碼:

? ? ? ? 闡述問題前,有必要澄清下待機及電池電量低報警的需求:

? ? ? ? 1.待機模式下屏蔽所有報警,包括生理報警和技術(shù)報警。

? ? ? ? 2.待機模式下屏蔽所有報警,包括生理報警和技術(shù)報警。[需求變化]電池電量低報警除外。

? ? ? ? 首先拋開職責劃分的原則不談,單就函數(shù)代碼可以窺見其開發(fā)者對新一代監(jiān)護軟件平臺架構(gòu)是不理解的。新一代架構(gòu)的核心思想,數(shù)據(jù)流會定時推送到UI層。該函數(shù)僅在響應待機狀態(tài)變化時清除報警列表無濟于事。因為下一秒數(shù)據(jù)流仍然會推送報警列表到UI層,此時待機狀態(tài)未變化而不會清除報警列表,因此被清除的報警下一秒又"神奇"的出現(xiàn)在界面上。

? ? ? ? 從該函數(shù)的最后一行代碼可以推測應該出現(xiàn)過上面說的問題。該行代碼回調(diào)的函數(shù)實現(xiàn)了進入待機時隱藏報警區(qū)。因此避免進入待機時清除報警列表的一秒后,仍然無法屏蔽報警的問題。代碼如下:

圖片發(fā)自簡書App

? ? ? ? 從功能上講,此更改修復了故障。但從編程能力上看,該開發(fā)者不能寫好一個函數(shù)。函數(shù)職責劃分不合理,既然有專門的函數(shù)更新報警列表,待機模式下清除報警,理應由該函數(shù)處理,而不至于放在響應待機狀態(tài)變化的函數(shù)中處理。也許開發(fā)者認為報警列表對象為類的成員變量,放在哪個函數(shù)處理都無所謂。但成員變量本質(zhì)上就是類域的全局變量,具有同樣的副作用,訪問及改寫不受控。造成目前的實現(xiàn)方式,唯一合理的解釋是:處理待機狀態(tài)變化的函數(shù)本身就是一個補丁。處理報警列表更新的函數(shù)此前已編寫完成,可能甚至通過測試。到后期突然測試人員發(fā)現(xiàn)某個故障,開發(fā)人員因為沒有理解之前的代碼邏輯或者不愿意更改之前的邏輯,因此新寫一個函數(shù)來實現(xiàn)清除報警的功能。

? ? ? 退一步講,打補丁在項目后期無可厚非。但總不能隨意,破罐子破摔。既然打補丁就是想在不引入其他問題的情況下,去解決已發(fā)現(xiàn)的問題。而在第一次補丁時并沒有解決待機下仍顯示報警的問題,第二次補丁通過隱藏報警區(qū)才解決掉。但其實引入更深層次的問題,極其隱蔽。本文不展開討論如何打補丁,而是來探討第二次補丁引入的問題,以及如何避免補丁。其實本文涉及的問題用補丁的方式已無濟于事,按下葫蘆起了瓢。

? ? ? ? 在開始探討接下來的問題之前,首先我對這個補丁函數(shù)進行改寫,避免兩次補丁造成不必要的干擾。重寫后的函數(shù)如下:

圖片發(fā)自簡書App

? ? ? ? 重寫的函數(shù)和之前的邏輯是等價的,但卻可以去掉通知UI待機狀態(tài)下隱藏報警區(qū)的函數(shù),也即是第二次的補丁??赡苎奂獾娜藭l(fā)現(xiàn)被去掉的函數(shù),邏輯不對等。if分支隱藏報警區(qū)和報警狀態(tài)區(qū),而else分支卻只顯示報警狀態(tài)區(qū),兩者不對等。那當退出待機模式后,會不會出現(xiàn)不顯示報警區(qū)的問題?這里又有一個奇葩做法,驚喜不斷,在UI響應報警列表更新的函數(shù)中,當報警列表不為空則顯示報警區(qū)。這個實現(xiàn)方式實在讓人難以理解,本來打補丁就是不愿意和之前的更新報警列表函數(shù)邏輯有瓜葛,可到最后仍然徒勞,還是在報警列表更新函數(shù)增加了顯示報警區(qū)的邏輯。不過在重寫待機狀態(tài)響應函數(shù)之后,去掉了隱藏報警區(qū)的邏輯,那么報警列表更新函數(shù)中的顯示報警區(qū)的邏輯就沒有存在的必要了。

? ? ? ? 重寫待機狀態(tài)響應函數(shù)后,代碼變得相對清晰整潔。實現(xiàn)的邏輯是等價的,但卻少一個函數(shù)。重寫的函數(shù)并沒有做任何具體的更改,僅僅是根據(jù)架構(gòu)的設計思想來編寫代碼。從之前函數(shù)代碼的本質(zhì)業(yè)務邏輯講,它想干的事情就是待機模式下不顯示報警,而至于是否隱藏或者顯示報警區(qū)是未考慮架構(gòu)的約束,實現(xiàn)方式不合理導致的額外處理。重寫的函數(shù)完全實現(xiàn)了之前的本質(zhì)邏輯,只要在待機模式下就清除報警,而不僅僅是在待機狀態(tài)發(fā)生變化時才清除。這時就會發(fā)現(xiàn)隱藏或者顯示報警區(qū)的處理完全是多此一舉。當然重寫的函數(shù)并不解決任何問題,只為不干擾后續(xù)的論述。

? ? ? ? 從上面的分析可以得出響應待機狀態(tài)的函數(shù)本身是補丁。那么接下來就得分析為什么需要這個補丁。這里有必要推演下床旁監(jiān)護儀和中央站關(guān)于待機模式的需求及開發(fā)演變的過程。

? ? ? ? 上一代的Tx監(jiān)護儀和中央站為兩個團隊各自開發(fā)。Tx監(jiān)護儀待機功能的原始需求如前文所述要屏蔽所有報警,但因為Tx監(jiān)護儀在待機模式下,界面上不顯示任何信息,僅顯示待機字樣提示。而中央站的界面卻并不同,除了顯示待機字樣提示,仍顯示報警區(qū)。Tx監(jiān)護儀開發(fā)時沒有將所有報警在待機模式下都屏蔽干凈,而其界面又無法發(fā)現(xiàn)該問題。當中央站的測試人員無意中發(fā)現(xiàn)Tx監(jiān)護儀在待機模式下仍有報警發(fā)送到中央站,并同時報告給Tx監(jiān)護儀的開發(fā)人員和中央站的開發(fā)人員。監(jiān)護儀開發(fā)人員一臉蒙逼,兩手一攤說版本都發(fā)布了,下個版本再說。中央站的開發(fā)人員心里一萬只草泥馬奔騰,干脆就一不做二不休在中央站屏蔽報警。Tx監(jiān)護儀下個版本開發(fā)過程中因為再沒有人反饋待機下未屏蔽報警的問題就不了了之了。

? ? ? 不幸的是,Tx監(jiān)護儀的待機需求發(fā)生變化,考慮到風險,待機模式下不能屏蔽所有報警,至少電池類報警不能屏蔽。這下開發(fā)人員炸了鍋,首先監(jiān)護儀待機模式下不顯示任何信息,怎么可能顯示出報警來?需求人員也跳了起來,態(tài)度堅決的說一定要報出來。這么高風險的報警不報,出了問題誰負責。于是大家僵持后不歡而散。

? ? ? ? 沒辦法,討論范圍要擴大,中央站開發(fā)人員被參與進來。中央站開發(fā)人員罵娘了,即使監(jiān)護儀報出來,中央站不可能報出來,上個版本老子才從根上屏蔽待機下的所有報警,現(xiàn)在來這么一手肯定搞不定。討論展開拉鋸戰(zhàn),突然中央站開發(fā)人員提出即使新版本可以再打補丁不屏蔽電池電量低的報警,但是有兼容性問題,監(jiān)護儀連上個版本還是報不出來。這無疑拋出重磅炸彈,大家一聽立刻打起十二分精神??隙ú荒苓@么搞,要換思路,堅決不能引入兼容性問題,不能背這個歷史包袱。于是決定得有資深人員來系統(tǒng)性考慮方案,兼顧監(jiān)護儀和中央站,前提是不能引入兼容性問題。監(jiān)護儀要支持待機下不屏蔽電池電量低的報警,除了需要更改電源管理模塊電池報警觸發(fā)邏輯外,主界面也需要更改顯示出報警區(qū)。中央站還需要同步更改再次補丁,屏蔽除電池電量低外的所有報警。但這就會出現(xiàn)前面說的兼容性問題,而且導致監(jiān)護儀和中央站的業(yè)務耦合在一起,更改和測試的工作量也相對較大,這是不可能接受的。

? ? ? ? 活人終究沒被尿憋死,找到了一個"天才"的完美方案。"反向"思維這個時候發(fā)揮了至關(guān)重要的作用,待機下不屏蔽電池電量低的報警需求既然這么難搞,那為什么不反其道而行之,在出現(xiàn)該報警時自動退出待機模式呢。如此一來,所有問題迎刃而解,Tx監(jiān)護儀任何時候都可以報出這個報警。而對于中央站而言可以不做任何更改,待機下仍然屏蔽所有報警,監(jiān)護儀有特殊報警要在待機下報出來就自動退出待機。這是個皆大歡喜的方案,甚至建立起一種處理待機特殊報警的機制,中央站和監(jiān)護儀待機業(yè)務徹底解耦,不需要關(guān)注監(jiān)護儀待機下的特殊處理。而且更改工作量小,影響可控??晌í毿枨笕藛T不接受,認為出現(xiàn)電池電量低報警自動退出待機不合適,用戶會很困惑。

? ? ? ? 于是又開會討論,這次領導和各個技術(shù)組的頭頭都到場。需求人員開始發(fā)牢騷抱怨,而開發(fā)人員同仇敵愾,認為這是目前最優(yōu)的方案,不但工作量小,影響可控,而且不會有任何的兼容性問題,說到這開發(fā)人員的聲音提高了幾度。雙方各執(zhí)一詞,大家把目光都轉(zhuǎn)向一臉凝重的領導。領導終于開口了,深思熟慮的說這個方案不是最好的方案,但是可行的方案,相比于風險而言,自動退待機用戶不至于不接受。另外從臨床場景看,待機下不插電源可能性比較小,出現(xiàn)這個問題的概率不大。"繡球"又拋回給需求人員,只見他們敢怒而不敢言,一臉委屈的說這樣也行吧。此時領導話鋒一轉(zhuǎn),口氣嚴厲的給在場開發(fā)人員訓話,我們回去后要反思為什么會出現(xiàn)這樣的問題,以后要如何避免類似的問題。所有開發(fā)人員若有所思的鄭重點點頭,一副醍醐灌頂?shù)臉幼?。最后領導做總結(jié)呈辭,目前就定這個方案,后面下一代監(jiān)護系統(tǒng)要從設計上全局考慮,系統(tǒng)性的解決這個問題。

? ? ? ? 各方向都滿意而歸,中央站方面不需要進行任何更改,此前那個待機下屏蔽所有報警的補丁就這么根深蒂固的被保留下來。Tx監(jiān)護儀通過自動退待機"優(yōu)雅"的規(guī)避掉報不出電池電量低報警的問題。監(jiān)護儀版本順利發(fā)布,大家對這個問題都有較為深刻的印象。

? ? ? ? 新一代的Nx監(jiān)護儀在緊鑼密鼓的開發(fā)中。此前那個待機屏蔽報警的問題刻骨銘心,于是設計時吸取經(jīng)驗教訓并"反思",一方面認為Nx監(jiān)護儀在待機模式時前端界面仍需要顯示報警區(qū)。另外一方面待機需求又發(fā)生變化,退出時必須手動選擇解除病人或者恢復監(jiān)護,不能自動退出。因此只能通過后端屏蔽除電池電量低外的所有報警。Nx監(jiān)護儀在待機模式下發(fā)生電池電量低時,可以正常觸發(fā)報警并顯示,而不在需要自動退出。Nx監(jiān)護儀前端界面在待機模式可顯示報警區(qū),所有的報警都被要求測試在待機模式下被屏蔽而不顯示。

? ? ? ? 待機模式下Nx監(jiān)護儀后端發(fā)送到中央站后端的報警列表已正確處理過,中央站前端只需呈現(xiàn)出來即可。當待機模式下出現(xiàn)電池電量低報警時則顯示,不存在時列表為空自然而然就不顯示報警。如此中央站前端收到后端的報警列表再進行判斷是否為待機模式而清除過濾就畫蛇添足了。

? ? ? 由此引發(fā)測試人員反饋的Nx監(jiān)護儀連接中央站待機時出現(xiàn)電池電量低,監(jiān)護儀可以觸發(fā)報警,而中央站卻不觸發(fā)報警的問題。前文提到的兼容性問題居然死灰復燃了。出來混遲早要換的,一時的規(guī)避,最終又讓Nx監(jiān)護儀再次掉坑里。

? ? ? ? 出現(xiàn)這個問題時,相關(guān)負責人迅速組織會議討論解決方案。會議的部分參與者經(jīng)歷過此前Tx監(jiān)護儀和中央站在待機模式屏蔽報警更改方案的討論。會上有人提出Nx監(jiān)護儀得按照當年Tx定下的機制實現(xiàn),待機模式下發(fā)生電池電量低的報警時則自動退出。Nx監(jiān)護儀開發(fā)人員強烈反對,這是歷史遺留問題,我們新一代產(chǎn)品要甩掉歷史包袱,不然負擔太重。其實潛臺詞是Nx監(jiān)護儀無法自動退出待機。新一代產(chǎn)品跟老產(chǎn)品中央站有點兼容性問題用戶也是可以理解的嘛。況且Nx監(jiān)護儀發(fā)布之后馬上就要開發(fā)統(tǒng)一軟件平臺的新一代中央站,到那個時候再解決也不遲。

? ? ? ? 產(chǎn)品換代嘛,總得經(jīng)歷一個陣痛的過渡期。于是解決問題的重擔落到新一代中央站的身上。這個問題已經(jīng)被反復提出來討論,有點炒剩飯的意思,已不如當年那般有震撼力。由于業(yè)務的優(yōu)化,組織架構(gòu)的調(diào)整,人員的重組,Tx監(jiān)護儀的維護已由西研的團隊接管,總部都投入到新一代監(jiān)護系統(tǒng)Nx系列的研發(fā)中。在Nx監(jiān)護儀上線發(fā)布后,原班人馬"兼收并蓄"了中央站團隊,因此總部都Focus在Nx系列上。當年參與討論Tx監(jiān)護儀和中央站待機屏蔽報警問題的人可能都已經(jīng)不太參與實際代碼的編程,其工作更多由團隊成員完成,他們只是把控關(guān)鍵的技術(shù)風險問題。待機問題已成剩飯,有些細節(jié)大家早已模糊,而新成員根本就不清楚這里面的道道(大坑)。

? ? ? ? Nx系列復用同一軟件平臺,對于待機下屏蔽除電池電量低外所有報警功能的測試,經(jīng)過等同性分析被認為不需要了。因為在開發(fā)Nx監(jiān)護儀時已對待機下所有報警的屏蔽做過細致全面的測試,中央站和監(jiān)護儀復用前端架構(gòu)及代碼,開發(fā)人員分析可以完全等價。

? ? ? ? Nx中央站研發(fā)時開始試水和西研團隊的協(xié)同開發(fā)。響應BU的大號召,逐步將軟件功能實現(xiàn)轉(zhuǎn)移過去,總部只負責關(guān)鍵技術(shù)方案設計,技術(shù)風險把控以及產(chǎn)品質(zhì)量控制。在這樣的大背景下,Nx中央站的開發(fā)時,考慮到西研團隊年輕經(jīng)驗不足,因此劃分"業(yè)務簡單"的前端部分功能到西研團隊。

? ? ? 西研測試團隊收到總部指示,潛意識認為Nx中央站的待機功能和監(jiān)護儀等同。測試人員重點關(guān)注Nx中央站和上一代和前x代監(jiān)護儀的交互。于是發(fā)現(xiàn)Tx監(jiān)護儀和Nx中央站在待機時,中央站仍能觸發(fā)報警的問題。西研團隊懵圈了,不是和Nx監(jiān)護儀一樣報警列表都被監(jiān)護儀正確處理過的嗎,怎么連接Tx監(jiān)護儀就出問題呢。于是報告給總部,當年掉坑里的中央站開發(fā)人員興奮的叫起來:"媽蛋,老子當年就掉這坑了。Tx監(jiān)護儀在待機下報警沒屏蔽干凈,為了給它擦屁股,不得已在上一代中央站上打補丁屏蔽報警。

? ? ? ? 這個問題已不能引起轟動,況且以后主流趨勢是與新一代Nx監(jiān)護儀互連。這次沒有展開太多的討論即達成結(jié)論,Nx中央站和Tx監(jiān)護儀互連,只是為了向前兼容而已,他們遲早要停產(chǎn)的。因為互連Nx監(jiān)護儀不會出問題,于是傳遞給西研團隊解決方案是簡單處理,避免影響擴散,增加測試人員的工作量。西研團隊充分領會總部的精神,和老中央站一樣打個補丁繼續(xù)給Tx監(jiān)護儀擦屁股。

? ? ? ? 這屁股擦的"萬劫不復",新一代Nx中央站肩負解決連接Nx監(jiān)護儀待機下不能報出電池電量低報警的問題。原本軟件復用自然而然就沒有問題。可又再次挖出當年和Tx監(jiān)護儀的舊債,作為僅負責開發(fā)新一代中央站部分前端功能的人來說,他能做的只能按照過去一樣的補丁方式處理。但要是考慮全面一點的話,至少判斷下連接Tx監(jiān)護儀才走補丁的邏輯,對于Nx監(jiān)護儀則不處理。但時代變了,監(jiān)護系統(tǒng)的架構(gòu)變得更加精細,架構(gòu)約束前端不允許針對連接的特定監(jiān)護儀機型做特殊處理。也即是說,中央站前端獲取不到當前連接的監(jiān)護儀機型。況且西研中央站前端開發(fā)人員壓根就不知道Nx監(jiān)護儀那么"變態(tài)",還有報警在待機下需要觸發(fā)出來。另一方面前端開發(fā)人員甚至還可能"自鳴得意"考慮周詳,既然無法獲知機型,那就等同了,而且杜絕以后Nx監(jiān)護儀萬一出現(xiàn)待機下報警屏蔽不干凈的問題時,中央站可以"獨善其身"。可不曾想中央站需要連接"無數(shù)種"的床旁監(jiān)護儀。這種單方面的以偏概全的補丁解決故障表面現(xiàn)象的背后,其影響是巨大的。

? ? ? 最終新一代Nx中央站連接Nx監(jiān)護儀時,同樣出現(xiàn)本文開篇提到的問題,待機下中央站不觸發(fā)電池電量低的報警。層幾何時這個問題在上一代產(chǎn)品,上一代和新一代過渡期都出現(xiàn)過。似乎這個問題是幽靈般讓我們陷入怪圈。而且每次由不同方向的人提出來,這次的測試人員是個不太熟悉"業(yè)務"(不知道水有多深)的新員工,甚至他一開始還認為是Nx監(jiān)護儀的問題,為啥待機下電池電量低的報警未屏蔽。

? ? ? ? 這次測試負責人找到中央站總工反饋問題,總工高瞻遠矚從臨床風險分析,既然床旁監(jiān)護儀報出來電池電量低的報警,那風險就可接受,而且一旦床旁監(jiān)護儀退出待機,中央站就可以報出來,認為問題不大暫不更改。

? ? ? ? 總工英明啊,要是決定改,我們可以大膽推測后續(xù)更改之情形。因為反復出問題,這次更改很有可能會收回到總部處理,而且職級高的資深人員投入其中,甚至負責Nx架構(gòu)的總工都要參與指導并審核。資深人員是Nx監(jiān)護儀開發(fā)中成長起來的骨干,很快就發(fā)現(xiàn)問題所在,中央站不需要處理報警的屏蔽,Nx監(jiān)護儀后端已處理正確,這個補丁直接刪掉,故障回歸。

? ? ? ? 然后故障回歸驗證時,Nx監(jiān)護儀連接中央站待機下電池電量低的報警可以正確觸發(fā),但是連接Tx監(jiān)護儀時本該在待機下屏蔽的其他報警卻在中央站又報出來了。故障重打開被打回來,開發(fā)人員馬上意識到問題原因。嘴上發(fā)著牢騷:"shit,Tx監(jiān)護儀做得怎么那么爛,待機下報警都不屏蔽干凈。"看來不能對所有機型都去掉這個補丁,至少對Tx監(jiān)護儀不可以。鑒于更改影響,只能再次打補丁在中央站前端判斷機型區(qū)分處理,Tx監(jiān)護儀待機下清除所有報警,Nx監(jiān)護儀不做處理。但架構(gòu)不允許獲取到機型信息,不過這似乎難不倒機智的開發(fā)人員,Nx總有些特定的信息,收到這個信息就認為是Nx機型。這種"曲線救國"的補丁其實在挖更大的坑,而且還在坑上鋪了稻草等偽裝物。將來一旦Tx監(jiān)護儀某個版本增加發(fā)送補丁用來區(qū)別機型的信息,中央站會誤認為Tx機型是Nx機型,對待機下的報警不做屏蔽處理,導致Tx監(jiān)護儀本應該在待機下屏蔽的報警在中央站再次顯示出來。而且中央站測試人員幾乎從不關(guān)注床旁監(jiān)護儀的版本,發(fā)現(xiàn)問題的時候提單為必發(fā)故障。等到開發(fā)人員查問題確認現(xiàn)場時,就傻眼了。明明當時必發(fā)的問題,怎么重現(xiàn)不了。覺得中央站是不是這段時間又改了啥,回退中央站到提故障的版本,仍復現(xiàn)不出來。開始懷疑人生,其實只是因為Tx監(jiān)護儀的版本不同而已。老版本不發(fā)送用于機型判斷的信息,不會掉坑里,新版本會發(fā)送,誤判斷為Nx機型而不做報警屏蔽處理。

? ? ? 當然這種"巧妙"的通過區(qū)分機型來解決問題的方式總工斷然不會贊成的。這時開發(fā)人員跳腳了,這不行那不行的,你說怎么搞嘛?這時總工終于親自深入代碼,一眼就看穿貓膩。接著爆了粗口:"臥槽,怎么TMD這么搞。前端處理個毛業(yè)務啊,待機下清除報警的邏輯必須放到后端去。"病根終于找到了,確診之后就對癥下藥著手啟動更改。

? ? ? ? 病已到扁鵲望桓候而還走的地步,要根治得做手術(shù)才行。此前待機下屏蔽報警的邏輯放在前端,針對連接到中央站的所有機型都起作用,目前只發(fā)現(xiàn)連接Nx監(jiān)護儀待出現(xiàn)待機下不報電池電量低報警的問題??梢坏┮频胶蠖藖砥帘未龣C下的報警,首先得考慮針對哪些機型進行屏蔽處理。要知道中央站除了連接Nx,Tx監(jiān)護儀外,還有Vx,PM,TM等監(jiān)護儀。如果僅針對Tx監(jiān)護儀進行屏蔽處理,不排除其他非Nx系列監(jiān)護儀存在待機下誤報警的問題。如果針對除Nx系列外所有監(jiān)護儀進行屏蔽處理,需要測試確認這些監(jiān)護儀都不存在類似Nx監(jiān)護儀電池電量低的特殊報警,否則同樣面臨目前Nx監(jiān)護儀遇到的問題。

? ? ? ? 改與不改似乎都是兩難的選擇。主管中央站業(yè)務的總工在看到此文章前,即已英明決策不更改。實屬萬幸,否則一陣折騰后講再次回到原點。我們只能期待將來這個問題不會被沒有眼力的新人再次提出來。也許這是程序員的集體困境,問題反反復復出現(xiàn)卻無法徹底解決。也許這也是程序員的出路,否則軟件里面故障改一個少一個,沒有故障程序員都得失業(yè)了。

? ? ? ? 本文是為程序員寫的,我估計很多人看不到最后這段話,這是情理之中的事情。如果能堅持讀到最后,肯定是有做好程序員的愿望和態(tài)度。如果還能從廢話連篇的描述中梳理出整個問題演化的過程來,說明具有做好程序員所具備的邏輯思維的潛力。如果不但能梳理出事情的脈絡,還能提出質(zhì)疑來,要么是成為"大師"的潛質(zhì)前奏,要么就是當年挖坑或者掉坑里的人。

? ? ? ? 要殺死一個程序員,變化三次需求足矣。作為程序員應該反思是需求真的變了嗎?還是在溝通時選擇性聽取需求?還是在按照自己的理解意淫需求?還是在構(gòu)思設計方案時"創(chuàng)造"需求?

? ? ? ? 有點亂,我們來梳理下整個更改過程的脈絡。問題發(fā)軔于Tx監(jiān)護儀在待機下報警屏蔽不徹底,中央站開發(fā)人員的"息事寧人"未推動Tx監(jiān)護儀更改解決而在中央站打補丁規(guī)避,接著面對待機下要觸發(fā)電池電量低報警的需求變更時的妥協(xié),成為壓死駱駝的最后一根稻草。至此一發(fā)不可收拾,該問題在Tx監(jiān)護儀,Nx監(jiān)護儀,新老中央站之間如幽靈般反復出現(xiàn),愈演愈烈。最終無法收場不得不"打脫牙和血吞"。

? ? ? ? 待機下屏蔽除電池電量低外的所有報警的需求看似簡單,以至于不受重視。這項需求的關(guān)鍵點在"屏蔽"二字。開發(fā)人員和需求人員所理解的"屏蔽"其實有所不同。開發(fā)人員理解也許只是界面不顯示,而需求人員卻認為屏蔽不僅僅界面不顯示,而且不存儲,還不能發(fā)送到中央站。開發(fā)過程中打著簡化不過度設計的旗號,我們丟掉本質(zhì),僅界面不顯示。如果能理解"屏蔽"的本質(zhì),中央站不至于僅在界面顯示上屏蔽待機下的報警。

? ? ? ? 關(guān)于監(jiān)護系統(tǒng)中監(jiān)護儀和中央站各自承擔的職責,以及前端與后端的職責,架構(gòu)約束可能描述的言簡意賅,很難讓開發(fā)人員達成一致理解而遵守。在第一次發(fā)現(xiàn)Tx監(jiān)護儀待機下報警屏蔽不干凈,就應該推動監(jiān)護儀端更改解決。即使出于進度,更改影響的考慮,中央站不應該在前端,而是要在后端的設備層打補丁。我們因為種種不遵守架構(gòu)定義的職責劃分原則,一步步的退讓妥協(xié)導致最終無路可退。不謀全局者不足以謀一域。要徹底解決問題,卻仍要從全局出發(fā),回歸初心。要么Tx監(jiān)護儀解決待機報警不干凈的問題,而中央站去掉補丁,要么中央站把補丁從前端移到后端針對存在問題的監(jiān)護儀機型屏蔽報警。

? ? ? ? 本文言語戲謔,由真人真事改編而來。作為程序員的你們也許或多或少會看到自己的身影,如有雷同,純屬巧合,請勿對號入座。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 我最擅長的運動大概就是徒步了。諸多運動項目中,游泳我只會蛙泳,游的距離還很短;跑步我最害怕,因為一跑就氣喘吁吁,不...
    相知是緣閱讀 455評論 2 3

友情鏈接更多精彩內(nèi)容