最新[工程觀念] 單元測試要測什麼、不要測什麼:釐清邊界,提高測試效益!
前言欸,各位工程師朋友好啊!今天 Hikari 我要來跟大家聊一個,在開發流程中很常聽到,但又常常讓人「不知道怎麼寫」、「寫了覺得沒用」的議題:**單元測試 (Unit Test)**!
很多人對單元測試可能抱持著各種想法:
「我們專案沒時間寫單元測試啦!」
「寫了單元測試,結果每次改程式碼都要改測試,超煩的!」
「不知道要測什麼,就隨便測一下,應付 CI/CD 而已。」
這些心聲我完全能理解!單元測試的確是個雙面刃,寫得好能讓你信心滿滿、快速迭代;寫不好則變成沈重的負擔,每次重構都像在拆地雷。其實,問題的核心往往在於我們對「單元測試的邊界」不夠清晰,搞不清楚它到底該測什麼、不該測什麼。
今天,我們就來好好聊聊,一個有效的單元測試,到底應該關注哪些點?又該避開哪些坑? 希望能幫助大家更有效率地運用單元測試,讓它成為你開發路上的好幫手,而不是絆腳石!
單元測試,到底要測什麼?首先,我們得搞清楚「單元」是什麼?在大多數情況下,一個「單元」指的是你程式碼中最小的、可獨立測試的邏輯片段,通常是一個函式 (Function) 或一個方法 (Method)。重點在於「單一職責 (Si ...
[程式原理] 非同步 async/await 常見誤用,你是不是也踩過這些雷?
前言欸,各位工程師朋友好啊!今天 Hikari 我要來跟大家聊一個,在現代程式設計中幾乎無所不在,但又常常讓人搞得頭昏腦脹的議題:「非同步程式設計」!特別是當我們有了 async/await 這種語法糖之後,寫非同步程式碼看起來好像變簡單了,程式碼也變得跟同步執行一樣好讀。但俗話說得好,水能載舟亦能覆舟,async/await 在簡化了語法的同時,其實也埋下了不少「地雷區」,讓很多開發者在不知不覺中踩到,導致程式碼不如預期、效能低落,甚至出現難以追查的 bug。
你是不是也曾經寫過 async/await 的程式碼,卻發現:
為什麼這個函式明明有 await,結果卻馬上執行下一行?
奇怪,我發了三個網路請求,怎麼等了這麼久?不是說非同步可以同時做嗎?
啊,明明加了 try/catch,怎麼錯誤還是噴出來了?
別擔心,你不是一個人!這些都是 async/await 非常常見的誤用情境。今天,我們就來好好拆解這些「雷區」,看看背後的原理,以及怎麼正確地使用 async/await,讓你的非同步程式碼既優雅又高效!
快速回顧:async/await 到底是什麼?在深入探討誤用之 ...
[後端] API 設計:分頁、篩選、排序的慣例,讓你的 API 更好用!
前言身為一個後端工程師,我們每天都在跟 API 打交道。設計一個好的 API,不只是讓它能動就好,更重要的是要「好用」、「好理解」、「好維護」。一個友善的 API 能讓前端同事笑咪咪,也能讓未來的自己少掉很多麻煩。
今天 Hikari 我想跟大家聊聊,在設計 API 時,有幾個非常常見但又常常被討論的議題:分頁(Pagination)、篩選(Filtering)和排序(Sorting)。這些功能幾乎是每個列表型資料都會需要,但設計上卻有各種不同的風格。到底怎麼做,才算是比較「慣例」且「好用」的設計呢?我們一起來拆解看看!
分頁(Pagination):資料太多怎麼辦?想像一下,如果你要顯示一個有幾十萬筆使用者資料的列表,一次全部撈出來回傳給前端,那會發生什麼事?
網路延遲爆表:傳輸大量資料需要時間,使用者等到天荒地老。
伺服器壓力山大:資料庫一次要撈幾十萬筆,記憶體、CPU 可能都吃不消。
前端卡到不行:瀏覽器一次渲染幾十萬筆 DOM 元素,直接死機給你看。
所以,為了效能考量和使用者體驗,我們一定要做分頁。常見的分頁方式有兩種:傳統的「頁碼分頁」(Offset-based)和比較 ...
[AI] 提示詞注入(Prompt Injection)與防禦:讓你的 LLM 應用不再被綁架!
前言自從大型語言模型(LLM)爆紅之後,各式各樣的 AI 應用如雨後春筍般冒出來,從客服機器人、內容生成、程式碼輔助到自動化代理人,無所不包。我們享受著 LLM 帶來便利的同時,也開始意識到它潛藏的資安風險。其中一個非常特別,而且也讓工程師們很頭痛的問題,就是「提示詞注入」(Prompt Injection)。
欸,什麼是提示詞注入?簡單來說,就是攻擊者透過設計過的輸入,去「綁架」或「誤導」LLM,讓它做出非預期的行為。這可不是開玩笑的,如果你的 LLM 應用程式被成功注入,輕則回答奇怪的內容,重則洩漏機密資料,甚至執行惡意操作!
今天,Hikari 我就來跟大家白話聊聊,這個聽起來有點科幻,但卻真實存在的威脅到底是什麼?它怎麼運作?又有哪些方法可以來防禦它呢?
什麼是提示詞注入(Prompt Injection)?我們知道,LLM 是靠著「提示詞」(Prompt)來理解我們的意圖並生成回應的。一個應用程式通常會有一段「系統提示詞」(System Prompt),用來定義 LLM 的角色、行為規則,還有它能做什麼不能做什麼。接著,使用者再輸入他們的問題或指令,這就是「使用者提示詞」(U ...
[AI] LLM 的 Function Calling / Tool Use 怎麼運作?白話拆解原理與實戰眉角
前言這陣子 LLM 應用爆炸性成長,但你可能會發現,雖然 LLM 很會聊天、很會寫文章,但在處理一些「即時性」或「需要外部工具」的任務時,它就顯得力不從心了。比方說,它沒辦法即時知道現在臺北的天氣,也沒辦法幫你直接查詢今天的股價,更別說幫你發一封信了。
難道 LLM 只能當個「嘴砲型」AI 嗎?當然不是!這時候,我們就要請出 LLM 的超能力之一:「Function Calling」或「Tool Use」了。這項技術讓 LLM 不只會說,還能「動手做」!今天,Hikari 我就來跟大家白話拆解一下,Function Calling 到底怎麼運作,以及我們在實作上會遇到哪些眉角。
Function Calling / Tool Use 到底在幹嘛?想像一下,你現在有一個很聰明的助理,他無所不知,但是他沒辦法自己去拿咖啡、沒辦法自己打電話。Function Calling 就是給這個助理一套「工具箱」跟「使用說明書」,讓他知道在什麼情況下,可以「呼叫」哪個工具,並且提供正確的「參數」給工具,讓工具去完成任務。
簡單來說,Function Calling 就是讓 LLM 能夠:
...
[AI] RAG 實作會踩到的雷與解法
前言這陣子 LLM 應用紅翻天,其中最實用也最常被拿來解決「幻覺」(Hallucination)問題的,大概就是 RAG(Retrieval Augmented Generation,檢索增強生成)了。白話來說,就是讓 LLM 在回答問題前,先去參考一些「課外讀物」,這樣它就比較不會憑空捏造,回答也能更精確。
RAG 聽起來很美好,架構圖看起來也好像很直觀,但實際下去做,你會發現裡面眉角超多,一不小心就踩到雷。我最近在玩 RAG 應用也遇到不少坑,今天就來跟大家分享一下,實作 RAG 會碰到哪些常見問題,以及一些我整理出來的實戰解法。
RAG 的基本流程,我們快速複習一下為了確保大家在同一個頻道上,我們先用一張圖快速回顧一下 RAG 的基本流程。其實就是三大塊:
資料準備(Ingestion):把你的原始文件(PDF、網頁、資料庫內容等等)切成小塊(Chunk),然後轉成向量(Embedding),存到向量資料庫裡。
檢索(Retrieval):使用者提問後,把問題轉成向量,去向量資料庫裡找出最相關的「小塊」(也就是前面切好的 Chunk)。
生成(Generation):把使用者問 ...
[後端] 向量資料庫是什麼?跟一般資料庫差在哪
前言這陣子,如果你有在關注 AI、尤其是大型語言模型(LLM)的應用,肯定會一直聽到一個名詞:「向量資料庫」(Vector Database)。什麼 RAG 要用向量資料庫、推薦系統要用向量資料庫、連圖片搜尋也跟向量資料庫有關……搞得好像它無所不能一樣。
欸,但是它到底是什麼?跟我們平常在用的 MySQL、PostgreSQL、MongoDB 這些傳統資料庫有什麼不同?難道這些老牌資料庫不能用嗎?為什麼突然間大家都跳出來說向量資料庫很屌?
今天,Hikari 我就來用最白話的方式,跟大家聊聊向量資料庫到底在幹嘛,還有它為什麼會在 AI 時代這麼重要。
所以,什麼是「向量」?要搞懂向量資料庫,首先要理解什麼是「向量」(Vector)。在數學上,向量就是一個有方向、有大小的量,通常用一串數字來表示。你高中物理可能學過位移、速度是向量對吧?
但在 AI 的世界裡,它更像是一種「特徵的數位化表示」。
想像一下,你想描述一個人。你可以說他「身高 175 公分、體重 70 公斤、年齡 30 歲」。如果把這些數字排成一串 [175, 70, 30],這就是一個很簡單的「向量」了。這個向量代表了這個人 ...
[後端] 資料庫交易與隔離等級白話講:為什麼你轉帳不能只做一半?
前言工程師們,大家午安!今天想跟大家聊一個看似老生常談,但其實超級重要、而且常常被誤解的概念:資料庫交易(Transaction) 跟 隔離等級(Isolation Level)。
欸,不要看到「交易」兩個字就想說跟錢有關就頭痛,它跟我們每天寫的程式、處理的資料息息相關。想想看,你平常在開發的時候,有沒有遇過這樣的狀況:
客戶回報說,他們的訂單狀態明明已經成功,但庫存卻沒有扣到?
或者使用者抱怨,他剛買完票,但重新整理頁面後,票又可以買了?
更嚴重一點,你轉帳給朋友,結果你的錢扣了,朋友卻沒收到?
這些問題的背後,常常都跟「資料庫交易」沒搞清楚,或者「隔離等級」設定不對有關係。今天,我們就來用最白話的方式,把這些概念拆解開來,讓你知道為什麼不能只做一半,以及怎麼在效能跟資料一致性之間做取捨。
什麼是「交易 (Transaction)」?為什麼你轉帳不能只做一半?想像一下你去銀行轉帳,整個流程通常是這樣:
從你的帳戶扣錢
把錢加到對方的帳戶
這兩個步驟必須「同時成功」或「同時失敗」,不能只完成其中一個。如果你的錢扣了,對方卻沒收到,那麻煩就大了。這個「要嘛全成功、要嘛全失敗」的原 ...
[AI] Prompt 的眉角:讓你的 LLM 不再雞同鴨講
前言自從大型語言模型(LLM)普及之後,大家是不是都開始想辦法把 AI 整合到自己的工作流程裡?從寫程式、除錯、文件整理到發想,LLM 真的超好用。但是,有沒有遇過你給它一個指令,它卻回覆得牛頭不對馬嘴,讓你覺得它根本聽不懂你在說什麼?
這種「雞同鴨講」的狀況,其實大部分時候不是模型不夠聰明,而是我們給的「說明書」不夠清楚。這個說明書,就是我們常說的 Prompt。
Prompt 不只是單純輸入問題,它是一種跟 LLM 溝通的藝術,也是一種工程。寫得好的 Prompt,能讓 LLM 成為你的神隊友;寫得不好,就變成一個只能給你模糊答案的黑箱。今天想跟大家分享一些我在實務上常用、而且很有效的 Prompt 技巧,希望能幫大家跟 LLM 合作得更順暢。
怎麼跟 LLM 溝通最有效?從角色設定開始想像一下,你要跟一個同事請教問題,你會直接丟一句「請解釋區塊鏈」嗎?通常不會對不對?你會先設定情境:「嘿,我是新來的,對區塊鏈有點好奇,可以請你用資深工程師的角度,跟我這個新手解釋一下嗎?」
對 LLM 也是一樣!給 LLM 一個明確的「角色(Role)」,它會更好地理解你的意圖,並以該角色應有的知 ...
[AI] 把 token 當成錢來算,context window 不是越大越好
前言每次看 API 帳單或看到 Token 耗盡的錯誤時,是不是都會有一種「這到底是什麼東西在計費」的懵懵懂懂?
LLM 的 Token 機制和 Context Window,聽起來很高深,但其實就是這兩個東西在決定你的程式會花多少錢、會不會卡。我今天不講大道理,只用最實際的方式拆解它們,還有我在實務上踩過的坑。
Token 到底在算什麼?最常見的迷思是:Token 等於一個英文字母,或等於一個中文字。
其實 Token 是模型底層的「碎塊」。英文大概 4 個字元等於 1 個 Token,中文因為每個字佔用空間較大,通常 1 個中文字會被拆成 1 到 2 個 Token(視語言模型而定)。
舉個例子,Prompt 寫這樣:
1請將以下文章翻譯成英文:今天天氣很好。
這句話大約會消耗 15-20 個 Token(Input token)。你會發現,中文的 Token 消耗速度比英文快很多,這也是為什麼台灣工程師特別需要注意的地方。
Context Window 不是越大越好Context Window 就是模型一次能記住的「工作記憶」容量。你可以想像成你開會時能同時記憶的紙張數量。
早 ...
![[工程觀念] 單元測試要測什麼、不要測什麼:釐清邊界,提高測試效益!](/img/covers/unit-test-what-to-test-what-not-to-test.jpg)
![[後端] API 設計:分頁、篩選、排序的慣例,讓你的 API 更好用!](/img/covers/api-design-pagination-filtering-sorting-conventions.jpg)
![[AI] 提示詞注入(Prompt Injection)與防禦:讓你的 LLM 應用不再被綁架!](/img/covers/prompt-injection-defense.jpg)
![[AI] LLM 的 Function Calling / Tool Use 怎麼運作?白話拆解原理與實戰眉角](/img/covers/llm-function-calling-tool-use-how-it-works.jpg)
![[AI] RAG 實作會踩到的雷與解法](/img/covers/rag-pitfalls-and-solutions.jpg)
![[後端] 向量資料庫是什麼?跟一般資料庫差在哪](/img/covers/vector-database-vs-traditional-database.jpg)
![[後端] 資料庫交易與隔離等級白話講:為什麼你轉帳不能只做一半?](/img/covers/database-transaction-isolation-level-explained.jpg)
![[AI] Prompt 的眉角:讓你的 LLM 不再雞同鴨講](/img/covers/llm-prompt-techniques-practical-tips.jpg)
![[AI] 把 token 當成錢來算,context window 不是越大越好](/img/covers/token-cost-context-window.jpg)