跳到主要內容

184開發感想

這篇其實開發到一半就想寫了,這次開發真是累翻了,沒有加班的天數居然屈指可數,當覺得超前了,經過一連串測試修正後,進度反而落後了,然後又開始加班了。這次unit test根本沒有作完,總覺得這次bug數一定會破表,雖然在沒有已知的bug的情況下進入了α階段,但是就像考試時,沒有做完完整的的檢查一樣的令人不安,而且實際開發時程與實踐開發衡量方式與預估有很大的不同。回頭來看看,到底為什麼會發生這樣的狀況。

1. 開發時程預估差距過大:

差距最大的還是走勢圖,基本上個股和指數的寫法幾乎完全不同,指數走勢圖所花的時間是個股走勢圖兩到三倍的時間。原本估計的時間是個股和指數一起寫完,原本認為個股寫出來指數也會很快的就完成,所以開發整個走勢圖預估的時間大概是個股走勢圖完成的時間乘以1.5倍,但實際上完成的時間卻幾乎是3倍,也就是說多花了一倍以上的時間,為了趕上進度,就只有不停的加班了。另外一個差距比較大的地方是排行表設定的部份,原本預估的時候,我的想法是盡量不更動原本紀錄架構,只是把UI調整到位,但是看了技術分析的版本的時候,我發現依原本的架構,是沒有辦法達到像技術分析一樣的效果,尤其如果未來在加上更多商品分類,得花更大的功夫開發。只好狠下心把整個架構翻掉,這樣開發的內容超乎我估計,當然又是一次加班的開始。其實我不爽的是我覺得這是很沒有價值的調整,在我精疲力盡之時,又要再加班,這股火氣幾乎另我喪失理智。

2. 港股資料源問題:

在開發走勢圖初期,因為沒有港股資料,開發的方法完全只有自己模擬資料,或依據bk舊的介面實做。但是等到有資料源後開始測試時,又得開始調整。有種事倍功半的感覺,因為每次link test都把之前寫的方法推翻掉,所以每個階段的link test比預估來的還要長,這也是進度不停落後的原因之一。

3. WBS與單元測試進度無法配合:

原本預計的開發流程是當每個WBS完成,應當依據測試計畫測試該WBS應當作的測試案例,但是資料源未完成時,有許多案例無法測試,因此只好進入下個WBS,如此而來原本unit test要與開發實際互相結合的方式便無法實現,結果變成把所有測試丟到後面來作。當開發時間已經不足了,單元測試自然也無法完成了。

4. 以完成日來決定開發時程:

這次時程的安排似乎受到的在某個特定日之前一定要完成的暗示來排定時程,這似乎是我在『在公牛上擠牛奶』這本專案管理書上看到不好的案例,雖然書上講的案例是接案人員,為了搶案胡亂開定時程與功能範圍,而當時程與功能無法配合時,專案自然就會失敗。當我們認定一定要在某日之前就開發完成,當排定的時程超過時,得自動縮減各個開發時程。但是縮減時程,就得面對開發品質不佳的風險。也很容易造成所謂的奈米完成日,在這日準時完成的機率,只有百萬分之一。

5. 規格書出現未預劃時程的規格:

部分規格在開發末期才發現有此規格,除了規格書標示更動之處不明外,其實我認為這是unit test沒有在開發時一併落實的後果之一。當unit test於開發時便一併進行,便容易看到之前沒有看到的部份,不過規格書一改,就要重新測試一遍,也是很麻煩的。但是要規定規格書不改好像又不可能。

這次的開發與183開發有很大的不同,如果下次有此狀況,我的建議是:

1. 先作與資料源無關的部份:

當資料源也一同並行開發時,我覺得先作與資料源無關的部份,當資料源完成後,再進入此處開發,避免事倍功半。或者資料連結部份先跳過去,等資料源完成再回來開發,但是這樣時程的安排會有一點奇怪,可能相同的部份要先跳過

2. 排定密集的link test:

因為相關的資料源也同步在開發,資料源一修正,我們也必須作相對應的測試與變動,以這次開發看來一個禮拜的開發週期排定一天以上的link test會比較佳,而非原來整個時程僅排定兩次的link test,並且以這次開發來看,最後的link test比想像中來的長。

3. Unit test與link test結合:

