--- title: '軟體工程師' disqus: Notes tags: Podcast --- # 軟體工程工作日常 ###### tags: `自學計劃` `學習資源` [TOC] ![](https://i.imgur.com/TLu16Vc.png) # 心法 * 持續學習是剛性要求 * 職業遍佈全行業 * 工程師特色 * 非常簡單的人 * 喜歡偷懶的人 * 嚴謹 持續改善 追求極致 * 熱衷於創新 * 一個成就感驅動的職業 * 35歲門檻 * 創始人 * 為公司帶來資源,吸引人才,帶來經濟與社會效益 * 帶動團隊,能夠自驅位公司和團隊制定方向與實施計畫,解決問題,推動計畫落地 * 創新優化 現有東西提出小而美的創新和優化 並推動執行 * 前瞻能力 行應變化 技術潮流 思考行業與公司未來 做好準備 * 抓重點:簡化 標準化 = 規模化 平台話 * 貢獻者 * 中層 做事熱情 推動工作進展 * 探路能力: 只要方向沒問題 沒有路也能探出路來 * 貢獻方法: 在實行中提出更好 更簡單的方法與創意 * 解決難題: 方法總比問題多 帶團隊解決一切問題 * 提高標準: 能夠不斷發現不足 隬補不足 解決問題 提高標準 * 行家 Expert 對做的事情很有經驗 能正確判斷與決策 * 降低成本 時間 金錢 人力 物力 * 提高效率 * 防火能力 * 按部就班做事的人 要避免成為這樣的人 # 四大台階 1. 新手 - 明確執行上級交付任務 - 必學入門語言:Python, JavaScript - 正式入門語言:Java - 工具:Git, VSCode IDE,英文 3. 進階 - 給問題 -> 方案 - 一個問題 需要把具體問題 抽象 拆解 獨立設計解決方案 5. 高手 30% - 架構師 (系統, 外部, 內部 技術 多維度綜合考量) 7. 大神 1% - 權威 你的東西 可以解決另外的問題 創新領域 * 去一家技術驅動的公司 * 公司要做的事情是否是技術未來趨勢 * 優先選擇在未來航道上那些快速發展的公司 * 技術文化為主導的公司 * 找到自己適合的路線 * 特長,興趣,方法,勤奮 # 開發流程 ## 規範 我的代碼 你能改 工作效率才會高 協同沒有障礙 一個公司不斷提升標準 才能做出更好的東西 與用戶體驗 更強競爭力 ### 編碼規範 推薦書 * Code Complete * 重構 改善既有代碼設計 * 程式員修煉之道 * 命名規則 * 副檔名 * 單元測試 * 即使沒有規範也得自我要求... 設計規範 ( API 接口設計規範最為關鍵 ) 生產規範 CI/CD, DevOps, 人月神話,持續交付發布可靠的軟件的系統方法 自動化 高度水平擴展的基礎 **優化代碼: 好代碼沒有止境** 初級:可讀 中級:可擴展 高級:可重用 方法: 1. 設計模式 2. 函數編成 3. DSL 4. 狀態機 5. 插件 **好理解的代碼** * 乾淨的接口 * 方便使用者的 使用者想到的問題你都預先想到了 * 有註解與文檔都講清楚 就不會太差 **註解** * 描述用途 * 如何使用 * 範例 **編碼原則** * 避免再造輪子 * 單一職責 - 把複雜問題簡單化 模塊化 降低問題的複雜度 不斷覆用 * 高內聚 低耦合 * 開閉原則 - 內部行為 封閉 互不依賴 但可擴展 * 重點是要解決什麼問題 * KISS - Keep It Simple, Stupid ## 拆分任務 ### 原則 * 接到任務後,先做任務分解,把大任務拆成小任務 * 可以幫你理清問題的思路 * 簡化問題的複雜度 ### 技巧 1. 抓重點, 去掉部必要的 留下必須要做的 找到任務骨幹 2. 按照單一職責原則對任務進行拆解, 列出功能 3. 每個功能對應小程序或模塊 最後拼裝起來 ## 讀代碼 什麼是好代碼 1. 被反覆使用的代碼 2. 穿越時間的代碼 - 10, 15年都沒被淘汰 3. 好呼叫調用的代碼 ### 好代碼的特點 * 清晰,明確,易用,自帶使用說明 * 非常高效 * 通用性很高,可擴展 * 自帶風格 代碼與說明文檔的差異 * 代碼:What, How, Detail * 文檔:What, How, Why 快速提升能力途徑 * 跟著高手牛人一起解題 * 和優秀的人一起工作 * 軟體工程師是一群特別愛分享的人, 所以只要你想學, 總能找到提升自己的路徑 # 進階篇 不再只是執行,而是要更多發會**創造性,獨立設計和優化**,在團隊裡不再止於埋首於完成自己的事情,而是要做好一個項目從**頭到尾的把控**,**協調內外部的合作關係**; 在學習上不再止於跟別人學,而是**內項精進,搭建起自己的知識體系** 需要能力 * 獨立設計 * 設計規劃 * 實現需求 ## 需求分析 * **避免 X-Y問題**:要真正確定真正要解決的問題是什麼,不要單方面只解決技術問題 通病 沒搞清楚問題核心以為此技術可以解決 弄錯了重點 * **明確模糊不清的問題** * **設定邊界條件**:金額大一點?多大?數值? * **關注不可預期性**:太多時間花在可預期的事情上 忽略忘了處理例外狀況 **學會謀篇佈局:** 需求-> 程序實現 -> 模塊拆解 -> 組合搭配 -> 思考總結 -> 獨立思考 -> 科學的解決方案 ## 規劃程式架構 * 圍繞著**要解的的核心問題展開** * **架構大小依照要解決的問題要恰當** * **設計需要抽象的能力** * **過程抽象**:把問題拆解成一個個 API * **數據抽象** ## 原型設計 PM 依照用戶面向設計打樣 沒有代碼 只是一個簡單的演示 讓一些模糊的問題變清楚 * 從**最難解決的問題做起** 及早發現問題 節省開發時間 評估 解決 * 當下如果**技術難以突破** 解決 整個項目**建議往後放** 不必繼續浪費時間 * 重點是**好的 API 接口的設計** **前後多想幾步** ## 架構設計 面向開發人員 **施工藍圖** **抽象和分解** **流程圖** **模塊組成** 之間的**邏輯關係** * **分而治之** 把任務拆分個模組 * **高內聚** * **低耦合** * 考慮**異常與極限情況** * 斷線 斷電 等 * **最大乘載能力** ## 技術調研 尋找最優解決方案 和讀代碼的能力也有正相關 分析優缺點,結合場景才有效(問題本身) # 項目管裡 ## 開發模式 1. 瀑布式 2. 敏捷式 3. 班車式 - 避免延期 驗證效果 - A/B test 用數據說話 ## 上線 做好監控(閉環 test case - env - monitor - bug - fix)與 壓測(承受10被以上的壓力) ## 團隊合作 ### 外部溝通 * 告訴業務,不要把技術當作需求解決方 這樣只會得到被動的技術團隊 * 要把技術當作解決問題的參與方, 技術的主觀動能就會被調動起來 * 不要把需求直接丟給技術,而是要告訴技術團隊真正想要解決的核心問題是什麼? * 我們面臨的所有問題都不只是單純的技術問題,大家一起努力,才能從根本上解決問題 滿足客戶的需求 * 只有技術知道如何與業務溝通,才能把需求實現好 ### 內部溝通 (前, 中, 後台) 平衡雙方的想法與痛點 前台是 1 中後台 團隊就是後面的 0 要圍繞著 1 去建設 去創造價值 去解決前台的需求與通點, 前台提供有價值的服務 取的平衡 ## 學習 打牢基礎,以不變應萬變 提升內功修養,解耦,提升代碼重用度 基礎是抽象和歸納 形成進一步的推論 抓住原理 舉一反三 1. 程式語言 基本語法 函式庫 編成(同步 異步), 編程規範, 設計模式 2. 系統原理: 計算機系統 操作系統 網路協議 數據庫原理 3. 中間件:消息陣列 緩衝系統 網關代理 調度系統 4. 理論知識:算法和數據庫 數據酷範式 網路七層 分佈式系統 搭建系統 - 知識數系統學習 * 用好知識樹:有系統地學習 * 探索知識緣由:知道為什麼 不要硬背 * 掌握方法與套路:學習不是為了找答案,而是為了找到方法 主動學習 提高你的學習效率 # 高手修養 * 需要有融會貫通的能力 - 做技術決策不只要解決當下問題 還要思考後幾年會發生的事 未來發展方向的預判 * 對現有系統重新佈局 - 清楚自己做什麼 不做什麼 解決什麼問題 不解決什麼問題 * 要在一個複雜系統裡做預判與取捨 做不好這些 難以成為高手 ## 技術職或管理職? 技術:特定的技術領域作深入的探討與研究 不涉及管理的工作 管理:側重統籌團隊完成一個個研發項目 離技術研究工作比較遠 ## 高手 架構師 - 前瞻能力:現在這樣 以及未來會朝什麼樣的方向演進 要看到未來趨勢 對未來預判 做技術選型 - 要有知識的廣度 多交流 - 跨行業的交流 - 取捨能力 - 明確目標: A, B, C 方案 選擇最適合目標 系統簡單 可控充 - 學會預測 哪個方案更優 - ### 主要工作 - **攻克難題** :技術難題要自己去找 提升自己 - 1. 整個行業公司發展方向 - 2. 跟目前工作相關 需要繼續學習的領域 沒有通用的解決方法 保持一個好心態 要有戰勝困難的信心 也要有接受失敗的準備 - 3. 嘗試不同方案 想方設法嘗試不同方案是最重要的 - **技術決策** - 這項技術是否要解決大問題 - 是否有想像空間 - 大公司撐腰 - 好的技術社群 - 殺手級應用 - 歷經十年以上 - 代碼評審 - 可讀性 - 維護性 - 知識共享目的 - 做出來 vs 做漂亮 - 幫助團隊賦能 - 不是為了找 bug 挑毛病 - 為了 可讀性 可維護性 可重用性 程序邏輯對應需求及設計 - 不要等做完 才做 code review 如何做 - 設計 是否精心設計適合系統 - 功能 是否符合開發者意圖 - 複雜 是否可以更簡潔 其他開發人員好接手 理解 - 測試 是否經過正確設計良好自動化測試 - 命名 變數 類別 方法 名命原則 - 註解 清晰有效 - 風格 遵循 谷歌代碼風格 - 文檔 是否同步更新文檔 ## 帶團隊心法 1. 業務上給下屬指導 2. 拆解任務 組織團隊完成目標 3. 日常管理工作 實力服眾 - 工程師寧願被 lead不願被 manage 技術得足夠牛 要按耐住 克服和適應 要做好思想轉變 :之前想的都是讓自己變得更好 現在你要做的是怎樣讓其他人更好 怎樣讓圖隊更好 善於說服 - 相對於下命令 還是要講道理 面試 可查一個人的能力 基本素質與能力 系統設計 代碼結構化 找關鍵問題 拆解 設計 員工激勵 讓工程師有成就感 做好人才佈局 關注長期目標 哪些事情值得長期投入 做了之後可以產生規模化效應 平衡需䲡: 判斷緊急與重要 做出平衡 協同機制:保持公開透明的信息協同 鼓勵大家把自己做的東西工具化 開源化 讓所有人都能看到和使用就很重要 團隊合作:一加一大於二 合作共贏:找到利益共同點 有目標地推進 合作就會順暢很多 # 行業大神 ## 丹尼斯,李奇 C語言之父 保持簡潔 ## 林納斯 托瓦茲 Linux 之父 只是為了好玩 開源 ## 及多 范羅 Python 允許不完美 保持開放 # 測試 做測試比寫程式還要難得多,因為做測試考驗的是一個人全面思考的能力 建議 1. 做測試最好的方式不是用人工,而是寫代碼 2. 想做好測試, 先訓練自己全面思考的能力 * 單元測試 - 白盒測試 * 確認所有零件模組是否都正常 * 離問題最近的地方 * 功能測試 - 黑盒測試 * 模塊組合在一起後,確保功能都正常 * 不關心具體怎麼實現, 把軟件當成一個黑盒來進行測試 * 整合測試 * 和周遭環境 系統上運行測試 * 維運 測試 * 非功能測試 * 性能,安全,穩定,破壞,容錯,可用,靈活性測試 * 回歸測試 * 以前做過的測試或犯過的錯再測試一次 軟體工程師對於測試幾個重要觀念 1. 測試要自己做, 不能讓用戶成為你的測試工程師 2. 除了測試基本輸入以外,還要努力構想更多的邊界條件 3. 測試接口定義的程式語意,而不是當前實現的具體行為 * API 注重是 what, 實現注重的是 how 是細節 * input -> output 才能確定與預期,中間過程怎麼實現非此測試的重點 5. 對於重要模塊,編寫的時候就要做到基本性能測試 6. 對於交付以後出現的問題與bug,要構建相對應的測試程序並提交代碼,保證以後回歸測試可以自動運行此項測試 ## Bug - 很多公司,新人進來做的第一件事,就是修 Bug - 考驗新人的分析思考能力 - 很可能改錯一個 Bug 導致更大的問題 - 像偵探一樣發現問題 - 好 Bug: 容易覆現的問題,只有局部邏輯錯誤 - 壞 Bug: 難覆現, 不知道問題核心 - 多線程, 並行程序, 隨機算法, 分布式 - ### 定位 Bug - 模擬 Bug 場景 - 二分法 - 檢驗工具 - 極限測試 - 小黃鴨調適法(找個聽眾 梳理程式邏輯與流程) - 做推論,立假設,做實驗,排除 ### 修復 - 梳理整體設計 - 理解代碼 - 保證你的修改不會影響到其他部分 ### 重構: 1. 看整體:最終運行的情況 2. 改細節:不只改Bug還可優化結構 讓代碼更易於理解 更安全 3. Review: 提交前找其他人一起 review 是否完善 是否有其他建議 解決問題後:要吸取經驗教訓, 將來不再類似的問題上犯錯 養成好的習慣(例如:初始值) ## 簡單並不簡單 有時候有人會說 系統太簡單 覺得一個系統要有多華麗才是好系統,應該沒有遭遇過複雜代來的辛酸, 有些人從來沒有接觸過什麼龐大的系統,設計的東西使用者也不多,當然不知道簡單就是美,也不知道設計的第一個原則就是 KISS ( Keep It Simple and Stupid ) 能夠大規模運作的系統,使用者方便上線,才是王道 很多系統的資料庫、不同軟硬體作業介面、加上網路錯綜複雜的關係,實際上相當複雜。 介面清楚方便,使用者進入的門檻低,是相當重要的關鍵。 尤其在大規模施行的時候,正常運作,沒有什麼重大問題,這是非常重要的關鍵 簡單才是最重要的特點,看起來簡單,其實一點也不簡單,能夠用100行寫完的程式,千萬不要寫成101行,執行的程序和步驟也是同樣的道理。 借力使力不費力,讓舊生意有新方法