Re: [討論] 前人的code 後人翻寫的機率高嗎?
單元測試有時候反而破壞程式碼的易讀性和維護性
因為要做到單元測試,就得斷開所有的相依性
而對抗相依性,作法就是引入 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
: 這些都是規定好寫在專案文件裡面的 (以前沒有的文件,現在開始留下記錄)
: 接著就是重頭戲的部分 --- 跟人有關的
: coding style 怎麼統一? 就算統一了還是會有漏網之魚
: 不小心看到 violation 還是會白眼翻到尾椎
: 所以這邊必須用自動化工具檢查,綁在 CI 流程裡
: 這樣已經可以省掉很多人工的部分
: 接著定期 code review,挑出變數不懂、「比較不易修改」的類別… 等等
: 這樣至少做到了幾件事情
: 1. 以前沒有的,現在開始留下記錄
: 2. 把 legacy code 加上 test
: 3. 把系統改成 API server 從視圖抽離後,再動前端 (refactor 分階段)
: 4. 統一 coding style
: 5. 符合 SOLID、易於修改的架構 (為了以後著想)
: 當然前面幾篇貼文,有些前輩也有提到
: 「有人的地方就有政治」
: 這句話應該劃 _底線_ 三顆星 ★★★
: 這之中太多阻礙了,電腦不會背叛你,人會 XDD
: 做了這麼多品質保證措施,一定會遇到成員反對
: 「一個變數而已,幹麻花這麼久時間討論?」
: 「我覺得 code review 花太多時間」
: 「我覺得一個東西,幹麻拆這麼多類別,放在一個不就好?」
: 深入探討提出這些問題的同事心態,不外乎幾個原因
: 1. 影響 issue solving 時間 --> 覺得產出變慢
: 2. 覺得寫單元測試很麻煩 --> 覺得程式會動就好
: 3. 覺得一個類別不用提煉為抽象+實作 --> 現在又沒這麼多需求 幹麻拆?
: 但他們忘記事實是,程式本來就是會修修改改的,而且也是會給別人改的
: 這讓我想到一句話
: 「
: 據統計,你現在挖的坑,有80%會自己來擦屁股
: -- 不知道是誰 」
: 即便跟他們說品質是什麼,clean code 的重要性,他們還是覺得『不需要』
: 所以大多數的問題,都是「人」造成的
: stop writing legacy code,從你我開始
: 但如果你身邊沒人支持,更進一步的說: 沒有得到老闆/主管支持
: 這公司也差不多 GG (因為不在意品質)
: 如果你是 team 的其中一個人,試著先從統一 coding style 開始
: 我在 Modern Web 2018 聽到有一場 keynote 是 Terry Yin 大神的「遺留代碼經濟學
」
: 裡面有提到,其實也不用這麼討厭 legacy code
: 因為有那些東西,我們工程師才得以被養活。
: 如果你發現有 code 裡面處處是坑,怎麼辦? 那就別再挖坑了啊!!
: 我們現在做的,只是把以前沒做的都補回來而已
: 但是,不要再欠下更多的技術債
: 債總有一天還是要還的,而且還會生利息
: 最後我要說一句
: 很多前輩們會建議,要重構前先寫測試
: 但是
: 一個萬能類別/萬能方法/高耦合,要寫單元測試,發現整個系統都要寫
: 有些 hard code 的 class 還不見得可以 mock
: 「人」的問題
: 無解。
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 220.135.20.48
※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1537962940.A.A36.html
→
09/26 20:10,
7年前
, 1F
09/26 20:10, 1F
→
09/26 20:11,
7年前
, 2F
09/26 20:11, 2F
→
09/26 20:11,
7年前
, 3F
09/26 20:11, 3F
→
09/26 20:12,
7年前
, 4F
09/26 20:12, 4F
→
09/26 20:13,
7年前
, 5F
09/26 20:13, 5F
→
09/26 20:15,
7年前
, 6F
09/26 20:15, 6F
→
09/26 20:15,
7年前
, 7F
09/26 20:15, 7F
→
09/26 20:15,
7年前
, 8F
09/26 20:15, 8F
→
09/26 20:16,
7年前
, 9F
09/26 20:16, 9F
→
09/26 20:17,
7年前
, 10F
09/26 20:17, 10F
→
09/26 20:17,
7年前
, 11F
09/26 20:17, 11F
→
09/26 20:17,
7年前
, 12F
09/26 20:17, 12F
→
09/26 20:18,
7年前
, 13F
09/26 20:18, 13F
→
09/26 20:18,
7年前
, 14F
09/26 20:18, 14F
→
09/26 20:18,
7年前
, 15F
09/26 20:18, 15F
→
09/26 20:18,
7年前
, 16F
09/26 20:18, 16F
→
09/26 20:19,
7年前
, 17F
09/26 20:19, 17F
→
09/26 20:19,
7年前
, 18F
09/26 20:19, 18F
→
09/26 20:19,
7年前
, 19F
09/26 20:19, 19F
→
09/26 20:20,
7年前
, 20F
09/26 20:20, 20F
→
09/26 20:20,
7年前
, 21F
09/26 20:20, 21F
→
09/26 20:20,
7年前
, 22F
09/26 20:20, 22F
→
09/26 20:20,
7年前
, 23F
09/26 20:20, 23F
→
09/26 20:20,
7年前
, 24F
09/26 20:20, 24F
→
09/26 20:20,
7年前
, 25F
09/26 20:20, 25F
→
09/26 20:21,
7年前
, 26F
09/26 20:21, 26F
→
09/26 20:21,
7年前
, 27F
09/26 20:21, 27F
→
09/26 20:22,
7年前
, 28F
09/26 20:22, 28F
→
09/26 20:22,
7年前
, 29F
09/26 20:22, 29F
→
09/26 20:23,
7年前
, 30F
09/26 20:23, 30F
→
09/26 20:24,
7年前
, 31F
09/26 20:24, 31F
→
09/26 20:24,
7年前
, 32F
09/26 20:24, 32F
→
09/26 20:24,
7年前
, 33F
09/26 20:24, 33F
→
09/26 20:26,
7年前
, 34F
09/26 20:26, 34F
→
09/26 20:26,
7年前
, 35F
09/26 20:26, 35F
→
09/26 20:27,
7年前
, 36F
09/26 20:27, 36F
→
09/26 20:29,
7年前
, 37F
09/26 20:29, 37F
→
09/26 20:30,
7年前
, 38F
09/26 20:30, 38F
→
09/26 20:32,
7年前
, 39F
09/26 20:32, 39F
→
09/26 20:32,
7年前
, 40F
09/26 20:32, 40F
→
09/26 20:34,
7年前
, 41F
09/26 20:34, 41F
→
09/26 20:49,
7年前
, 42F
09/26 20:49, 42F
→
09/26 20:49,
7年前
, 43F
09/26 20:49, 43F
→
09/26 20:50,
7年前
, 44F
09/26 20:50, 44F
→
09/26 20:52,
7年前
, 45F
09/26 20:52, 45F
噓
09/26 22:15,
7年前
, 46F
09/26 22:15, 46F
→
09/27 00:45,
7年前
, 47F
09/27 00:45, 47F
推
09/27 09:08,
7年前
, 48F
09/27 09:08, 48F
噓
09/28 00:34,
7年前
, 49F
09/28 00:34, 49F
討論串 (同標題文章)