其實我一直覺得unit test是衡量進度的一種方法,每個WBS的完成意味著已經通過了此部份的unit test。但是如我前面所提得,如果開發與資料源有緊密的關係的話,此WBS是否完成與資料原有很大的干係,因此以link test的時程為unit test的一個衡量點或許會好一點。

4. 不要預設在某日之前一定要完成來規劃開發時程:

當決定在某日之前一定要完成時,會錯估時程的判斷,依實際要開發的時間來估計吧,不要以如果砍時程,那麼就加班來應付,看起來開發過程中,加班是一定的,如果一開始就決定加班,那可真是災難的開始。

5. 測試與修正時程拉長:

測試與測試後的修改應該包含在時程規劃中,而且依這次看來這段時間還不短。拉長的另一個因素是我們不知道最後規格書會修改多少,通常就算規格書新增或修正功能也還是不能延長時程,因此這段時間也應把這個風險吸納進去。

6. 把企劃拉進來測試:

其實這個想法,上次就提過了,主要的理由是可能他表達的與我們理解的有些差距,在每個階段的測試時把他拉進來看,不是為了測bug,而是確認這是他要的功能,所以他不用作資料正確性的驗證或monkey test,他僅需做的是規格的確認而已。至於QA要不要拉進來,感覺上這是政治的議題,哈哈。他們說沒人力,如果有也只派一個資淺的,那不是一樣嗎,如果在α階段時之前沒有參與測試的QA人員說要改功能,我們能說不討論嗎。如果共同的目標是讓產品有好品質,這自然得討論,如果以他們有人進來測試而沒提出問題來回堵他們,這不是很奇怪嗎。所以我覺得要嗎,進α後規格書都不要改,不然就是QA在開發時就全部進來確認規格與程式功能。不過以上兩點我都覺得不可能達成。所以似乎規格在α期間變動是理所當然的。此外我覺得如果把規格更改的時間也納入我們的α時程,也是件不公平的事,為什麼新加或修正的功能也算在我們頭上呢?所以我覺得如果在α階段有修正或新增功能,而我們又如期進入β,那我們應該算是加分才對啊!

總歸一個原則,把測試含進時程規劃裡,並且不是最後才做而是階段性的作。我所認為的測試,兩個人互測其開發的項目,這樣才會檢查出漏掉的地方,而不是自己單方面的測試。時程預估錯誤,雖然也是進度落後的主因之一,但我覺得是不可避免的,有時候估計的太短,有時候估計的太長,這都是互補的,只是下次預劃時程得更加注意這次預畫錯誤的原因。另外此次雖然WBS不停的修正,但事實上實際所花的時間與修正內容還是有差距,只是不停地想跟上所預畫的進度而不斷的加班。

其實這次開發,學到很多程式的技巧,收穫不少,但是也很累,希望這次的經驗對下次開發有幫助。如果本篇概念有錯的地方請指正,謝謝。

留言

這個網誌中的熱門文章

解決 CI Trust Issue:Target Must Be Enabled Before It Can Be Used

📱 iOS開發 | 🔧 CI/CD | 💻 Xcode | 🐛 除錯筆記 🔴 問題描述 這兩天在跑 CI 時突然出現錯誤訊息: Package@swift-6.0.swift:PACKAGE-TARGET:CasePathsMacros: error: Target 'CasePathsMacros' must be enabled before it can be used 🤔 嘗試過的解法 💬 Claude 的建議 首先詢問了 Claude,得到以下步驟: 先更新 swift-case-paths 到最新版本 確保使用 "Up to Next Major Version" 執行 File → Packages → Reset Package Caches Clean Build Folder (Cmd + Shift + K) 重新 Build 結果: 一看就知道沒用 😅 🤖 ChatGPT 的建議 接著試了 ChatGPT 的解法,主要是降低引用到的 package 版本。繞了一圈,還是沒用。 ✅ 最終解決方案 最後還是回到 Google,找到了真正有效的解法。針對這個 macro fingerprint validation 問題,有三種解決方式: 📌 方法一:本機開發用(Terminal 指令) defaults write com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES 📌 方法二:xcodebuild 參數 在執行 xcodebuild 指令時,加上 -skipMacroValidation 參數 📚 參考連結: https://vocus.cc/article/690779ebfd89780001859b14 📌 方法三:CI 正統做法 ⭐️(推薦) 步驟 1: 在專案根目錄建立資料夾 ci_scripts 步驟 2: 在此資料夾中建立腳本 ci_post_clone.sh ,內容如下: #!/bin/zsh mkdir -p ~/Library/org.swift.swiftpm/security/ cp macros.js...

