---
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行,執行的程序和步驟也是同樣的道理。
借力使力不費力,讓舊生意有新方法