前言
這篇稍微紀錄一下這次讀本書第四篇的感想,前面重點在講測試相關UnitTest,TDD,BDD等等,但我想記錄點別的 The practice of code extensibility跟 Some practical rules for improving readability
Agenda
- The practice of code extensibility (代碼可擴展性的實現)
- Some practical rules for improving readability (一些改散可讀性的實用規則)
前提
- 這篇很重要想說的事: 可測試性,可擴展性,可讀性。可測試性就是要你寫測試,你的程式碼質量會提升的,相對的是你的產力會下降,但在後續維護成本也會下降,有接受過相同規格的工程師,就可以延續你的程式碼繼續工作,就不怕老鳥離職沒人處裡工作了。這就是可維護性的最高價值,老闆阿,主管阿,你們知道了嗎?別以為讓所有工程師都處理到每一個Module或是碰到每一個業務,就可以避免離職後沒人處裡的囧境。(例如: Fontend要搞Backend,要搞Operation,要搞測試QA,最後緊急時候要搞SRE,這不離職才有鬼,也可能公司付出高額薪資獎金留人才也說不定,但我覺得不是很健康就是了,各司其職才是正確作法,專注完美近乎苛求阿,我想說的是專注一件事,可以把一件事做到極盡的完美,相對的處裡很多事務在同一個人身上,容易出現遺漏,不專業等等的狀況)。所以可維護性的價值是很高的。要達到可以維護的程式碼就需要可測試,可擴展,可讀性高。下面紀錄 可擴展 跟 可讀性。
The practice of code extensibility (代碼可擴展性的實現) :
- 這篇還有一個讓我省思的地方就是 “過度設計”,這點我有時候就會犯到,拿捏如何設計得恰到好處,就考驗你的經驗,那什麼經驗呢? 每種會遇到的模式都試過就算數嗎? 當然不是,有些人經驗很久了,但是始終設計不出到味的架構,有時候是能力,有時候是遠見,有時候是太多的雜質在旁影響了他,因為這真的是很難的。我認為是如果你遇到的都是相同的商業模式想必你的前任工作經驗可以使用到現在的工作上。但隔行如隔山,有些經驗是不適用在不同行業上的,這時候經驗可能還會是你的絆腳石。人和經驗就不再話下。人和經驗在哪個職場都適用,離題了。好,如何避免過度設計,你需要檢測3項事: Interface-based design基於接口的設計,Plugin Architecture插件架構,State Machines狀態機。
Interface-based design基於接口的設計
- 接口的意思是指兩個元件之間的一種契約,當一個類可以處理某個接口時,代表著他也可以處裡任何相同的其他元件的接口。其實就是直接new一個實作元件,而透過interface接口的方式去接,方便抽換,降低耦合。也提高擴展性。但這理想提到另一個問題就是你應該全部的方法類別都這樣做嗎?把所有的類都設計成可擴展的方式,本文說這是很不實際的,因為這會兆呈你過度設計。本文也說這是蠻困難的挑戰,你得弄清楚哪裡才是你專案邏輯需要共用的接口。我也是看到本文在知道原來不是每個方法類別都需要做interface。
Plugin Architecture插件架構
- 另外一個提高擴展性的方法是使用插件模式,我第一個想到的就是使用Nuget Package,將自己的類別,Utility等等的工具library封裝成Nuget套件,透過下載安裝方式來使用,這樣可以讓其他專案也使用到該工具library,也不需要重刻工具library。但這裡沒提到Nuget Package,但內部作法差不多,一樣需要一個專有的專案,將內部功能抽出來,一樣使用interface或是abstract方法抽象化,在搭配IOC方式透過Config做抽換。但有一點不是很明白本文所謂的程序的狀態共享給插件。如果我的log放在這個package內,每個使用這個library會透過實例的時候建出新原件,他是說這個原件將會共用嗎? 這我覺得不太像,每個Process有自己的application,application之間可以共用交流,但Process之間是無法的,他們是獨立分開的。如果他說的是application狀態給package應該就可以,反正都是在自己的Process應用之內,然後會需要拉出共用的Data Class讓兩個專案都可以使用到。
State Machines狀態機
- 狀態機說明到把複雜的功能分成個別的步驟做管理,文件說明最簡單的方式是使用switch。雖然使用switch本身違反SOLID的單一職責跟開放關閉原則。但在這裡你可以輕易透過switch新增一個狀態方法的路線,這在以前建置JOB專案時候使用過,給個JOB有自己的名稱或是代號,透過這個名稱帶入進入點,讓他啟動到對應的程式碼,這也是一種簡易的擴展性的方式。
Some practical rules for improving readability (一些改散可讀性的實用規則):
Comment
- 註解,這個想必大家都知道,問題是有人不寫而已,還有就是寫的不清楚。但這裡要特別說到一點就是“禁止明顯的註解”,寫太明白也不好? 沒錯,我剛看到的時候也有點驚訝,但仔細思考後,沒錯耶,你寫的落落長就模糊了焦點,只需要告知這個方法的主要目的即可,其他的都會干擾。
Consistency
-
一致性,沒錯就是你原本怎麼寫就別一直換來換去,但是這邊想說一個很妙的狀況,多半我都是看公司怎麼寫我就怎麼寫,畢竟一開始不是我設計的,如果我使用我慣用的方式,那可是會摧毀一致性的,所以很妙的狀況是,原本的程式碼很差,我該延續一致性嗎? 也不能說差,只是我剛好有經歷過更好的方式,所以我知道有更好的寫法或是應用,但是根據一致性規則,我坦白說,我不會去”甲會”。因為違反一致性規則是,公司資深元老會來撻伐你的,除非你有更高的頭銜,或是更高的聲望,但有這兩點你也不會是寫程式的了。為了維護團隊的和諧,我選擇維持一致性。你一定想問團隊和諧? 這是什麼? 適者生存阿。以前曾經這樣想過,但是這樣最終會導致離職率提高的,而且最終實作重構這件事,很重要的一個先決條件就是團隊是否團結。沒達到這個先決條件,直白地說,重構是望塵莫及。
-
要達到可讀性,一致性的原則很重要,而且這個原則是公司層級的,絕對不是個人,絕對不是,而每個公司部門都應該在教育訓連時期,告知這件事,而且是強力執行,這就是公司的鐵則,寫出有瑕疵的代碼是常發生的,是人就會出錯,但這種一致性規則是可以強力限制的,而且可以透過IDE工具限制或是Code Review,養成一種習慣。沒有含糊的地方可言。有人說這大公司才有吧,我覺得也不用多大,3個人的團隊就應該要有,除非你一個人團隊。誰去定當然就是你啦,技術主管 (主管,架構師)。
Clarity
-
清晰性,有一個狀況是你寫簡單一點,大家就懂了。但是有時候英雄主義犯了,想寫出高深,沒人看得懂的,卻又可以正確執行的程式碼,好像沒人懂就是最棒一樣。這是不好的,最終會傷害整體維護。嘿嘿,你可能會說,我覺得很清楚啊,那是其他人程度太低。好吧! 可能真的太低,但試問有問題只有你能解,你是很重要的,也可以達到公司重用你,但是你會很忙,忙到死,薪水可能會有漲,但是不會漲得很誇張。這是因為寫程式的終歸是寫程式。不是老闆,不是主管,不是有頭銜的。他不會給RD的錢跟主管一樣多。所以你會面臨領差不多的錢,但是做很多事,然後你不能推遲,因為那些程式碼是你寫的,沒人看得懂。別自食惡果了,讓團隊都懂才是好事,有時候一起成長一起努力也是不錯的。
-
我曾經改過一段程式碼,使用極盡可能的方式將它優化,提升它的速度,最後他真的提升了,秒數比之前快上75%。很爽,但是可讀性很差,不過因為當時主管的目標是希望他可以更快一點,希望提高效能,而且根據KPI論,我得量化他,當時重構我也達到了我的目的。不過在之後的某一次重構上,它又被其他同事改了,改成可讀性高的程式碼,但是效能就沒辦法跟我之前的比了,這樣KPI又可以在寫了嗎? 他怎麼量化的呢?哈哈。這不是重點。重點是取捨效能好還是可讀性高,這兩點我覺得要看部門討論,抓出一個目前業務上可以都符合的一個方式,既不影響效率,也可以達到程式碼可讀性。
Short the Better
- 如果可以簡短,就盡量簡短一點寫吧,本文建議以一個滑鼠滾輪為一個範圍,如果查看該方法的程式碼超過兩個滾輪,可能就不方便閱讀,保持在同一個區塊更好。或是你的方法超過30行,也可以注意是不是需要重構。