用 AI Debug 的迷思:當建議越改越糟時

現在許多開發者習慣用 AI 來協助 debug,但在實務上常遇到一種情況: 依照 AI 建議改了兩三輪後,錯誤仍然存在,甚至越改越複雜。 這種狀況其實有幾個常見的盲點,值得特別注意。 1. 先回到「上一個正常版本」 當你已經按照 AI 的方向修了好幾次但問題仍未解決時,最有效的第一步是: 回到上一個正常工作的版本,縮小問題來源。 許多 bug 並不是你正在看的那段程式碼造成的,而可能是: 同事剛好修改了某個底層模組 某個 shared component 產生 side effect Auto Layout 層級重新 layout 時觸發 crash 如果只是盯著眼前的 function 修,反而容易被誤導。 2. AI 沒有看到你的整個專案 AI 通常只能根據你貼出的片段判斷問題,這代表它不知道: 你的 view hierarchy 裡是否有其他 constraint 影響 layout 某些 model 是否被 extension 修改過 父層或子層邏輯是否干擾目前的行為 整個專案採用的 concurrency 模型是什麼 因此,AI 可能會朝著完全錯誤的方向修,導致反覆修改卻無法解決。 3. Swift 6 例子:錯誤真正原因常不在你修改的那一行 例如開發者常遇到的錯誤: passing closure as a 'sending' parameter risks causing data races 許多人(包含 AI)會開始從 function 內部調整,但這類錯誤真正的關鍵通常是: 傳進去的物件沒有實作 Sendable。 也就是說,你不是要改 function,而是要回頭檢查: 傳入的 model / struct / class 裡面是否有 non-Sendable 成員 是否需要標註 @unchecked Sendable 如果 AI 沒看到相關檔案,自然很難找到正確方向。 結語:AI 是工具,不是預言機 AI 很適合用來: 解釋概念 協助產生測試程式 提供重構建議 釐清你已懷疑的方向 但在 debug 狀況下,以下三件事更重要: 回到上一版,縮小差異範圍。 釐清真正問題來...

借助 AI 除錯:解決登出時的解密錯誤

  前言 最近遇到一個有趣的 bug,趁這次機會試試看用 AI 來協助除錯。整個過程蠻有收穫的,分享給大家參考。 問題發現 Bug 描述 在測試登出功能時,發現 app 會發生 crash。追蹤後發現是在登出時,API 會呼叫底層的解密函式,但解密用的 key 明顯有問題,導致解密失敗而引發錯誤。 由於這段流程是另一位同事負責開發的,程式碼邏輯比較複雜,短時間內看不出根本原因。於是先採取防禦性做法: 如果 key 為空值,就將解密失敗的錯誤吃掉不處理 。判斷後認為這樣不會影響 UI 操作,因為登出後 key 會重新取得。測試後確認沒問題,就先把這個 bug 暫時壓下來了。 深入追查 第一回合:初步分析 趁著有空檔,決定詳細釐清這個問題。想試試 AI 的能耐,於是下了第一個 prompt: 分析 SessionManager 的 processEncryptedData 方法中,為何會發生 bytesToTrim > currentLength 的錯誤?從呼叫該方法的地方分析可能發生的原因。 AI 給出了幾個可能的原因: 加密數據損壞或截斷 網路傳輸過程中數據包丟失或損壞 API 回應中的加密字串不完整 解密後的最後一個字節值異常大 錯誤的加密算法或密鑰 使用了錯誤的解密密鑰或 IV Session key 交換失敗,但程式繼續使用無效密鑰解密 解密產生亂碼 Hex 字串轉換錯誤 包含非法字符、長度不是偶數、部分缺失等問題 AES CBC 解密失敗但沒有檢查錯誤 Whitebox 密鑰準備失敗 IV 不匹配 數據長度不符合 AES 塊大小要求 PKCS7 Padding 格式錯誤 加密時使用了錯誤的 padding 方式 最後字節不是有效的 padding 長度值 (1-16) 多重解密處理錯誤 數據被重複解密或解密順序錯誤 記憶體緩衝區問題 緩衝區大小分配錯誤或溢出 AI 也分析了呼叫鏈: API 回應 → DataTransformer → CryptoHandler → decryptSessionKey → processEncryptedData 評估: 這些分析大多是從相關函式內部找錯誤,但沒有太大用處,...