Re: [心得] (轉)軟體開發六年後我改變想法的事情

軟工

34330

這篇滿有意思的,牽涉的主題很廣,不過有些事情只有一句很難講清楚

針對中間幾點,分享一些我自己的理解

: 看到不錯的文章 翻譯分享一下
: 原文:
: https://chriskiehl.com/article/thoughts-after-6-years
: 翻譯:
: 軟體開發六年後我改變想法的事情:
: - 如果你的隊友經驗參差不齊,Typed languages 是比較好的選擇

Typed languages 相對容易做程式碼 static analysis,在還沒跑起來前

就容易找到錯誤,一些常見的錯誤甚至有工具可以自動修正,對正確性有幫助

另外在文件不足的狀況下,有時候知道參數和 return value 的類別,會比較容易

看出 method 的正確使用方法。

: - Standups 會議以注意新人來說是有用的
: - Sprint retrospectives 如果拿來做真正的流程修正(course correction)是有用的;
: 而不是一些敏捷/scum master 拿來浪費大家時間的
應該說 retrospective 本來的目的,就是用來檢討要如何做得更好。

不只是流程,有時後會發生交付的東西,和一開始要求的有落差,就需要釐清

團隊的合作是哪個環節發生了問題,或是一開始的 user story 可能根本就弄錯了

如果不能針對改進有建設性的討論,只是流於形式,為開會而開會,確實浪費時間。

: - 軟體架構比啥都重要。有好的抽象再爛的實作都不太會弄髒 code base;爛抽象或
: missing layer 可以讓 code base 變成一坨屎。

所以在 refactor 或是幫 non-testable legacy code 導入新的測試的時候,

一個有用的策略,就是先添加 abstraction layer 再開始 (Refactor by Abstraction)

新增 abstraction 之後本來高度耦合的 code 就比較容易解開,變得好測試

: - java 沒那麼爛
: - Clever code 通常不是什麼好 code;清晰好讀(Clarity)的 code 最重要

一般 code 只會被寫一次,但是後續會被接手的不同人讀很多次,所以好讀是必要的

除非 profiling 確認是效能瓶頸,才會用特別的寫法去加速,否則可讀性比較重要

如果一個 function 不是會執行很多次的熱點,選效率差一點但好讀很多的寫法

對整體效能並不會有影響,不需要過早最佳化。

: - 爛 code 可以被以任何方式寫出來 (in any paradigm)
: - 所謂的 best practices 是要看上下文,並非通用解。盲目追求會讓你看起來像白癡
: - 在你不需要時硬去設計一個 scalable system,你就是爛工程師

這句話乍看比較武斷一些,舉個具體的例子,假設產品還在早期 proof of concept

階段,商業模式都不確定,也還沒跟潛在客戶驗證好可行性,這時候趕快做出來

趕快驗證點子,如果不行趕快換方向才是最重要的。在這種階段有很高的機率

幾個月後這個專案(甚至公司)就不見了,好的工程師能夠針對不同情況

手上有多少資源,做出最適合當下狀況的設計。

例如 monolith first:
https://martinfowler.com/bliki/MonolithFirst.html


太早為了 scalability 拆分大量不成熟的微服務,反而會有害之後的發展。

: - Static analysis 有用
: - DRY(dont repeat yourself) 是為了避免特定問題,並不是最終追求目標。

一般不喜歡 code duplication,重複的東西會盡量抽出來成 module / class /function

但有種情況例外,就是 unit test,test 的重點要一眼看得出在測什麼,

如果抽出太多細節,反而要一直跳來跳去 trace 還看不出在測什麼,這時候還不如

把重要的細節在每個 test case 都重複一次,讓他一目了然 (DAMP principle)

補充:
https://enterprisecraftsmanship.com/posts/dry-damp-unit-tests/


: - 一般來說 RDBMS > NoSql
: - Functional programming 是另一個工具,不是萬用解/靈丹
: 一路走來堅持的觀念
: - YAGNI, SOLID, DRY 請按造這個順序
: - YAGNI:You aren't gonna need it
: - SOLID: 某個 OO 原則(單一功能、開閉原則、里氏替換、介面隔離、依賴反轉)
: - DRY: dont repeat yourself
: - 紙筆是最好的開發工具但很少人用

在一開始最前面的設計階段,用紙筆畫系統架構,或是假想的 UI,確實很方便!

: - 用乾淨/可讀(purity)為代價換取實用性是個好方法
: - 狂導入額外的技術不是好方向
: - 直接跟客戶/需求端理解需求會比較快又精確
: - "scalable"這個詞在碼農中有股神秘的力量,僅僅這個字可以讓他們陷入瘋狂,然後僅
: 僅為了這個字可以做出瘋狂的設計
: 有點難翻XD 原文:
: The word "scalable" has a mystical and stupefying power
: over the mind of the software engineer.
: Its mere utterance can whip them into a depraved frenzy.
: Grim actions have been justified using this word.
: - 雖然叫工程師,但其實很多決策都是跟風(cargo-cult),並不是有嚴謹的分析、資料數
: 據佐證
: - 大概九成的 PM 明天消失對你都沒影響,甚至效率還會變好
: - 當我做了一百場面試後: 面試方法徹底崩壞,我也不知道怎麼做更好
: 沒變的觀念
: - 會刁 code style, linting rules 或枝微末節的都怪咖
: - Code coverage 跟 code 品質完全沒差

