發表文章

目前顯示的是 2025的文章

使用 ADO Coding Agent 套件,在 Pipeline 中讓 AI Agent 自動運行各種任務

圖片
前言 你可能有聽過 GitHub Copilot Coding Agent ,它是一個可以搭配 GitHub Action,在背景自動執行 AI 任務的工具。甫一推出,就讓開發者們眼睛一亮,因為它讓 AI 能夠在 PR 或 CI/CD Pipeline 流程中,自動化地幫助我們完成許多重複性任務。 可惜的是,它目前只能在 GitHub Repo 上使用。 因此,我試著開發了 ADO Coding Agent 套件。 簡單來說,ADO Coding Agent 就像是 GitHub Copilot Coding Agent 的 Azure DevOps 版本 - 它可以在 Azure DevOps Pipeline 中自動執行你給 AI 的提示詞 (背後是 GitHub Copilot CLI),將 AI 的強大能力與 CI/CD 工作流程無縫整合。 我之前也 Demo 過,如何在 Azure Pipeline 中運行 GitHub Copilot CLI,我對這議題一直很有興趣,因為這讓 AI 驅動的自動化開發變成可能。這意味著,我們未來可能不再需要手動執行重複性的程式碼修改工作,而是可以在每次程式碼提交、或 PR 被觸發時,透過 Pipeline 讓 AI 來執行這些自動化工作。 無論是自動化 Code Review、自動生成單元測試、自動撰寫文件、自動修復 Bugs、或是進行程式碼重構,ADO Coding Agent 都能夠在背景完成,並且把結果直接寫回 Repo 中,這已經不只是效率的提升,而是我一直期待的 24h 自動化 AI 開發團隊的逐漸成形。 具體使用方法: 在 Pipeline 中添加 ADO Coding Agent Task (套件安裝位置: https://marketplace.visualstudio.com/items?itemName=tw-developer.ado-coding-agent )。 在 GitHub 站台上申請一個具有 Copilot Requests 權限的 PAT (申請位置: https://github.com/settings/personal-access-tokens/new ),這是因為該 task 主要是在 Pipeline 中調用 GitHub Copilot CLI ...

使用 Managed Identity 讓 WebApp 毋須帳密直接存取 KeyVault

圖片
你有沒有過這種經驗?把資料庫密碼寫在設定檔裡,commit 之後才驚覺「慘了!」然後開始瘋狂 Google「如何從 Git 歷史紀錄中永久刪除檔案」。 或者更糟的是,一時偷懶把 API Key 硬寫在程式碼裡,結果被同事在 Code Review 時抓包,尷尬地說「我只是暫時測試用的啦」(但其實已經在 Production 跑了三個月)。 歡迎來到~密碼管理地獄。😈 然而你可能不知道,Azure 提供了一個叫做 Managed Identity(受控識別) 的機制,可以跟本性的解決這類問題。 Managed Identity 是 Azure AD 中的一種應用身分(Service Principal),它就像是幫你的應用程式辦了一張「雲端身分證」。有了這張身分證,你的 WebApp 可以直接向 Azure 的各種服務(像是 Key Vault、Storage、Database)亮出證件說:「嘿,我是合法的!讓我進去!」 同時完全不需要在程式碼裡寫任何帳號密碼。 😲 這就像是住在有門禁管理的大樓,你不需要每次都掏出鑰匙,因為管理員認識你的臉。系統會自動幫你驗證身份,既方便又安全。 為什麼這麼做會讓老闆和資安長都笑開懷?那你得先知道,究竟使用 Managed Identity 的好處有多少? 1. 零密碼外洩風險 💪 當你的程式碼裡 完全沒有 密碼時,就算有人偷看你的 GitHub Repository、翻遍你的設定檔、甚至把整個專案下載回去,也拿不到任何可以用來入侵的憑證。因為根本就不存在!這就像是你家的保險箱沒有鑰匙孔,只能透過虹膜辨識開啟,小偷就算把保險箱搬走也沒用。 2. 不用再煩惱密碼輪替(Rotate) 🔄 傳統做法中,如果要定期更換密碼(資安政策通常要求 90 天換一次),你常常得改設定檔檔、重新部署、還要確保所有環境都同步更新。一個不小心,Production 就掛了。但使用 Managed Identity,Azure 會在背後自動處理所有的憑證更新,就像是有個超敬業的助理幫你處理所有煩人的行政工作。 3. 精準的權限管理 🎯 透過 Azure 的 IAM(Identity and Access Management),你可以精確控制「 誰 」可以「 對什麼資源 」做「 哪些操作 」。想讓 WebApp ...

漸漸消失的信任

圖片
我有兩次非常不好的用餐經驗。嗯…或許,該說是一次半。🤔 某天假日,一時興起想吃個早午餐,到了知名的連鎖店之後,點了看起來頗可口的漢堡。過程一切順利,餐點非常迅速的上桌,我迫不及待地品嘗一口,溫度適中,口感極好。一切都非常的完美… 直到…桌上放醬料的籃子旁,突然出現一隻蟑螂,會動的。靠~ 我不動聲色,伸手攔截了剛好從我座位旁經過的服務人員,他一臉驚訝地望著我(我猜他是在想,我為何突然伸手襲擊他!?)。 我什麼都沒說,隨即給了他一個眼色。 他朝我的目光望去,臉上的驚訝轉為慌張。 但,他也不動聲色(厲害!),朝著目標前進,居然用手一巴掌把目標物給抓了起來,隨即往廚房走去,就好像什麼事情都沒發生過一樣。 另一次,一天早晨,我到了一個過去不曾來過的地點,因為剛好有一段不長不短的時間(等人),所以我就沿著大街閒逛,突然看到一家老麵包子店,正愁沒吃早餐,因此我就隨便點肉包菜包各一份,想說試試看。 沒想到,非常之好吃 ! 我對包子是很挑的,我覺得全台灣好吃的包子只有三家,而我今天吃到的這家,居然可以媲美我心中第二名,這讓我內心的包子排行榜大大的洗牌了。 回到家之後,立刻把這包子跟家人分享。 然後我也很疑惑,這麼好吃的店怎麼從來沒有聽到過呢? 上網查。 一查不得了,Google 評價非常兩極。 翻了幾頁都還無所謂,直到我看到一個評價,除了文字還附上了一張照片。 文字是這麼寫的:『吃到腳了,有人吃到頭嗎?』 然後照片是包子裡面一節蟑螂的腳。 靠~ 又來。 你猜,我後來還有去這兩家店嗎? 再也沒有,一次都沒有。 這兩家店不好吃嗎? 不會,其實都很好吃。 但我不會去了,因為我對這兩家店完全失去信心。 (那怕其中一家根本不是親身經驗) 上面是第一段故事。 接著,我要講另一段我前幾天在課堂上說的故事。 我有一個朋友(不是我),他從小喜歡外文,也常常看外文書籍,雖然都是自學,但也因此遍覽群書,自從有了 AI 之後,他樂翻了。 透過 AI 的翻譯,他開始閱讀過去不曾讀過的語言,剎那間全世界的浩瀚,都在他的眼前。由於他常常在網路上分享他讀過的書,因此出版社就開始找他作書籍翻譯,他也很開心能夠把不同語言的書籍介紹給更多有興趣的人。 但因為他畢竟都是靠自學和 AI 翻譯,所以對於比較艱澀少見的文字較難掌握,不過整個大方向他是 OK 的,他用極...

Too Fast to Think 快到來不及思考:AI 時代開發者的腦力透支危機

圖片
上週四晚十一點,有位工作上的夥伴 Eric 在 Teams 上貼出了一段訊息:「剛剛用 Claude 一口氣寫了三個功能,感覺效率爆表!」文末還配上了一個肌肉的 emoji 💪。 隔天,早上九點,我看著他頂著熊貓眼進會議室,手裡拿著第三杯咖啡。「怎麼了?」我問。 「昨晚那幾個功能…有兩個邏輯不對,一個測試全掛…我從半夜改到剛剛。」他苦笑著說「AI 寫得太快了,我根本來不及想清楚就繼續下一個,結果…」 這種場景,你是不是也開始很熟悉? AI 讓我們變成了「高速公路上的疲勞駕駛」 還記得沒有 AI 的年代嗎?(對,我知道那好像已經是上個世紀的事了,雖然才過了兩年) 以前寫程式是這樣的: 思考需求(泡杯咖啡,先想個 15 分鐘) 設計架構(畫畫白板,跟同事討論一下) 開始寫 code(一行一行慢慢敲) 測試除錯(找問題,修 bugs) 提交上版(長舒一口氣) 現在呢? 有了 Claude、GitHub Copilot、Cursor 這些開發神器後,開始有所不同: 在 Prompt 輸入方格裡描述需求(30 秒) AI 給你三種架構方案(10 秒) 選一個,AI 自動生成程式碼(20 秒) 複製貼上,改改參數(1 分鐘) 跑不過?問 AI 為什麼(30 秒) AI 給你修正版本(20 秒) 能動,結束。那…繼續下一個功能… 看起來超讚的對吧?效率提升十倍!老闆眉開眼笑,專案進度超前! 但問題來了:我們的大腦跟上了嗎? 「認知債」:比技術債更可怕的東西 技術債大家都知道,就是為了趕進度寫出來的爛 code,將來要花更多時間來償還。 但現在我們面對的是一種新型態的債務: 認知債 。 什麼是認知債?就是 當 AI 生成程式碼的速度,遠超過你理解這些程式碼的速度時,累積下來的「理解負債」 。 舉個例子。 某天 AI 幫你生成了一個看起來「完美」的 .NET 8 Web API 專案:用 Minimal APIs 搭配 依賴注入 (DI) 、全域 Exception Handling Middleware 、 EF Core (含 UnitOfWork 與 Repository 模式)、 MediatR 指令/查詢分離、 FluentValidation 、 AutoMapper 、背景作業用 IHos...

在 ADO Pipeline 中使用 GitHub Copilot CLI:實現全天候24h開發的夢想

圖片
我跟你說,我夢想著實現這個功能很久了✌ 我一直希望能夠在 CI/CD Pipeline 中加入 LLM 的力量。 我一直想透過 CLI 讓 LLM 在 Pipeline 中自動處理重複性任務。例如,在晚上讓 AI 自動幫我找 bugs、自動做 Code Review、甚至自動撰寫說明文件或一部分程式碼… 然後,我夢寐以求的 “兩班制全天候24h開發團隊” 就可以實現了!!! 白天,由 Developer 搭配 AI 進行開發。 晚上,由 AI 自己去做比較不需要人監督或無傷大雅的工作,像是寫文件,找 bugs 之類的。 然後隔天早上工程師上班之後,就可以繼續接手 AI 昨晚產出的成果,接著進行開發。 嘿嘿,這樣是不是太完美了? 想想都覺得興奮。 緣起 在現代軟體開發中,效率與自動化是不可或缺的要素。 GitHub Copilot CLI 的出現,為我們提供了一個強大的工具,能夠在開發過程中自動生成程式碼、撰寫技術文件,甚至協助除錯。 假設我能將這項工具整合到 Azure DevOps 的 Pipeline 中,自動在晚上運行,就可以實現我之前說的 全天候的開發流程 。(以前是把程式碼發包給印度的工程師,現在 AI 就是我的夜班工程師!!!) 嘗試在 Azure DevOps Pipeline 中使用 GitHub Copilot CLI 想要將 GitHub Copilot CLI 整合到 Azure DevOps Pipeline 中,有幾個關鍵步驟。 首先,你要能夠在 Build Agent 上安裝 GitHub Copilot CLI。要這麼做不難,只需透過底下這個 bash script 指令就可以完成安裝 。 npm install -g @github/copilot 只是,你得先確定 Node.js 已經安裝在你的 Agent 上,且是最新版本。 因此,我們會在 pipeline 中,先用一個 step 來安裝 Node.js。 steps : - task : NodeTool@0 displayName : 'Use Node 22.x' inputs : versionSpec : 22.x 接著,我們就可以安裝 GitHub Copilot CLI 了...

使用ADO MCP搭配Chrome DevTools MCP享受E2E自動化UI測試

圖片
這支影片展示了如何透過 Azure DevOps (ADO) 的 Model Context Protocol (MCP) 整合 Chrome DevTools MCP ,實現端到端(E2E)的自動化 UI 測試流程。 影片中展示了如何讓測試腳本的運行不再倚賴人工,開發者只需要在 GitHub Copilot 中下達提示指令,MCP 代理便能自動呼叫瀏覽器、執行互動測試、檢查運行結果並回報測試通過或失敗,還能順手撰寫完整的測試報告。 整個流程結合了 AI Agent + Chrome DevTools + Azure DevOps Test Case 的強大能力,實現真正的「零人工自動化測試」: 由 PM/SA/PO 負責描述測試路徑 (例如登入流程、輸入數據、按鈕執行…etc.) 由 Chrome DevTools MCP 負責具體執行並檢查測試結果 由 GitHub Copilot 負責記錄與撰寫測試結果 這樣的整合大幅提升測試效率與速度。 未來,或許每位工程師都能「像喝咖啡一樣輕鬆地跑完自動化測試」。 看完之後,來 FB 留言分享一下你的感想~ https://www.facebook.com/DotNetWalker/posts/pfbid02qnBruy8mJLnoCswoXnNRQvAqoyAhnXMEA9dqcun3M3rSMx1rv3NovvAZWmJBFqwBl 我很好奇大家的看法。

有趣比有意義重要

圖片
日前參加 DevDays 2025 大會,和幾位 MVP 講師在台上 live 接受學員們的提問。問題五花八門,既有技術細節,也有宏觀趨勢。會後又和社群朋友閒聊,回到家,還收到幾則來自學員與老友的 LINE 訊息。 和大夥閒聊和互動的過程中讓我更感受到,似乎還是有不少開發人員對 Vibe Coding 以及最近這陣子以來,AI所帶來的改變感到焦慮~ 技術變化如此快速,我們究竟該緊跟不放,還是先按兵不動? 到底該持續follow,還是讓子彈飛一會兒? 不只是個人,企業也急於導入 AI,卻總是找不到真正有意義的場景與能發揮價值施力點。 大家隱約知道 AI 開始改變了許多事情,但心中又有一絲不安:自己該怎麼辦?該如何面對? 在一個半小時的時間裡,我還真無法給一個面面俱到的答案。 最後主持人請我做個總結,但其實我心裡想講的是,在資訊產業當中,面對變革早已不是一天兩天的事情了。2022 年底 ChatGPT 初現時,我滿懷興奮與期待;到了 2023 年中,焦慮與疑惑席捲而來;2024 年底,我逐漸找回自己的節奏,直到今天。 回想自己整個歷程, DevDays 2025 大會的最後,我分享給大家我自己面對 AI 時的三個心態與轉折… 接觸:直球對決 直到今天,仍有不少人對 AI 避之唯恐不及,甚至認為它只是一場即將破滅的泡沫。這樣的想法很可以理解,當市場上各種 AI 課程、話題氾濫,它走向泡沫並不令人意外。但請注意,那是對投資人而言。而我們來說,則大大不同。還記得2001年 .com 泡沫化之後發生的事情嗎?真正的改變,那時才剛剛開始。 AI帶來的影響已無庸置疑,這個階段,你的各種的接觸都是好事(是的,包含可能帶來風險的 Vibe Coding ),各種嘗試都是加分,不要躲避,去面對這個改變,直球對決,這是第一件事情,也是最重要的一件。 體驗:唯有親身嘗試,才會生出洞見 接著是體驗,我是指你自己親身的體驗。不只是去聽聽課,或只是上網玩玩圖片生成、與ChatGPT聊聊天而已。 昨天提到,光是 Vibe Coding 這個詞,十個人就能說出十一種不同的解釋。我自己在 2022 到 2025 年間,就歷經至少四種不同型態的 AI 輔助開發,而 Vibe Coding 這個詞到了2025年初才開始出現。其實每種方式在碰到不同的情境時(專案大小、團隊...

Responsible Vibe Coding

圖片
昨天 “恰巧” 碰上了洗版全台的 vibe coding 事件,所以很多人以為我說 Responsible Vibe Coding 是玩笑話 ​ 不~我是認真的。 你拿 Responsible Vibe Coding 這個字去網路上搜尋,就會發現,早已經有太多人在討論 Vibe Coding 帶來的風險以及如何因應。 特別是對於原本不在軟體開發領域的開發新手而言,有許多需要注意的事情,甚至已經有人針對 Responsible Vibe Coding 列出了 guidelines… LLM確實讓進入軟體開發的門檻大幅下降,甚至有人用了 democracy 這個詞來形容(意味著過去被少數人壟斷的專有能力,如今已釋放給所有人…),但這也是 吳恩達(Andrew Ng) 不喜歡 vibe coding 這個詞彙的原因 讓人誤以為軟體開發從此就變得人人可做了。 然而其實不是的。 因為,專業 與 非專業 的差異,其實不只是能力,而是 『態度』。 專業不只是因為能力比較強,或是比較有經驗,也是因為願意去做那些流程中看似無聊和瑣碎的雜事,以至於我們的成品可以在安全性和品質上得到保障。 寫程式,或許變得容易了(反正都是AI寫嘛),但寫出高品質的好程式,則依舊是專業人士才能作到的事情。 新手面對 Vibe Coding 到底該注意些什麼,如何才能兼顧品質、安全、和效率? 我把相關資訊,放在底下: https://vibe-coding-manifesto.com/ https://medium.com/@harsz89/from-heads-down-to-hands-off-a-journey-into-responsible-vibe-coding-3d81a1c5634c https://www.businessinsider.com/andrew-ng-vibe-coding-unfortunate-term-exhausting-job-2025-6 針對 vibe-coding-manifesto 這份給開發人員的 Responsible Vibe Coding 建議,整理如下: Rules for AI-Assisted PR Submissions(AI 輔助的 PR 提交規則) 這一部分主要在講:如果你用 AI 幫忙產生程式碼,當...

LINE Imagemap 陷阱:baseUrl 原來不是一張圖!

圖片
在最近的某個專案當中,客戶希望在 LINE 官方帳號的互動中,使用 Imagemap 訊息格式。 Imagemap 可以讓使用者點擊圖片上的不同區塊,以便於觸發不同的行為,例如導向不同的網頁、回傳不同的文字訊息,非常適合設計互動式選單或導覽。 例如,假設你用底下這張圖當作Imagemap: 則可以設定成,如果用戶點選左邊,則會出現 鶯歌 的簡介,點右邊,則會出現八德的簡介。 我的 team member 馬上動手實作,照著文件寫下程式碼,其中一則 Imagemap 訊息的json代碼類似底下這樣: { "type" : "imagemap" , "baseUrl" : "https://example.com/images/sample.png" , "altText" : "選單" , "baseSize" : { "width" : 1040 , "height" : 1040 } , "actions" : [ { "type" : "uri" , "linkUri" : "https://example.com/page1" , "area" : { "x" : 0 , "y" : 0 , "width" : 520 , "height" : 520 } } ] } 但是,不管怎麼設定,圖片就是顯示不出來。總是出現類似底下這樣的錯誤訊息: debug 了好一陣子,毫無頭緒。 同仁跑來問我時,我看了一眼,突然想起以前也踩過這個坑。 其實, baseUrl 並不是一張圖片的 URL ! 此參數之所以叫做「baseUrl」,是因為它代表的是 圖片的基底路徑 。(而非圖片的路徑) LINE Imagemap 為了要在不同裝置(例如手機解析度不同)都能有合適的圖...

在LINE Bot中使用MemoryCache保存Semantic Kernel的對談記憶

圖片
在開發 LINE Bot 的 AI Agent 或客服機器人時,最重要的功能之一就是 記憶 。 使用者永遠會預期機器人應該要能「記得上一句話」,並能依照上下文繼續對話。 在 Semantic Kernel 中,提供了 ChatHistory 物件來維護對話脈絡。這個物件會記錄 system / user / assistant 的訊息序列,當傳給大語言模型 (LLM) 時,就能讓模型在上下文中產生更自然的回覆。 但是,有一個問題: LINE Bot 的 Webhook API 是 Stateless 的 ,這意味著,每一次訊息事件進來,Controller 都是新的,不會自動幫你保存之前的 ChatHistory 。 因此,如果我們要讓 Semantic Kernel 記住對話,就需要額外設計一個「記憶儲存機制」。 短期記憶的解決方案:MemoryCache 方法有很多,但如果你的應用場景是: AI Agent / QA 客服 一次對話通常會在 半小時內結束 這時候就不需要複雜的資料庫,只要使用 .NET 內建的 MemoryCache 就能搞定。 MemoryCache 的特點 存放在伺服器記憶體中 可以設定 滑動到期時間 (SlidingExpiration) → 長時間沒互動就清掉 可以設定 絕對到期時間 (AbsoluteExpiration) → 即使一直互動,最多存活多久(避免高費用或token爆掉) 效能快。但也因為是存放在伺服器端記憶體中,應用程式重啟或多台伺服器作HA架構時,資料會消失,重新佈署應用程式時,也會消失。 還算是適合「短期記憶」的應用場景。 專案架構 底下示範如何在 LINE Bot WebAPI 專案中,整合該機制,我們建立了三隻程式: Controllers/LineBotChatGPTWebHookController.cs (處理 LINE Webhook) Controllers/ChatCompletion.cs (使用Semantic Kernel 生成 AI 對話) Controllers/ChatHistoryMemoryStore.cs (短期對談記憶保存) 完整程式碼我放在: https://github.com/isdaviddo...

C# 格式化(formatter)在 VS Code 中的選擇

圖片
程式碼的世界裡,有一個古老的爭論: 大括號 { 到底該放在同一行,還是獨立成一行? 這不只是排版問題,有時甚至會演變成團隊會議上的「宗教戰爭」。而我自己也有喜歡的 indent style ,如果看到團隊中其他人的寫法和我不同,雖不至於惱怒,但總覺得有些彆扭。有一種衝動很想把它全部改成自己習慣的方式。 你大概可以想像,當有一天,我發現 VS Code 升級到新版之後,排版和對齊方式竟然變成和我喜歡的不同,那時候我有多麼的震驚,一整天都想要把它給改回來。 怎麼做? 今天我們就來談談,如何在 VS Code 裡改設定,讓 { 的排版聽話。 兩種常見風格 先來看看範例: 1. K&R (大括號跟在同一行) public class HelloWorld { public void SayHello ( ) { if ( true ) { Console . WriteLine ( "Hello, world!" ) ; } } } 2. Allman Style(大括號獨立一行) public class HelloWorld { public void SayHello ( ) { if ( true ) { Console . WriteLine ( "Hello, world!" ) ; } } } 先問問,你喜歡哪一種? 各自的優缺點 同一行風格 (K&R) ✔ 節省垂直空間,檔案比較短。 ✔ 很多 C# 官方範例和文件都是這種格式。 ✘ 有人覺得程式「擠在一起」,閱讀時容易忽略最末端的 { 。 獨立一行風格 (Allman) ✔ 大括號醒目,結構一眼就能看出來。 ✔ 不容易漏掉對應的 { 與 } 。 ✘ 程式會「莫名變長」,多佔好幾行。 👉 簡單說:前者像極簡主義,後者像穿寬鬆衣服,空間感十足。 你是哪一派呢? 在 VS Code 裡如何調整? 方法一: .editorconfig (推薦) 在專案或解決方案根目錄新增 .editorconfig 檔案: root = true [*...

開發者的肌肉記憶

圖片
前陣子,網路上出現一支很轟動的受訪影片, 原因不只是它的長度驚人👉整整六小時: 更重要的是,受訪者是 DHH。 如果你不熟悉他是誰,DHH 全名是 David Heinemeier Hansson,他是 Basecamp 的創辦人,更是 Ruby on Rails 框架的建立者。在開發者的江湖裡,他是那種推一句話就可能引發社群爭論、寫一篇 blog 就可能改變許多開發者的那種人。 訪談中,他談到一個很多人都有那麼點感覺的主題: AI 與 Vibe Coding 對開發者帶來的影響。 他坦言,自從頻繁使用 Auto Complete 與 AI code generation 之後,開始感受到一種「技能退化」的跡象。(有鑑於他的開發能力與背景,我相信他說的,遠多過於其他那些早已不寫 Code 的業界大佬) 一些原本熟練的 API 名稱,突然要多想一下; 思考邏輯的節奏被打斷,肌肉記憶也逐漸消失。 你知道我個人對 AI 輔助開發一直以來的看法, 在絕大部分的情況下,我支持使用 AI 輔助開發遠高於其他人。 為何是「在絕大部分的情況下」呢? 因為,身為一位稍有年資的開發者,我依稀覺得有某個地方怪怪的,但又一直說不上來是哪裡。 直到這次聽到 DHH 的分享,他是第一個明確說出我一直講不出來的那種感受的人,深思後我不得不同意他的觀點。 大量使用 AI輔助開發,特別是最近很紅的 CLI 那種,確實有可能失去開發者特有的 「肌肉記憶」,不只是敲鍵盤的準確度而已,而是某種鍵盤跟大腦之間獨特的聯繫。 如今,大量使用 AI 輔助開發的人, 大多都認為未來開發者的角色將逐漸改變。 從一個「敲打鍵盤的人」,變成一個「溝通者」或「監工者」。 與 AI 溝通、審視 AI 產出、並且進行判斷與修正。 但這樣的轉變,是否也像極了過去許多技術人員,逐漸離開技術轉型成主管的過程? 看似升級,實則在過程中逐漸失去對技術本身的感知與掌握。 當我們不再自己動手,久而久之,是否也會失去「能動手」的能力? DHH 說,那些「自己一行行鑿刻程式碼」的過程,恰好是開發工作樂趣的來源。 當我們在鍵盤上敲下每一個詞彙時,大腦同時也在構建一種獨特的神經迴路 – 那正是開發者創造力與思考能力的來源。 他並不反對 Vibe Coding,只是用一個開發人員的角度給出了提醒...

Junior Developers 在 Vibe Coding 時的問題與挑戰

圖片
最近有個發生在我們專案上的真實案例。 一位初階開發人員用 AI 一口氣生出 前端註冊表單 以及 後端驗證與寫入資料庫 的程式碼。建置沒錯、可以運行、AI 自我檢查後也說了聲沒問題,但是一跑, 前端的資料就是進不到後端模型 ,驗證當然也就永遠失敗。 這位 Junior Developer 卡在這邊三小時(生成這段程式碼的時間其實只有5分鐘),直到下班前,一票老傢伙看不下去,在旁邊盯著把前後端程式碼一一對起來後才發現,問題居然只需要改一個字母而已。 現場重現:前端 AJAX 送這個 劇情其實很簡單,前端把使用者輸入後的資料,包裹成類似底下這樣的 JSON,透過 AJAX 丟到後端 Controller: { "UserName" : "Rick" , "Email" : "rick@example.com" , "Password" : "P@ssw0rd!" , "PhoneNumber" : "0987123456" } 產出上面的這段 JSON 的程式碼是 AI 寫的。 而接著 ASP.NET Core 的 Controller 大概長底下這樣: [ ApiController ] [ Route ( "api/[controller]" ) ] public class AuthController : ControllerBase { [ HttpPost ( "register" ) ] public IActionResult Register ( [ FromBody ] RegisterRequest input ) { // input 的屬性全是 null -> 驗證失敗 if ( input is null || string . IsNullOrWhiteSpace ( input . username ) ) return BadRequest ( "payload invalid." ) ; /...

AI Agent 開發者必學的 Streaming 漸進式輸出技巧

近年來「AI Agent」的開發已經非常普遍,不管是做客服機器人、知識檢索,還是線上客服小幫手,大家常用的API介面幾乎都是 OpenAI 的 Chat Completions API 。 在大多數情境下,我們會用 非串流(non-streaming) 的方式呼叫,也就是送出一個請求,等伺服器思考完再一次回傳完整的回答。這樣的模式在 LINE、Teams、Slack 這類即時通訊平台的 Chat Bot UI 中沒什麼問題,因為使用者本來就習慣機器人一次回覆一整段文字。 但其實還有一種像是ChatGPT 官網那樣的輸出方式。 漸進式輸出的好處 但如果你用過 ChatGPT 官方網站,就會發現它的回覆方式完全不同:文字會像打字機一樣一個字一個字冒出來。這種「漸進式輸出」的體驗有幾個好處: 回應更即時 使用者不需要等模型完整算完才能看到內容,能先讀到前幾個字,就有「系統已經在思考」的感覺。 降低等待焦慮 在 UX 上,空白畫面最容易讓人懷疑「是不是壞掉了」。逐字輸出則能持續回饋,讓人安心。 模擬自然對話 人類聊天的過程就是一邊想一邊講,這種輸出方式更貼近自然互動。 更有戲劇感 對 Demo、教學、產品展示特別有用,可以讓使用者感覺「AI 正在思考」。 因此,雖然很多 Chat Bot 不一定需要這樣的 UI,但如果你的產品本身能夠提供這種 漸進式對話 ,以「Streaming 方式回覆」可以讓用戶體驗好很多。 Streaming 是怎麼實作的? 那麼,ChatGPT 網站的打字機效果是怎麼做的? 關鍵就在於 OpenAI 提供的 stream: true 參數。 當你在呼叫 /v1/chat/completions API 時,如果設定 stream: true (底下第二行),伺服器就不會一次把整個 JSON 給你,而是會用 Server-Sent Events (SSE) 協議,持續推送「事件」。 { "model": "gpt-4o-mini", "stream": true, "messages": [ { "role": "system", "co...

別讓使用 Vibe Coding 的起點,成為你學習的終點

圖片
『Vibe Coding 是本年度最糟糕的主意。』Continuous Delivery 一書的作者 David Farley 這麼說。 毫無疑問的,AI 可以加快開發速度,但同樣毫無疑問的,Vibe Coding 可能會讓開發人員減少對程式碼的『思考』。👈而這件事情長期來看是危險的。 如果你有開始用 Vibe Coding 做實際專案的開發,特別是中大規模的重構或功能實作,應該多少都會有類似的體會。 讓我自己最訝異的,是現在我花最多的時間竟然不是寫程式,而是在「等待」AI 回應我下的提示詞。 這個等待,短則一兩分鐘,有時甚至要等個五分鐘以上。 在這段等待時間裡,我偶爾會做一些與專案有關的事,但老實說,更多時候是作些雜事,像是回個 Email、傳訊息,甚至看看 YouTube。 等回過神來,思路早已被打斷,在多工之間切換,原本熟悉的「心流」也一點一點消失了。 儘管開發的總體效率看起來是變快的,但我對自己產生的這份程式碼,卻有種「不是我寫的」的陌生感。 儘管每一行都是照著我的提示詞產出,測試也通過了,但我心裡對它總有種說不出的距離。 一開始,我還會很努力地逐行確認,逐句檢查邏輯。 但當 AI 產出的品質愈來愈穩定,我發現自己開始得「靠意志力」才能完整地看過每一段程式。 一旦哪天趕進度、趕時程、測試又剛好都通過,我們就很容易放過它了。「AI這樣改…應該是OK的吧?」這句話愈來愈常出現在心中。 可以想像,當專案進入壓力期,那種「認真檢查 AI 程式碼」的機率只會雪崩式下滑。 從專案管理的角度來看,這樣好像也沒什麼問題:時程更短,效率更高,品質甚至可能更穩定。PM 滿意、客戶開心,聽起來一切都挺不錯的。 但 David Farley 給了我一絲提醒,動手實作對開發者的價值,不只是產生程式碼,而是「透過實作的過程訓練思考與設計」讓開發人員持續累積洞察與能力。 對外行人來說,軟體開發是一種生產技術;但對開發者自己而言,寫程式本身就是一種認知活動,一種將抽象邏輯具象化的過程,是設計、分析、解構與重組問題的訓練。 而 Vibe Coding 讓我們把這些練習機會,一次又一次的交給了 AI。 我們依舊能交付成果,但卻少了過去那些累積經驗的軌跡。 如果寫程式除了交付價值,還包含學習價值,那這部分現在正慢慢被 AI 侵蝕。 以前,從一個 juni...

關於 SSO 登出的那些事:Google、Microsoft、LINE 開發者必讀差異

圖片
前情提要 為何大家現在都喜歡採用 SSO? 我最近手上很多案子,都建議客戶不要自己實作帳號密碼登入,而是直接採用SSO登入。 因為,現今資安與用戶體驗的雙重考量,很多專案開發時,都會選擇整合 Google、Microsoft、LINE 這類大廠的 SSO(Single Sign-On,單一登入)機制,來取代自己儲存帳號密碼,如此可以降低很多資安風險,在面對資安稽核的時候,也省了一些什麼資料庫帳號密碼加密、金鑰保存的一堆麻煩。 而採用SSO對用戶也有一個好處,就是用戶不再需要記得很多組密碼,可以輕易實現 「一個帳號,多處通行」 。用戶在某個服務登入一次,其他整合同一身份平台的 網站/應用程式 就能直接使用,不必每次重新輸入帳密。對用戶來說方便,對開發者來說省事,對資安來說統一控管理論上也比較更安全。 但,不是每個 SSO 都能「好好登出」 某次,被客戶問到了一個問題。 客戶的用戶,使用瀏覽器登入我們的系統,但該瀏覽器會記得用戶的SSO session,因此當用戶關閉瀏覽器後,重新開啟瀏覽器登入系統時,看似需要登入,但發現即便導引到了SSO的登入畫面,卻無須輸入帳密,隨即可以登入!? 其實,SSO單一登入機制 by design 就是這樣設計的,這本來就是SSO的便利性和好處。然而,客戶卻有個疑問,如何強制讓用戶一定要用戶重新輸入帳密呢? 事實上,還真的不是每個 SSO 都能「登出」 雖然許多人都有用過 SSO,但可能很多人不知道: 不是每一個 SSO 都有支援「全域登出」的 API 或 URL 。 事實上,很多整合 SSO 的「登出」功能,本質上只是 在下一次登入時強迫重新驗證 ,並不是真的清空 IdP(身份提供者)的全域 Session。 更有趣的是: 這個所謂的「重新驗證」也不一定會要求用戶重新輸入密碼 。 有的 SSO 可以透過特定的參數在登入時直接強迫用戶輸入帳密(無視現有 Session),有的則只能「盡力要求」。最後要不要真的打密碼,還得看 SSO Provider 如何實作安全政策(例如MFA、零信任)。 就拿我在專案中最常使用的 MS, Google, LINE 三種 SSO Provider 來說,對於「登出」與「重新登入」的實作方式都不同。 Microsoft — 最直白的強制重登 https://login.m...

善用SAS機制在網頁上安全的分享媒體內容

圖片
最近爬蟲事件很熱鬧,許多網站針對防止爬蟲程式竊取資料都有著不同的做法。日前,在一個聚餐中,有位同學提到了一個她們自己公司最近的需求。 該公司所開發的網站,需要將大量的媒體內容(影片、圖片、或是文件),分享給不特定的用戶,上網觀看這些內容的用戶不需要登入,就可以以匿名方式檢視這些媒體內容。 然而,該網站又不希望,用戶(其實主要擔心的不是用戶,是爬蟲)能夠輕易地獲取媒體的網址,就將其分享給其他人,甚至輕易複製出一個完全一模一樣的網站。 簡單的說就是,網站想分享資訊,卻不希望用戶可以再次把這資訊分享給其他人,問大家有沒有好方法。 問到我,當然推一下 Azure 的 Blob儲存體。 近代的雲端儲存機制,其實都有提供類似的功能,可以讓媒體(mp4, jepg, pdf, … etc.)的檢視網址,變成僅供一次性的使用,而且可以針對特定IP或特定時間進行鎖定。 也就是說,當用戶進到某個網頁觀看上面的影片、圖片、閱讀PDF文件的時候,倘若將該媒體的網址複製下來,然後傳給其他第三人,這個第三人是無法用該網址觀看媒體資料的,因為IP不同,觀看的時間也不同。 這個功能稱為 SAS( Shared Access Signature ) : 在 Azure Storage 儲存體的 Blob 上,你可以針對一個受保護的檔案,設定其 SAS( Shared Access Signature ),這意味著如果用戶拿到這個檔案的 url,也無法開啟,一定要有一個合法的簽章,類似底下這樣: https://teststo202508.blob.core.windows.net/testcontainer/sashimi.jpg?sp=r&st=2025-08-02T07:10:29Z&se=2025-08-02T15:25:29Z&spr=https&sv=2024-11-04&sr=b&sig=ch7GZYS8rJii%2B45GJb4kKWj4valFW84E3Btgppc51aE%3D 如果用戶只拿該檔案的原始URL: https://teststo202508.blob.core.windows.net/testcontainer/sashimi.jpg 肯定是不能讀取的,會出現底下錯誤: 你可以針對該檔案,...

原來使用 .net 寫個 MCP Client 也如此簡單

圖片
之前我發了一篇文章,標題是「原來使用 .NET 寫一個 MCP Server 如此簡單」。結果有不少朋友留言敲碗,說:「只有 Server,沒有 Client,這怎麼行?」 呃…我只能說,這個要求顯然 很有道理 。🙄 所以今天趁上課的空檔,補一篇文,來介紹如何撰寫 MCP Client ,把整個架構補齊。 你會發現,其實,開發 MCP Client 也非常簡單耶。 MCP 架構的本質 不過,在開始之前,有一個觀念需要釐清:無論是 MCP Server 或 MCP Client,其實都與 LLM(大型語言模型)沒有 直接關聯 ,這和很多人理解的不同。 MCP 架構的本質,只是為了讓 AI Agent(或 Chat Bot)更容易知道怎麼呼叫外部的服務提供者(就叫做MCP Server),並且能方便地列舉出這些服務所提供的功能(就叫做MCP Server Tool),以及清楚了解每個功能呼叫時所需的參數。某種程度上,它的角色有點類似早期 Web Service 時代的 WSDL/SOAP ,或是現代 REST API 架構中的 Swagger/OpenAPI 👉👉 都是用來提供一種 標準化的服務描述與呼叫方式 ,使服務整合變得更一致、更具可預測性。 至於, 什麼時候該呼叫哪一個功能 、呼叫時所要填入的具體參數 值 是什麼,這些判斷與決策的工作,才是由 AI(LLM) 來處理的。而真正去執行這些呼叫動作的,則是 AI Agent(或者稱之為,MCP Host)。 簡單的說就是,對談機器人(或AI Agent)可以藉由 LLM 來呼叫遠端的服務,而 MCP 架構則讓對談機器人可以得知有哪些服務可供呼叫,並且在呼叫時應該要傳入哪些參數。 因此,要開發一個能夠呼叫 MCP Server 服務的 Client 端,自然也需要建立一個具備決策與執行能力的 AI Agent。 這部分,我們待會會採用 Semantic Kernel 作為實作的基礎框架。 之前我們 早已介紹過 Semantic Kernel ,它不僅可以介接各種 大語言模型(像是 OpenAI 或 Azure OpenAI),還能彈性地設計與掛上各種 skills 與 plugins ,非常適合用來打造具備「對談 → 意圖理解 → 功能選擇 → 發出呼叫」這一整套流程的AI Agen...