Re: [討論] 前人的code 後人翻寫的機率高嗎?

作者: accessdenied (存取違規)   2018-09-26 19:55:39
單元測試有時候反而破壞程式碼的易讀性和維護性
因為要做到單元測試,就得斷開所有的相依性
而對抗相依性,作法就是引入 DI。但是 DI 就會增加代碼閱讀和維護的複雜度。
舉例來說,如果代碼內有時間上的相依性,例如用了 DateTime 物件取得現在時間做某些
判斷,原本可以很簡單的寫出易於閱讀和維護的邏輯:
If (DateTime.Now > 12:00:00) then return “PM” else return “AM”;
為了讓單元測試可以控制驗證條件,只能
Interface IDateProvider { virtual GetNow(); }
Class DateMock : IDateProvider { GetNow() { return 13:00 }
IDateProvider dateProvider = container.Build(....);
If (dateProvider.GetNow > 12:00:00) then return “PM” else return “AM”;
然後再搞個 config 想辦法讓程式吃到你寫的 DateMock 類別....
上面是sudo code 就不用討論語法細節
這就是單元測試的代價!程式真的會比較容易閱讀嗎?
單元測試要花在切除相依性的條件花費的成本時間遠高於撰寫production code
而且你的 production code 能不能賺錢還不知道咧?
到底需不需要單元測試和 clean code ? 先搞清楚寫的用途和目的,你寫的東西有沒有
真正的商業價值再說吧。
不要把 clean code 和 TDD 無限上綱了
工程師最容易自嗨就是這樣,還會自以爲「這是專業」?
乞丐的乞討專業比我們強也不會產生「價值」。
※ 引述《banqhsia (BEN)》之銘言:
: ※ 引述《peanut97 (丁守中)》之銘言:
: : 大家中秋節快樂,快收心了。
: : 想問一個假設性問題,大家在工作上,如果有一份專案的 code 是某位前人一手寫的
: : 後來新人加入,變成前人帶新人,此時繼續維護那份code。
: : 但再過一陣子,前人離職了,唯一的創始者走了。
: : 新人把舊 code 重構,或是砍掉重鍊的機率高嗎?
: 先跟主管、老闆提,確認有人支持你,不然你會被當成怪物
: 「為什麼要改?」
: 「系統好好的幹麻改?」
: 「改了有好處嗎?」
: 「會花多久時間?」
: 「時間剩不多,要動不動隨便你,不要影響到時程」
: : 我的想像是,如果一份code是出自於1個人之手
: : 我的想像是,如果一份code是出自於1個人之手
: : 那麼code就是他的世界觀、他的切入點
: : 那麼code就是他的世界觀、他的切入點
: : 後面的人看著他的世界觀,有時候不一定能全部接受
: : 而有人的地方就有政治
: : 當他還在的時候,當然就不會亂動。
: : 而當他走了的時候,後面的人,一看不爽,就可能改寫成自己看得爽的、
: : 好改的code。
: : 如果是一個團隊,那當然要好好討論為什麼要改
: : 哪些因素造成現在不好的情況,以及主管同不同意改等等的。
: : 只是我很好奇,1,2人的專案,改的機率高嗎?
: : 是不是,code只能是「現在還存在公司的人」能控制的才行。
: 我們公司的經驗,以前因為很多原因 (十幾年前的 code)
: 導致系統沒有測試、沒有嚴謹的 coding style、方法註解也很少
: copy paste 是基本,沒有遵照 SOLID
: 錯誤不是丟 null 就是 false (欸! 我的 Exception 呢?
: 每個 team 成員想怎麼寫就怎麼寫,不管後續的漣漪
: 反正東西交出來就好 多棒
: 然後中間當然成員就是來來去去的
: 我看這之中大概也是 有人進來 -> 看 code -> what the fuck? -> 離職
: 大概就是這種循環
: 因為自己痛過,知道 clean code、設計模式 的重要性
: 進公司沒多久就跟主管說這 code 不能搞,一定要重構
: 每個工程師一定看不爽前人的 code XD
: 但是不是說說而已,總是要提出改善的方法
: 理所當然地,你前面那些問題我都被問過
: 幸好我的主管與老闆也是支持我這件事情
: 但是我們討論的結果,現在的 code 也沒辦法全部翻掉,怎麼辦
: 在那個時候剛好要把原本的系統生出一套 API
: 原本的系統是 server-side template render,模板與資料、樣式高耦合
: 這個沒辦法改成 API
: 我們的作法是,把原本 DAO 抽出來,放進框架裡當成 library
: 然後加一層 Adaptor 讓新系統相容舊模組
: 舊的 DAO 邏輯怎樣就不去動他,要改一律在 Adapter 裡面改
: (就算 method rename 也是)
: 在這個新系統,以 SOLID 與設計模式為基楚
: controller 與邏輯之間,包裝成 service 呼叫 (一律把該寫的東西放在該去的地方)
: service 只准有抽象的敘述,實作的部分寫成介面去依賴,由子類別注入 service
: 使用 DI Container 自動注入依賴的類別,不准直接 new (方便替換測試)
: 提交功能分支以前,要一併提交單元測試與 functional test,否則不准進 develop
: 這些都是規定好寫在專案文件裡面的 (以前沒有的文件,現在開始留下記錄)
: 接著就是重頭戲的部分
作者: Killercat (殺人貓™)   2018-09-26 20:10:00
這個很正常 要先界定黑箱範圍 這算FAQ了...黑箱一開始一定非常大 唯一的要求就是testable output慢慢穩定以後才會慢慢的在把黑箱切小另外其實你舉的例子怪怪的 這input output都是testableMock也沒那麼困難 我不知道為什麼要搞那麼複雜...
作者: accessdenied (存取違規)   2018-09-26 20:15:00
原本Input不在自己可控的範圍內,早上和晚上測到的output不同就不能說是testable, 因為單元測試應該要能隨時跑、隨時測、都一致。
作者: Killercat (殺人貓™)   2018-09-26 20:16:00
er... Mock DataTime.now()很困難嗎 o_oa?我知道你想表達的點 但是GMock(C++) Mokito(Java)做到這件事情都不困難啊... ?
作者: landlord (91)   2018-09-26 20:17:00
我不用 interface 也可以模擬 DateTime 耶。
作者: accessdenied (存取違規)   2018-09-26 20:18:00
Anyway, 只是個例子,不用糾結在DateTime 的mock困不困難,實務上絕對會遇到為了Mock而大費周章的案例
作者: landlord (91)   2018-09-26 20:18:00
你講的是學習單元測試必定會碰到的障礙,這肯定沒錯但碰到障礙是解決障礙,還是退回原路,就是選擇了
作者: Killercat (殺人貓™)   2018-09-26 20:19:00
有是有啦,不過真的不常見,底層才比較會碰到
作者: senjor (哞哞)   2018-09-26 20:19:00
有,Database的Accessor要MOCK的確蠻麻煩的
作者: landlord (91)   2018-09-26 20:20:00
任何東西無限上綱跟把它當萬靈丹,都是有問題的
作者: senjor (哞哞)   2018-09-26 20:20:00
但是回頭來說,程式也是人寫的,既然都知道有特例,幹嘛不
作者: Killercat (殺人貓™)   2018-09-26 20:20:00
我是覺得 碰到mock困難 該做的應該是提出案例討論 而非
作者: landlord (91)   2018-09-26 20:21:00
為了單元測試而多墊很多不必要的中間層,那是菜鳥錯誤
作者: Killercat (殺人貓™)   2018-09-26 20:21:00
應該說 除非語言很奇耙 不然其實現有套件來講 應該很多都不需要你墊這些中間層只為了能測...或者中間夾了層打不爛的巨大黑箱 不然其實特例討論即可
作者: landlord (91)   2018-09-26 20:23:00
大部分測試案例難加,難維護,維護成本高,都是設計太爛而要解決的問題是「設計太爛」,而不是「不寫測試」
作者: accessdenied (存取違規)   2018-09-26 20:24:00
我沒有要全盤否定喔。但對堅持一定要的人,我覺得是可以多想想的
作者: Killercat (殺人貓™)   2018-09-26 20:26:00
我倒覺得思考能不能做到的可能性很重要 不過的確,總會碰到一些窒礙難行的時候,我是覺得就討論看看說真的以我的經驗 這種case不是很多
作者: x000032001 (版廢了該走了)   2018-09-26 20:29:00
不知道貴公司一天下git blame的次數有沒有上千次
作者: sharku (明珠求瑕)   2018-09-26 20:30:00
Mock技術決定一切
作者: landlord (91)   2018-09-26 20:32:00
如果模擬now寫成那樣子,我贊成你,我也希望他不要寫。只是在製造債,把簡單代碼搞得更複雜而已。
作者: Killercat (殺人貓™)   2018-09-26 20:34:00
文雅點 我們都叫他annotate而不是blame XD
作者: accessdenied (存取違規)   2018-09-26 20:49:00
喔!91大週六有課程喔?工程師該去的都去喔,不要再寫拿著那噁心的DI code了
作者: Killercat (殺人貓™)   2018-09-26 20:50:00
DI都是有原因有目的才DI 不是DI噁心 是亂DI才噁心...
作者: accessdenied (存取違規)   2018-09-26 20:52:00
也是啦,刀子殺人不是刀子的錯,是用刀的人
作者: KanzakiHAria (神崎・H・アリア)   2018-09-26 22:15:00
大師先推再說
作者: viper9709 (阿達)   2018-09-27 00:45:00
原來是這樣
作者: superpai (超級白)   2018-09-27 09:08:00
你不會寫 pure function嗎?
作者: Ghamu (貓丸)   2018-09-28 00:34:00
好棒

Links booklink

Contact Us: admin [ a t ] ucptt.com