這樣講是比較誇大,test coverage 高品質未必好,但是過低品質確實需要擔心

重點不是 coverage 有多少 %,而是你測試了什麼 scenarios,是不是有包含到

最重要的功能,是不是連 error handling 都有測試到,這會比較重要。

要偽造很高的 coverage 數字很簡單,把一大堆 code 包在一包讓他全跑,然後

assertion 的時候檢查一個超寬鬆的條件,這樣看起來就會 coverage 100% 了

所以重點確實不是 coverage 多高,而是你測了什麼

: - Monoliths (大概指微服務的反面)系統在大部分情境都是很好的

推薦參考 monolith first:
https://martinfowler.com/bliki/MonolithFirst.html


如果有好的 abstraction,都是照 SOLID principle 開發的話,就算是 monolithic

日後需要拆分服務是不至於太難拆,問題就是不良的架構跟寫 code 習慣,

把東西全部黏在一包,光一個 class 的功能就拆不開了,更不要說拆服務了

: - TDD 主義者(purists)是最糟糕的存在,他們的腦不能理解現實中存在不同的 workflows

TDD 雖然被很多人批評,但我自己使用的感覺他也有很方便的時候

舉例來說如果你原本就有 test case,你想要稍微調整現有 class 的行為

那先針對預期行為的改變去調整 test case。或是新增對應的 test case 這是很直覺的

例如你要實做一個新的 RESTful API,input / output 都訂好很清楚,這時候先寫

test case 完全沒問題,而且很直覺也方便。

反之如果你對於 class 該怎麼拆分,或是一些細部的設計還沒想好的時候

強迫要先寫 test 這個就真比較違反一般人的直覺,執行上很困難

我們不一定要信 TDD,但可以擷取他們的優點,有兩點我覺得很重要:

1. 透過先寫 Test 你可以「試用」你設計的 API,早期發現 API 設計缺陷

這比都實做完了才發現 API 超難用才要修正要好很多,這個想法很有價值

2. 一定要先跑 test 確認在還沒實做的時候,test case 真的會 fail

我自己被這個救過幾次。舉例來說有些 test framework 會找 function 名字有

test 開頭的來跑,有一次我打錯名字成 tset,導致這個 test 根本沒測到

就很開心的 pass 了,殊不知那段 code 是有問題的,卻根本沒測到

或是設計的 test case 是有問題的,出錯根本不會 fail...

TDD 可以非常有效的預防這種狀況,而且這種狀況是真的會發生。

以上延伸原文,分享一些個人淺見,希望有幫助,歡迎各位先進不吝指正補充

--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.231.158.38 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1630510002.A.6C3.html
jasonwung1樓 09/01 23:39
CKNTUErnie2樓 09/02 00:30
alihue3樓 09/02 00:59
Inglenook4樓 09/02 03:24
joney6411195樓 09/02 05:15
freeunixer6樓有神快拜~~ 09/02 05:17
art17樓寫測試好難,像是演算法的測試到底該怎麼寫呢?要怎麼樣寫測 09/02 05:31
art18樓試才能驅動出特定演算法呢? 09/02 05:31
taipoo9樓謝謝分享 09/02 05:49
potatososo10樓 09/02 08:35
chchwy11樓演算法才是最好測的吧 固定輸入就固定輸出 09/02 08:44
brianhsu12樓演算法就像寫 online judge 的側資一樣啊,先某個你已經 09/02 09:47
brianhsu13樓知道的直覺的輸入輸出,然後再慢慢加上各種邊界側資。un 09/02 09:47
brianhsu14樓it test 不是要你針對每一個 private method 或 functio 09/02 09:47
brianhsu15樓n 都一定要單獨測,你也可以把一個完整的演算發當成一個 09/02 09:47
brianhsu16樓「單元」。 09/02 09:47
lemontea032817樓推~ 09/02 10:22
vi00024618樓 09/02 10:32
freedls19樓有神先拜 09/02 10:50
frank98361220樓 09/02 10:51
ACRRBYEK21樓推 務實 09/02 11:16
wulouise22樓不懂tdd的問題在哪邊?為什麼這麼多人反觀 09/02 12:47
wulouise23樓*反感 09/02 12:47
fantasychese24樓 09/02 12:57
EPGo25樓 09/02 13:36
bewitchsky26樓 09/02 14:12
tbpfs27樓PCman的作者發文底下一堆有神快拜,子午播放器的作者發文 09/02 14:15
tbpfs28樓被後輩下指導棋,進對公司真的很重要 09/02 14:15
OSDBNetwork29樓推 PCman 09/02 14:35
jobintan30樓給推先,進到錯的公司就要趕快找機會跳,跳到對的公司。 09/02 15:19