<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Liwen's Digital Garden Blog</title>
        <link>https://garden.liwen.studio/blog</link>
        <description>Liwen's Digital Garden Blog</description>
        <lastBuildDate>Sun, 07 Jun 2026 13:30:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>zh-Hant</language>
        <item>
            <title><![CDATA[寫程式不如 AI？當我們陷入「開發恐怖谷」，工程師的價值該往哪裡擺？]]></title>
            <link>https://garden.liwen.studio/blog/ai-development-uncanny-valley</link>
            <guid>https://garden.liwen.studio/blog/ai-development-uncanny-valley</guid>
            <pubDate>Sun, 07 Jun 2026 13:30:00 GMT</pubDate>
            <description><![CDATA[當 AI 展現出超越人類的開發能力，工程師該如何自處？探討在 AI 時代下，軟體工程師如何從「執行者」轉型為「系統建築師」的價值反思。]]></description>
            <content:encoded><![CDATA[<p>在與 AI 協作的過程中，你是否曾產生過一種不適感？</p>
<p>這是一種微妙的「程式開發恐怖谷效應」。當 AI 在程式碼撰寫、邏輯推演上都展現出超越人類的能力時，我們不禁會產生懷疑：<strong>我們真的比 AI 厲害嗎？如果我硬要介入技術細節，反而成為了 AI 發揮能力的絆腳石？</strong></p>
<p>這是我近期深刻的迷惘。</p>
<!-- -->
<p><img decoding="async" loading="lazy" src="https://truth.bahamut.com.tw/s01/202005/dfa5560a71d8b2b81279b273a352469b.JPG" alt="當 AI 成為開發主力" class="img_ev3q"></p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="放手或許才是最高級的協作">放手，或許才是最高級的協作<a href="https://garden.liwen.studio/blog/ai-development-uncanny-valley#%E6%94%BE%E6%89%8B%E6%88%96%E8%A8%B1%E6%89%8D%E6%98%AF%E6%9C%80%E9%AB%98%E7%B4%9A%E7%9A%84%E5%8D%94%E4%BD%9C" class="hash-link" aria-label="放手，或許才是最高級的協作的直接連結" title="放手，或許才是最高級的協作的直接連結" translate="no">​</a></h3>
<p>過去我們習慣思考如何用特定的技術（技術選型）來實作功能，但現在如果我們強行用自己有限的技術認知去規範 AI 的開發路徑，結果往往不如直接告訴 AI 目標，讓他自己尋找最優解。</p>
<p>就像詠春拳教導的，「不要跟他拼拳，要切他中路」。與其在 AI 最擅長的「寫程式」與「邏輯運算」上硬碰硬，我們應該找到目前 AI 的「短板」，那才是人類工程師的核心戰場。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="工程師的切中路策略從執行者轉向設計師">工程師的「切中路」策略：從執行者轉向設計師<a href="https://garden.liwen.studio/blog/ai-development-uncanny-valley#%E5%B7%A5%E7%A8%8B%E5%B8%AB%E7%9A%84%E5%88%87%E4%B8%AD%E8%B7%AF%E7%AD%96%E7%95%A5%E5%BE%9E%E5%9F%B7%E8%A1%8C%E8%80%85%E8%BD%89%E5%90%91%E8%A8%AD%E8%A8%88%E5%B8%AB" class="hash-link" aria-label="工程師的「切中路」策略：從執行者轉向設計師的直接連結" title="工程師的「切中路」策略：從執行者轉向設計師的直接連結" translate="no">​</a></h3>
<p>既然 AI 擅長產出，那麼我們就專注在產出前的「需求收斂」與產出後的「價值整合」。我分析了目前 AI 尚無法完美取代的四個核心領域：</p>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-跨部門工作流workflow的梳理與整合">1. 跨部門工作流（Workflow）的梳理與整合<a href="https://garden.liwen.studio/blog/ai-development-uncanny-valley#1-%E8%B7%A8%E9%83%A8%E9%96%80%E5%B7%A5%E4%BD%9C%E6%B5%81workflow%E7%9A%84%E6%A2%B3%E7%90%86%E8%88%87%E6%95%B4%E5%90%88" class="hash-link" aria-label="1. 跨部門工作流（Workflow）的梳理與整合的直接連結" title="1. 跨部門工作流（Workflow）的梳理與整合的直接連結" translate="no">​</a></h4>
<p>AI 無法直接走進辦公室，理解各部門之間那些混亂、充滿人性與政治角力的溝通鏈。我們不可能直接把一台掛著 AI Agent 的電腦扔給業務部門，就指望他們梳理出自動化的邏輯。</p>
<ul>
<li class=""><strong>人類的價值：</strong> 我們扮演「翻譯者」與「架構師」，去洞察部門真實的痛點、梳理資源流程，並將這些充滿雜訊的訊息，轉化為 AI 可理解的精確規格。</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-專業需求分析與深度檢核">2. 專業需求分析與深度檢核<a href="https://garden.liwen.studio/blog/ai-development-uncanny-valley#2-%E5%B0%88%E6%A5%AD%E9%9C%80%E6%B1%82%E5%88%86%E6%9E%90%E8%88%87%E6%B7%B1%E5%BA%A6%E6%AA%A2%E6%A0%B8" class="hash-link" aria-label="2. 專業需求分析與深度檢核的直接連結" title="2. 專業需求分析與深度檢核的直接連結" translate="no">​</a></h4>
<p>使用者往往無法清楚描述自己要什麼，他們說的是「結果」，而非「需求」。</p>
<ul>
<li class=""><strong>人類的價值：</strong> 我們用專業知識幫使用者收斂需求，確保 AI 產出的產品符合預期；並在產出後，扮演「品質守門員」，檢核效能、資安、可維護性等面向。雖然 AI 未來可能也會考慮這些，但這正是我們現在發揮經驗積累的關鍵。</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-系統架構設計與技術債治理">3. 系統架構設計與「技術債」治理<a href="https://garden.liwen.studio/blog/ai-development-uncanny-valley#3-%E7%B3%BB%E7%B5%B1%E6%9E%B6%E6%A7%8B%E8%A8%AD%E8%A8%88%E8%88%87%E6%8A%80%E8%A1%93%E5%82%B5%E6%B2%BB%E7%90%86" class="hash-link" aria-label="3. 系統架構設計與「技術債」治理的直接連結" title="3. 系統架構設計與「技術債」治理的直接連結" translate="no">​</a></h4>
<p>AI 寫單一功能（Happy Path）非常快，但它往往缺乏對整個專案「宏觀架構」的想像力。如果完全放任 AI 寫程式，很容易產出看起來能動，但未來難以擴充的「義大利麵條程式碼」。</p>
<ul>
<li class=""><strong>人類的價值：</strong> 我們必須身兼「架構師」的角色，不只要確保模組化設計（如 MVC、Design Patterns），更要防堵 AI 產生幻覺或默默累積巨大的「技術債」，確保系統底層的健康與高擴充性。</li>
</ul>
<h4 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-邊界條件edge-cases與複雜除錯">4. 邊界條件（Edge Cases）與複雜除錯<a href="https://garden.liwen.studio/blog/ai-development-uncanny-valley#4-%E9%82%8A%E7%95%8C%E6%A2%9D%E4%BB%B6edge-cases%E8%88%87%E8%A4%87%E9%9B%9C%E9%99%A4%E9%8C%AF" class="hash-link" aria-label="4. 邊界條件（Edge Cases）與複雜除錯的直接連結" title="4. 邊界條件（Edge Cases）與複雜除錯的直接連結" translate="no">​</a></h4>
<p>當系統在完美狀態下運行，AI 無懈可擊；但真實世界總是充滿意外，例如第三方 API 文件寫錯、網路不穩的玄學問題、或是各種奇葩的使用者行為，這時 AI 往往會陷入鬼打牆的死胡同。</p>
<ul>
<li class=""><strong>人類的價值：</strong> 我們憑藉著多年的踩雷經驗與「除錯直覺」，在處理極端邊界條件、效能瓶頸或冷門的底層環境問題時，依然是目前無可取代的終極救火隊長。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="未來的技能發展方向">未來的技能發展方向<a href="https://garden.liwen.studio/blog/ai-development-uncanny-valley#%E6%9C%AA%E4%BE%86%E7%9A%84%E6%8A%80%E8%83%BD%E7%99%BC%E5%B1%95%E6%96%B9%E5%90%91" class="hash-link" aria-label="未來的技能發展方向的直接連結" title="未來的技能發展方向的直接連結" translate="no">​</a></h3>
<p>思考過後，我認為未來軟體工程師的職涯發展，應該朝向以下幾個維度進行自我優化：</p>
<ul>
<li class=""><strong>從「會用 AI」升級為「打造 AI 生態」：</strong> 當熟練操作 AI 工具已成為所有工程師的「基本盤」，未來的突圍方向將是「AI 產品化」。不再只是用 AI 寫扣，而是要具備設計 AI Agent 工作流、甚至是將企業內部痛點結合 LLM 轉化為自動化服務架構的能力。</li>
<li class=""><strong>深耕業務邏輯優化：</strong> 成為更懂「業務」的開發者。利用 AI 高效率產出程式碼，我們則騰出時間去優化整體部門的邏輯結構與自動化流程。</li>
<li class=""><strong>跨領域的技術整合（全端思維）：</strong> AI 大幅降低了語法的學習門檻，前端跨後端、甚至跨雲端部署的成本變得極低。未來不再死守單一技術棧，能運用 AI 串聯 Frontend、Backend 到 DevOps 的「全端整合者」將大放異彩。</li>
<li class=""><strong>軟實力與影響力升級：</strong> 當「寫出能動的程式」變成基本盤，工程師的護城河將轉移到跨部門溝通、專案時程控管，以及將技術語言轉化為商業價值的說服力。這些充滿「人味」的軟實力，是 AI 最難以複製的籌碼。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="結語">結語<a href="https://garden.liwen.studio/blog/ai-development-uncanny-valley#%E7%B5%90%E8%AA%9E" class="hash-link" aria-label="結語的直接連結" title="結語的直接連結" translate="no">​</a></h3>
<p>不要再糾結於「寫程式這件事我輸給了 AI」。當我們不再執著於拼拳，轉而專注於梳理邏輯與串連價值，你會發現，人類工程師並未被淘汰，我們只是從「磚塊搬運工」，變成了「系統建築師」。</p>]]></content:encoded>
            <category>AI協作</category>
            <category>職涯發展</category>
            <category>隨筆</category>
        </item>
        <item>
            <title><![CDATA[【開發者心聲】當「技術優化」變成「職場許願池」，我們該如何應對？]]></title>
            <link>https://garden.liwen.studio/blog/tech-optimization-vs-wishlist</link>
            <guid>https://garden.liwen.studio/blog/tech-optimization-vs-wishlist</guid>
            <pubDate>Wed, 13 May 2026 01:43:00 GMT</pubDate>
            <description><![CDATA[身為工程師，我們最怕的不是複雜的演算法，而是那種「邏輯斷層」的溝通。最近在思考職場定位時，有感而發想聊聊一個現象：為什麼有些優化專案，最後會變成技術人員的災難？]]></description>
            <content:encoded><![CDATA[<p>身為工程師，我們最怕的不是複雜的演算法，而是那種「邏輯斷層」的溝通。最近在思考職場定位時，有感而發想聊聊一個現象：為什麼有些優化專案，最後會變成技術人員的災難？</p>
<p>當「技術優化」的口號響起，如果缺乏清晰的業務定義，工程師往往會從「解決問題的人」變成「幫人通靈的人」。這不僅是效率的浪費，更是對專業價值的消耗。</p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="為什麼優化會變成災難">為什麼優化會變成災難？<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#%E7%82%BA%E4%BB%80%E9%BA%BC%E5%84%AA%E5%8C%96%E6%9C%83%E8%AE%8A%E6%88%90%E7%81%BD%E9%9B%A3" class="hash-link" aria-label="為什麼優化會變成災難？的直接連結" title="為什麼優化會變成災難？的直接連結" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-消失的需求發起人傳聲筒式溝通">1. 消失的需求發起人：傳聲筒式溝通<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#1-%E6%B6%88%E5%A4%B1%E7%9A%84%E9%9C%80%E6%B1%82%E7%99%BC%E8%B5%B7%E4%BA%BA%E5%82%B3%E8%81%B2%E7%AD%92%E5%BC%8F%E6%BA%9D%E9%80%9A" class="hash-link" aria-label="1. 消失的需求發起人：傳聲筒式溝通的直接連結" title="1. 消失的需求發起人：傳聲筒式溝通的直接連結" translate="no">​</a></h3>
<p>在理想的開發流程中，需求應該來自對業務有深刻理解的使用端。但現實中，常出現一種「傳聲筒式」的需求：上層給了壓力，中間單位便列出一長串清單，卻沒有人能解釋清單背後的業務邏輯。</p>
<p>當技術端被要求「主動追蹤」這些模糊的需求時，我們其實是在替別人思考。這種「思考轉嫁」不僅效率極低，更讓工程師變成了行政追蹤員。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-專業邏輯的界線技術不是萬能丹">2. 專業邏輯的界線：技術不是萬能丹<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#2-%E5%B0%88%E6%A5%AD%E9%82%8F%E8%BC%AF%E7%9A%84%E7%95%8C%E7%B7%9A%E6%8A%80%E8%A1%93%E4%B8%8D%E6%98%AF%E8%90%AC%E8%83%BD%E4%B8%B9" class="hash-link" aria-label="2. 專業邏輯的界線：技術不是萬能丹的直接連結" title="2. 專業邏輯的界線：技術不是萬能丹的直接連結" translate="no">​</a></h3>
<p>最令人無奈的情境是：當系統計算結果與預期不符時，使用者回了一句：「我不知道，那是系統（或 AI）算的。」</p>
<p>這反映了一個嚴重的認知偏誤：<strong>技術可以優化流程，但無法「發明」業務邏輯。</strong>
如果連使用單位都說不清楚核心計算公式，卻期待工程師能通靈產出答案，這不叫優化，這叫「盲目建設」。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-被瑣事消磨的技術熱忱">3. 被瑣事消磨的技術熱忱<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#3-%E8%A2%AB%E7%91%A3%E4%BA%8B%E6%B6%88%E7%A3%A8%E7%9A%84%E6%8A%80%E8%A1%93%E7%86%B1%E5%BF%B1" class="hash-link" aria-label="3. 被瑣事消磨的技術熱忱的直接連結" title="3. 被瑣事消磨的技術熱忱的直接連結" translate="no">​</a></h3>
<p>開發者的成就感來自於解決具挑戰性的技術問題，或是學習新的技術架構。然而，當大部分的時間被浪費在「釐清不存在的邏輯」或「處理白做工的行政流程」時，技術熱忱就會迅速被消磨。</p>
<blockquote>
<p><strong>「白做工」是職場上最大的資源浪費。</strong></p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="建立健康的協作防線開發者的自我守護">建立健康的協作防線：開發者的自我守護<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#%E5%BB%BA%E7%AB%8B%E5%81%A5%E5%BA%B7%E7%9A%84%E5%8D%94%E4%BD%9C%E9%98%B2%E7%B7%9A%E9%96%8B%E7%99%BC%E8%80%85%E7%9A%84%E8%87%AA%E6%88%91%E5%AE%88%E8%AD%B7" class="hash-link" aria-label="建立健康的協作防線：開發者的自我守護的直接連結" title="建立健康的協作防線：開發者的自我守護的直接連結" translate="no">​</a></h2>
<p>為了避免成為無底洞的許願池，我認為技術端需要建立幾道防線：</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="️-拒絕通靈開發">🛡️ 拒絕「通靈」開發<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#%EF%B8%8F-%E6%8B%92%E7%B5%95%E9%80%9A%E9%9D%88%E9%96%8B%E7%99%BC" class="hash-link" aria-label="🛡️ 拒絕「通靈」開發的直接連結" title="🛡️ 拒絕「通靈」開發的直接連結" translate="no">​</a></h3>
<p>要求需求方必須提供明確的業務邏輯與預期目標。如果對方說不清楚「為什麼要做」與「規則是什麼」，那麼這個開發任務就不應該啟動。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-釐清責任邊界">🤝 釐清責任邊界<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#-%E9%87%90%E6%B8%85%E8%B2%AC%E4%BB%BB%E9%82%8A%E7%95%8C" class="hash-link" aria-label="🤝 釐清責任邊界的直接連結" title="🤝 釐清責任邊界的直接連結" translate="no">​</a></h3>
<p>技術負責「實現（How）」，業務負責「定義（What）」。當邊界模糊時，工程師會被迫承擔非專業領域的決策壓力，這對雙方都是風險。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-守護核心時間">⏳ 守護核心時間<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#-%E5%AE%88%E8%AD%B7%E6%A0%B8%E5%BF%83%E6%99%82%E9%96%93" class="hash-link" aria-label="⏳ 守護核心時間的直接連結" title="⏳ 守護核心時間的直接連結" translate="no">​</a></h3>
<p>減少無效的行政追蹤。工程師的時間應該花在優化架構、提升效能，或是探索能帶來真實價值的技術迭代，而不是在混亂的溝通中空轉。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="結語把時間花在創造價值">結語：把時間花在創造價值<a href="https://garden.liwen.studio/blog/tech-optimization-vs-wishlist#%E7%B5%90%E8%AA%9E%E6%8A%8A%E6%99%82%E9%96%93%E8%8A%B1%E5%9C%A8%E5%89%B5%E9%80%A0%E5%83%B9%E5%80%BC" class="hash-link" aria-label="結語：把時間花在創造價值的直接連結" title="結語：把時間花在創造價值的直接連結" translate="no">​</a></h2>
<p>與其在混亂的流程中掙扎，不如重新思考如何優化協作機制。我們應該把時間花在創造真實的價值，而不是在別人的懶惰或邏輯斷層中打轉。</p>
<p><strong>優化的第一步，往往不是改 Code，而是先優化溝通。</strong></p>]]></content:encoded>
            <category>職場</category>
            <category>工程文化</category>
            <category>心法</category>
        </item>
        <item>
            <title><![CDATA[ai coding 讓我開始害怕自己忘記怎麼思考]]></title>
            <link>https://garden.liwen.studio/blog/ai-coding-reflection</link>
            <guid>https://garden.liwen.studio/blog/ai-coding-reflection</guid>
            <pubDate>Wed, 06 May 2026 00:06:32 GMT</pubDate>
            <description><![CDATA[深度反思 AI 輔助寫程式對開發者邏輯能力的影響，探討如何從『結果導向』轉向『邏輯導向』的 AI 協作模式。]]></description>
            <content:encoded><![CDATA[<p>最近我有個習慣讓我有點不安——我發現我在用 AI 寫程式的時候，根本不會先想「這要怎麼做」，而是直接打開對話框，把需求貼進去，等結果出來。</p>
<p>有一天我突然意識到：如果 AI 今天消失了，我還會寫程式嗎？</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="一個讓我驚醒的小需求">一個讓我驚醒的小需求<a href="https://garden.liwen.studio/blog/ai-coding-reflection#%E4%B8%80%E5%80%8B%E8%AE%93%E6%88%91%E9%A9%9A%E9%86%92%E7%9A%84%E5%B0%8F%E9%9C%80%E6%B1%82" class="hash-link" aria-label="一個讓我驚醒的小需求的直接連結" title="一個讓我驚醒的小需求的直接連結" translate="no">​</a></h2>
<p>事情是這樣的。我在做一個功能，有個欄位裡面存了多家公司的 tag，產品需求是：<strong>超過 3 家公司的時候，不要全部列出來，改成顯示一個「Open Model」的 tag，使用者點擊之後跳出彈跳視窗看明細。</strong></p>
<p>以前的我，會直接這樣跟 AI 說：</p>
<blockquote>
<p>「這欄位裡面抓出來的公司，如果超過 3 家直接幫我顯示 open model 的 tag，點開之後我要可以看到明細」</p>
</blockquote>
<p>這樣說沒有錯，功能也會動。</p>
<p>但我發現一件事：<strong>我完全不知道 AI 怎麼做到的。</strong></p>
<p>我不知道它用什麼資料結構存公司清單，不知道它怎麼判斷數量，不知道 modal 是怎麼觸發的。如果它生出來的東西有 bug，我甚至不知道要從哪裡下手。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="我決定改變問法">我決定改變問法<a href="https://garden.liwen.studio/blog/ai-coding-reflection#%E6%88%91%E6%B1%BA%E5%AE%9A%E6%94%B9%E8%AE%8A%E5%95%8F%E6%B3%95" class="hash-link" aria-label="我決定改變問法的直接連結" title="我決定改變問法的直接連結" translate="no">​</a></h2>
<p>後來我強迫自己先想一遍流程，再跟 AI 說：</p>
<blockquote>
<p>「這個欄位抓出來的公司清單，幫我用陣列變數先儲存起來。如果公司數量超過 3 家，顯示 Open Model 的 tag，使用者點擊之後跳出彈跳視窗，裡面列出完整的公司明細。」</p>
</blockquote>
<p>差在哪裡？</p>
<p>我在說這句話之前，腦袋裡已經跑過一遍：</p>
<ul>
<li class="">先用<strong>陣列</strong>把資料存起來</li>
<li class=""><strong>判斷陣列長度</strong>是否超過 3</li>
<li class="">超過的話<strong>渲染 tag</strong></li>
<li class="">點擊觸發<strong>modal 顯示明細</strong></li>
</ul>
<p>AI 只是幫我把這個邏輯寫成程式碼，<strong>邏輯是我的</strong>。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="用程式碼來說明差異">用程式碼來說明差異<a href="https://garden.liwen.studio/blog/ai-coding-reflection#%E7%94%A8%E7%A8%8B%E5%BC%8F%E7%A2%BC%E4%BE%86%E8%AA%AA%E6%98%8E%E5%B7%AE%E7%95%B0" class="hash-link" aria-label="用程式碼來說明差異的直接連結" title="用程式碼來說明差異的直接連結" translate="no">​</a></h2>
<p>讓我用實際的例子讓這個差異更具體。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="結果導向的問法ai-可能生出這種東西">「結果導向」的問法，AI 可能生出這種東西：<a href="https://garden.liwen.studio/blog/ai-coding-reflection#%E7%B5%90%E6%9E%9C%E5%B0%8E%E5%90%91%E7%9A%84%E5%95%8F%E6%B3%95ai-%E5%8F%AF%E8%83%BD%E7%94%9F%E5%87%BA%E9%80%99%E7%A8%AE%E6%9D%B1%E8%A5%BF" class="hash-link" aria-label="「結果導向」的問法，AI 可能生出這種東西：的直接連結" title="「結果導向」的問法，AI 可能生出這種東西：的直接連結" translate="no">​</a></h3>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(80, 250, 123)">CompanyTags</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token parameter"> companies </span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">companies</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">tag</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">Open Model</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> companies</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">c</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">tag</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">c</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>功能是有了，但你看到這段 code 可能還是霧煞煞——modal 呢？明細呢？你可能要再問一次，然後 AI 幫你加上去，結果整個邏輯散在各地，你也不知道為什麼。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="邏輯導向的問法你腦袋裡有架構ai-生出來的東西才是完整的">「邏輯導向」的問法，你腦袋裡有架構，AI 生出來的東西才是完整的：<a href="https://garden.liwen.studio/blog/ai-coding-reflection#%E9%82%8F%E8%BC%AF%E5%B0%8E%E5%90%91%E7%9A%84%E5%95%8F%E6%B3%95%E4%BD%A0%E8%85%A6%E8%A2%8B%E8%A3%A1%E6%9C%89%E6%9E%B6%E6%A7%8Bai-%E7%94%9F%E5%87%BA%E4%BE%86%E7%9A%84%E6%9D%B1%E8%A5%BF%E6%89%8D%E6%98%AF%E5%AE%8C%E6%95%B4%E7%9A%84" class="hash-link" aria-label="「邏輯導向」的問法，你腦袋裡有架構，AI 生出來的東西才是完整的：的直接連結" title="「邏輯導向」的問法，你腦袋裡有架構，AI 生出來的東西才是完整的：的直接連結" translate="no">​</a></h3>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">import</span><span class="token plain"> </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token imports"> useState </span><span class="token imports punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token keyword module" style="color:rgb(189, 147, 249);font-style:italic">from</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"react"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">function</span><span class="token plain"> </span><span class="token function maybe-class-name" style="color:rgb(80, 250, 123)">CompanyTags</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token parameter"> companies </span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">isOpen</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> setIsOpen</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"> </span><span class="token operator">=</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">useState</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token boolean">false</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// 1. 用陣列變數儲存公司清單（companies 本身就是陣列）</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token comment" style="color:rgb(98, 114, 164)">// 2. 判斷數量是否超過 3 家</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> isOverLimit </span><span class="token operator">=</span><span class="token plain"> companies</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token property-access">length</span><span class="token plain"> </span><span class="token operator">&gt;</span><span class="token plain"> </span><span class="token number">3</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token keyword control-flow" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">isOverLimit </span><span class="token operator">?</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)">// 3. 超過就顯示 Open Model tag</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">          </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">tag open-model</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">          </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript arrow operator" style="color:rgb(255, 121, 198)">=&gt;</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">setIsOpen</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript boolean" style="color:rgb(255, 121, 198)">true</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">          </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">style</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript literal-property property" style="color:rgb(255, 121, 198)">cursor</span><span class="token tag script language-javascript operator" style="color:rgb(255, 121, 198)">:</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript string" style="color:rgb(255, 121, 198)">"pointer"</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token tag" style="color:rgb(255, 121, 198)">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">          Open Model</span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token comment" style="color:rgb(98, 114, 164)">// 沒超過就正常列出</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        companies</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">company</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> i</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">          </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">key</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">i</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">tag</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">company</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">span</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token comment" style="color:rgb(98, 114, 164)">/* 4. Modal：顯示公司明細 */</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">isOpen </span><span class="token operator">&amp;&amp;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">modal-overlay</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript arrow operator" style="color:rgb(255, 121, 198)">=&gt;</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">setIsOpen</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript boolean" style="color:rgb(255, 121, 198)">false</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">          </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">className</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(248, 248, 242)">=</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag attr-value" style="color:rgb(255, 121, 198)">modal-box</span><span class="token tag attr-value punctuation" style="color:rgb(248, 248, 242)">"</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript parameter" style="color:rgb(255, 121, 198)">e</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript arrow operator" style="color:rgb(255, 121, 198)">=&gt;</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> e</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token tag script language-javascript method function property-access" style="color:rgb(80, 250, 123)">stopPropagation</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">h3</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">公司清單</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">h3</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">ul</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">              </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">companies</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token method function property-access" style="color:rgb(80, 250, 123)">map</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token parameter">company</span><span class="token parameter punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token parameter"> i</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token arrow operator">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">li</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">key</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)">i</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain">company</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">li</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">              </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">ul</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">            </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;</span><span class="token tag" style="color:rgb(255, 121, 198)">button</span><span class="token tag" style="color:rgb(255, 121, 198)"> </span><span class="token tag attr-name" style="color:rgb(241, 250, 140)">onClick</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(248, 248, 242)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript arrow operator" style="color:rgb(255, 121, 198)">=&gt;</span><span class="token tag script language-javascript" style="color:rgb(255, 121, 198)"> </span><span class="token tag script language-javascript function" style="color:rgb(80, 250, 123)">setIsOpen</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token tag script language-javascript boolean" style="color:rgb(255, 121, 198)">false</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text">關閉</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">button</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">          </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">        </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag" style="color:rgb(255, 121, 198)">div</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">      </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain-text"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&lt;/</span><span class="token tag punctuation" style="color:rgb(248, 248, 242)">&gt;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></div></code></pre></div></div>
<p>這版你看得懂：陣列在哪、判斷在哪、modal 怎麼開、怎麼關。哪裡出問題，你知道要去找哪裡。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="兩種問法的本質差異">兩種問法的本質差異<a href="https://garden.liwen.studio/blog/ai-coding-reflection#%E5%85%A9%E7%A8%AE%E5%95%8F%E6%B3%95%E7%9A%84%E6%9C%AC%E8%B3%AA%E5%B7%AE%E7%95%B0" class="hash-link" aria-label="兩種問法的本質差異的直接連結" title="兩種問法的本質差異的直接連結" translate="no">​</a></h2>
<table><thead><tr><th></th><th>結果導向</th><th>邏輯導向</th></tr></thead><tbody><tr><td>你在做什麼</td><td>描述你要什麼</td><td>描述怎麼做到</td></tr><tr><td>AI 的角色</td><td>幫你解決問題</td><td>幫你把想法寫成 code</td></tr><tr><td>出 bug 時</td><td>不知從何下手</td><td>知道要去哪裡找</td></tr><tr><td>長期影響</td><td>邏輯能力退化</td><td>持續在練習拆解問題</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="其實這不是-ai-的問題">其實這不是 AI 的問題<a href="https://garden.liwen.studio/blog/ai-coding-reflection#%E5%85%B6%E5%AF%A6%E9%80%99%E4%B8%8D%E6%98%AF-ai-%E7%9A%84%E5%95%8F%E9%A1%8C" class="hash-link" aria-label="其實這不是 AI 的問題的直接連結" title="其實這不是 AI 的問題的直接連結" translate="no">​</a></h2>
<p>仔細想想，這個問題不是 AI 造成的，而是<strong>我讓自己跳過了思考的步驟</strong>。</p>
<p>以前沒有 AI 的時候，我要自己 Google、自己拼湊、自己想架構——那個過程雖然痛苦，但正是那個過程在鍛鍊邏輯。</p>
<p>AI 的出現，讓這個過程可以跳過。但跳過不代表不需要。</p>
<p>所以我現在給自己定了一個規則：</p>
<blockquote>
<p><strong>在打開 AI 之前，先在腦袋裡或紙上把步驟拆一遍。</strong></p>
</blockquote>
<p>不需要想到 code 層級，但至少要想到：資料怎麼存、判斷條件是什麼、觸發什麼事件、呈現什麼結果。</p>
<p>這樣 AI 就回到它該有的位置——<strong>是工具，不是大腦。</strong></p>
<hr>]]></content:encoded>
            <category>ai</category>
            <category>職涯心理</category>
        </item>
        <item>
            <title><![CDATA[小夕出月中記：新手爸爸的三棲戰士日常與育兒觀念碰撞]]></title>
            <link>https://garden.liwen.studio/blog/weekend-dad-full-time-heart</link>
            <guid>https://garden.liwen.studio/blog/weekend-dad-full-time-heart</guid>
            <pubDate>Sun, 03 May 2026 11:37:41 GMT</pubDate>
            <description><![CDATA[記錄新手爸爸在公司、月子中心與家庭間奔波的『三棲戰士』生活，並探討長輩傳統育兒觀點與現代護理觀念間的摩擦與反思。]]></description>
            <content:encoded><![CDATA[<p>小夕終於出月中了！回顧這一個月，日子過得既疲憊又充實，還充滿了各種「驚喜」。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="三棲戰士的日常">三棲戰士的日常<a href="https://garden.liwen.studio/blog/weekend-dad-full-time-heart#%E4%B8%89%E6%A3%B2%E6%88%B0%E5%A3%AB%E7%9A%84%E6%97%A5%E5%B8%B8" class="hash-link" aria-label="三棲戰士的日常的直接連結" title="三棲戰士的日常的直接連結" translate="no">​</a></h2>
<p>這段時間，我成了名副其實的「三棲戰士」：<br>
<!-- -->每天在公司、月中、家裡三個點之間來回奔波，除了要應付公司裡的煩心事，還要抓緊時間學習育兒技能。</p>
<!-- -->
<p>雖然累到快被疲勞轟炸，但收穫也很多——從怎麼餵奶、洗澡，到解讀寶寶的需求，這些都是以前難以想像的挑戰。</p>
<p>以前總覺得玩別人的小孩很簡單，自己動手才發現：要照顧好一個生命真的好難。看著小夕喝完奶扭來扭去不睡覺，到底是要換尿布還是沒吃飽？每一組肢體動作都是密碼，雖然燒腦，但也很有趣。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="出月中後的挑戰">出月中後的挑戰<a href="https://garden.liwen.studio/blog/weekend-dad-full-time-heart#%E5%87%BA%E6%9C%88%E4%B8%AD%E5%BE%8C%E7%9A%84%E6%8C%91%E6%88%B0" class="hash-link" aria-label="出月中後的挑戰的直接連結" title="出月中後的挑戰的直接連結" translate="no">​</a></h2>
<p>然而，挑戰才剛開始，出月中後我們即將面臨暫時的分隔。<br>
<!-- -->因為規劃的關係，小夕要回台北長住，我也正式進入「假日爸爸」的模式。想到這裡難免有些感傷，但在這轉換的過程中，我更深刻體會到：<strong>育兒觀念的碰撞，才是最考驗人的修行。</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="與岳母的育兒觀念差異">與岳母的育兒觀念差異<a href="https://garden.liwen.studio/blog/weekend-dad-full-time-heart#%E8%88%87%E5%B2%B3%E6%AF%8D%E7%9A%84%E8%82%B2%E5%85%92%E8%A7%80%E5%BF%B5%E5%B7%AE%E7%95%B0" class="hash-link" aria-label="與岳母的育兒觀念差異的直接連結" title="與岳母的育兒觀念差異的直接連結" translate="no">​</a></h2>
<p>我岳母是一位專業保母，領有證照，最近剛帶完一對雙胞胎，本來打算進入退休生活，剛好小夕「報到」，讓她的退休生活一點都不無聊。</p>
<p>但也因為長輩有著深厚的「實戰經驗」，讓我們在月中學到的現代護理觀念，面臨了前所未有的挑戰：</p>
<ol>
<li class="">
<p><strong>痱子粉才是萬能，屁屁膏都是化學？</strong><br>
<!-- -->關於屁屁護理，岳母堅持使用她那「加了中藥、比較天然」的痱子粉，直接拒絕了我們準備的屁屁膏。</p>
</li>
<li class="">
<p><strong>母奶至上，配方奶是外道？</strong><br>
<!-- -->在月中時，因為小夕便便次數過多，醫生建議先換無乳糖配方奶觀察。沒想到一回台北，岳母立刻下令「全面改回母奶」，甚至認為寶寶拉肚子是因為媽媽亂吃（完全無視月中營養師配過的月子餐，她一直覺得月子餐沒她煮的補）。</p>
</li>
<li class="">
<p><strong>乳液有害論：洗完澡擦乳液？我都沒在用的</strong><br>
<!-- -->建議洗澡後幫寶寶塗個乳液，換來的是一句：「我帶過這麼多小孩都沒在擦，那都是化學的東西，對小孩不好。」聽得我只能乾笑。</p>
</li>
<li class="">
<p><strong>肥皂絕對優於沐浴乳</strong><br>
<!-- -->岳母拿出一塊肥皂要我帶回家，強調她都用這個洗，還嫌棄我們買的沐浴產品。<br>
<!-- -->我提醒她：「肥皂裡有香精，小夕現在不適合碰。」她卻回我：「但這是嬰兒專用的啊！」<br>
<!-- -->我只好無奈反擊：「我的乳液也是嬰兒用的啊...」最後只能在尷尬中不了了之。</p>
</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="心情與期待">心情與期待<a href="https://garden.liwen.studio/blog/weekend-dad-full-time-heart#%E5%BF%83%E6%83%85%E8%88%87%E6%9C%9F%E5%BE%85" class="hash-link" aria-label="心情與期待的直接連結" title="心情與期待的直接連結" translate="no">​</a></h2>
<p>老實說，心裡真的很不爽，但礙於對方是長輩又是幫忙帶小孩，真的難以言說。<br>
<!-- -->我打算先冷靜觀察一週，看看寶寶適應的情況。</p>
<hr>
<p><strong>小夕，你要撐住啊！爸爸下禮拜就去接你。</strong></p>]]></content:encoded>
            <category>育兒</category>
            <category>生活紀錄</category>
            <category>心理成長</category>
        </item>
        <item>
            <title><![CDATA[Vibe Coding 很爽，但別讓 AI 隱藏的「安全地雷」毀掉你的產品]]></title>
            <link>https://garden.liwen.studio/blog/ai-vibe-coding</link>
            <guid>https://garden.liwen.studio/blog/ai-vibe-coding</guid>
            <pubDate>Thu, 23 Apr 2026 05:10:26 GMT</pubDate>
            <description><![CDATA[探討 AI 輔助開發（Vibe Coding）帶來的安全風險，包含 API Key 洩漏、SQL 注入與部署安全等實戰保命指南。]]></description>
            <content:encoded><![CDATA[
<p>最近開發圈最迷人的詞莫過於 <strong>Vibe Coding</strong>——打幾句話，看著 AI 幫你把功能生出來，測試沒問題就光速部署。以前要花好幾天的專案，現在一個下午就能搞定。</p>
<p>說真的，這種「腦力即產力」的感覺非常爽。但就在這種高速生產的流程中，我注意到了一個隱形危機：<strong>流程太順了，順到讓我們忘記了身為開發者最基本的「防禦本能」。</strong></p>
<p><code>{</code>/* truncate */<code>}</code></p>
<p>如果你也熱衷於 Vibe Coding，這篇「保命指南」你一定要加入收藏。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-第一關你的-api-key正在-github-上裸奔嗎">🛑 第一關：你的 API Key，正在 GitHub 上裸奔嗎？<a href="https://garden.liwen.studio/blog/ai-vibe-coding#-%E7%AC%AC%E4%B8%80%E9%97%9C%E4%BD%A0%E7%9A%84-api-key%E6%AD%A3%E5%9C%A8-github-%E4%B8%8A%E8%A3%B8%E5%A5%94%E5%97%8E" class="hash-link" aria-label="🛑 第一關：你的 API Key，正在 GitHub 上裸奔嗎？的直接連結" title="🛑 第一關：你的 API Key，正在 GitHub 上裸奔嗎？的直接連結" translate="no">​</a></h2>
<p>這是最常見、也最容易導致「信用卡刷爆」的失誤。</p>
<p>當你叫 AI 快速串接 OpenAI 或 Stripe API 時，它生成的範例程式碼為了讓你直接跑通，往往會長這樣：</p>
<div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)">/* ⚠️ 這是自殺式寫法：千萬別學 */</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">const</span><span class="token plain"> openai </span><span class="token operator">=</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">new</span><span class="token plain"> </span><span class="token class-name">OpenAI</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">  </span><span class="token literal-property property">apiKey</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"sk-proj-xxxxxxxxxxxxxxxxxxxxxxxx"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// AI 為了方便，直接幫你填在這裡了</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">;</span><br></div></code></pre></div></div>
<p>如果你直接 <code>git push</code> 上 GitHub，不到一分鐘，全世界的爬蟲機器人都會拿到你的金鑰，開始瘋狂盜刷。</p>
<blockquote>
<p>[!WARNING]
<strong>緊急救援：</strong> 如果金鑰已經 push 出去，請第一時間去後台 <strong>廢掉 (Rotate) 那支 Key</strong>！「刪掉 commit」是救不了你的，因為 Git 的歷史紀錄會永遠留存。</p>
</blockquote>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="-正確的優雅姿勢">✅ 正確的優雅姿勢：<a href="https://garden.liwen.studio/blog/ai-vibe-coding#-%E6%AD%A3%E7%A2%BA%E7%9A%84%E5%84%AA%E9%9B%85%E5%A7%BF%E5%8B%A2" class="hash-link" aria-label="✅ 正確的優雅姿勢：的直接連結" title="✅ 正確的優雅姿勢：的直接連結" translate="no">​</a></h3>
<p>請把金鑰放進 <code>.env</code> 檔案，並嚴格檢查你的 <code>.gitignore</code>。</p>
<p>如果你的專案規模較大，強烈建議改用 <strong><a href="https://infisical.com/" target="_blank" rel="noopener noreferrer" class="">Infisical</a></strong> 或 <strong><a href="https://aws.amazon.com/secrets-manager/" target="_blank" rel="noopener noreferrer" class="">AWS Secrets Manager</a></strong> 這種專門的加密管理平台，這能讓你即便不小心洩漏了環境變數檔案，金鑰依然安全無虞。</p>
<blockquote>
<p>[!TIP]
<strong>Next.js 警語：</strong> 千萬別在私密金鑰前綴加上 <code>NEXT_PUBLIC_</code>，否則它會被打包進前端。到時候讀者只要按一下 F12，你的私鑰就會直接在瀏覽器裡跟你招手。</p>
</blockquote>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="️-第二關ai-只管功能它不會主動擋壞人">🛡️ 第二關：AI 只管功能，它不會主動「擋壞人」<a href="https://garden.liwen.studio/blog/ai-vibe-coding#%EF%B8%8F-%E7%AC%AC%E4%BA%8C%E9%97%9Cai-%E5%8F%AA%E7%AE%A1%E5%8A%9F%E8%83%BD%E5%AE%83%E4%B8%8D%E6%9C%83%E4%B8%BB%E5%8B%95%E6%93%8B%E5%A3%9E%E4%BA%BA" class="hash-link" aria-label="🛡️ 第二關：AI 只管功能，它不會主動「擋壞人」的直接連結" title="🛡️ 第二關：AI 只管功能，它不會主動「擋壞人」的直接連結" translate="no">​</a></h2>
<p>AI 的天性是「解決問題」，它不太會主動考慮到「被惡搞的場景」。例如一個簡單的資料庫查詢，AI 可能會給你這樣的 code：</p>
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># 經典的 SQL 注入溫床</span><span class="token plain"></span><br></div><div class="token-line" style="color:#F8F8F2"><span class="token plain">db</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">execute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">f"INSERT INTO notes VALUES ('</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token string-interpolation interpolation">user_input_text</span><span class="token string-interpolation interpolation punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token string-interpolation string" style="color:rgb(255, 121, 198)">')"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></div></code></pre></div></div>
<p>這在資安領域叫做 <strong>SQL Injection</strong>。只要有人輸入一句特殊的代碼，你的整個資料庫內容可能就會被洗劫一空。</p>
<p><strong>Vibe Coder 必須建立的習慣：</strong></p>
<ul>
<li class=""><strong>不信任任何輸入</strong>：永遠檢查使用者傳過來的文字。</li>
<li class=""><strong>限制頻率 (Rate Limiting)</strong>：如果有人寫個迴圈狂灌你的 API，你的帳單會比你的程式碼跑得快。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-第三關部署後的隱形後門">🔍 第三關：部署後的「隱形後門」<a href="https://garden.liwen.studio/blog/ai-vibe-coding#-%E7%AC%AC%E4%B8%89%E9%97%9C%E9%83%A8%E7%BD%B2%E5%BE%8C%E7%9A%84%E9%9A%B1%E5%BD%A2%E5%BE%8C%E9%96%80" class="hash-link" aria-label="🔍 第三關：部署後的「隱形後門」的直接連結" title="🔍 第三關：部署後的「隱形後門」的直接連結" translate="no">​</a></h2>
<p>現代部署平台（如 Vercel, Railway）讓上線變得太簡單。但簡單的背後，這兩個地方最容易踩雷：</p>
<ol>
<li class=""><strong>Debug 模式忘了關</strong>：開著 Debug 模式上線，就像是把家裡的平面圖與保險箱密碼貼在大門口。它會把檔案路徑、環境變數詳細地報給使用者（和駭客）看。</li>
<li class=""><strong>資料庫公開存取</strong>：Supabase 或 Firebase 預設為了方便開發，有時會開放權限。<strong>上線前請務必檢查 Row Level Security (RLS)</strong>，確保那是鎖好的。</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-vibe-coder-的安全百寶箱">🧰 Vibe Coder 的安全百寶箱<a href="https://garden.liwen.studio/blog/ai-vibe-coding#-vibe-coder-%E7%9A%84%E5%AE%89%E5%85%A8%E7%99%BE%E5%AF%B6%E7%AE%B1" class="hash-link" aria-label="🧰 Vibe Coder 的安全百寶箱的直接連結" title="🧰 Vibe Coder 的安全百寶箱的直接連結" translate="no">​</a></h2>
<p>為了讓你安心地「Vibe」，建議在工作流中加入這幾位「自動化保鏢」：</p>
<ul>
<li class=""><strong><a href="https://github.com/trufflesecurity/trufflehog" target="_blank" rel="noopener noreferrer" class="">Trufflehog (金鑰獵人)</a></strong>：專門掃描你的 Git 歷史，翻出那些被你遺忘在舊版本裡的秘密。</li>
<li class=""><strong><a href="https://snyk.io/" target="_blank" rel="noopener noreferrer" class="">Snyk (套件漏洞雷達)</a></strong> / <strong><a href="https://github.com/dependabot" target="_blank" rel="noopener noreferrer" class="">Dependabot</a></strong>：GitHub 內建或外掛。它們會監控你的套件庫，發現漏洞時會直接發一個 PR 幫你修好。</li>
<li class=""><strong><a href="https://github.com/gitleaks/gitleaks" target="_blank" rel="noopener noreferrer" class="">Gitleaks</a></strong>：這是最後一道防線，如果你想在本地端攔截失誤，它可以在你 <code>commit</code> 的那一刻阻止你把 Key 傳出去。</li>
<li class=""><strong><a href="https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning" target="_blank" rel="noopener noreferrer" class="">GitHub Secret Scanning</a></strong>：GitHub 官方內建的強大功能，能第一時間阻斷洩漏。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="-總結快雖好但安全不能省">💡 總結：快雖好，但安全不能省<a href="https://garden.liwen.studio/blog/ai-vibe-coding#-%E7%B8%BD%E7%B5%90%E5%BF%AB%E9%9B%96%E5%A5%BD%E4%BD%86%E5%AE%89%E5%85%A8%E4%B8%8D%E8%83%BD%E7%9C%81" class="hash-link" aria-label="💡 總結：快雖好，但安全不能省的直接連結" title="💡 總結：快雖好，但安全不能省的直接連結" translate="no">​</a></h2>
<p>Vibe Coding 讓每個人都能成為「數位創作者」，這是一場民主化革命。但這也代表，以前工程師才會碰到的炸彈，現在我們每個人都要懂得拆。</p>
<p><strong>記住這個「安全清單」：</strong></p>
<ol>
<li class=""><strong>金鑰必進 <code>.env</code></strong>，且必須加入 <code>.gitignore</code>。</li>
<li class=""><strong>不信任輸入</strong>，一定要做內容驗證。</li>
<li class=""><strong>確認權限</strong>，上線前關閉 Debug 與資料庫公開權限。</li>
<li class=""><strong>定期檢核</strong>，跑一下 <code>npm audit</code> 看看套件健不健康。</li>
</ol>
<p><em>做產品本來就有風險，但這些低級錯誤不值得你冒險。</em></p>
<hr>]]></content:encoded>
            <category>security</category>
            <category>ai</category>
        </item>
        <item>
            <title><![CDATA[雲端邊緣的折翼：Next.js 部署到 Cloudflare Pages 的 48 小時奮鬥實錄]]></title>
            <link>https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle</link>
            <guid>https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle</guid>
            <pubDate>Thu, 23 Apr 2026 00:56:25 GMT</pubDate>
            <description><![CDATA[記錄將 Next.js 應用從 Vercel 遷移至 Cloudflare Pages 的挑戰，深入分析 Edge Runtime 的 3MB 腳本限制、SDK 體積優化與 Node.js API 相容性問題。]]></description>
            <content:encoded><![CDATA[<p>在 Web 開發的世界裡，我們通常會從 Vercel 開始。它很美、很快、很有質感，就像是一個精心裝潢的豪華公寓。但隨著專案成長，我們開始在想：有沒有那種既能擁有極致性能，成本又更平易近人的「自由之地」？</p>
<p>於是，我們把目光投向了 Cloudflare。這兩天，我們就像是一群試圖帶著行李從 Vercel 搬家到 Cloudflare 邊緣計算之城的旅人。雖然最終我們因為行李太重而暫時撤退，但這場「失敗」留下的經驗教訓，或許比成功搬家更值得記錄。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="為什麼想告別-vercel擁抱-cloudflare">為什麼想告別 Vercel，擁抱 Cloudflare？<a href="https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle#%E7%82%BA%E4%BB%80%E9%BA%BC%E6%83%B3%E5%91%8A%E5%88%A5-vercel%E6%93%81%E6%8A%B1-cloudflare" class="hash-link" aria-label="為什麼想告別 Vercel，擁抱 Cloudflare？的直接連結" title="為什麼想告別 Vercel，擁抱 Cloudflare？的直接連結" translate="no">​</a></h2>
<p>LiwenBlog CMS 雖然目前在 Vercel 運行良好，但我們心中一直有個「邊緣夢」：</p>
<ol>
<li class=""><strong>打破流量焦慮</strong>：Vercel 的商業方案雖然強大，但對於個人或小型工作室來說，Cloudflare Pages 那近乎無限的請求數和更透明的成本結構更具吸引力。</li>
<li class=""><strong>追求「真正的」邊緣</strong>：我們希望在離使用者最近的地方（Edge Runtime）處理資料，讓部落格的每一毫秒都能被節省下來。</li>
<li class=""><strong>技術棧的終極整合</strong>：既然我們的數據庫在 Supabase，如果能把 Next.js 也放在 Cloudflare 上，就能構建出一個完全去中心化、高性能的世界級技術棧。</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="撞上那一堵牆數字背後的物理極限">撞上那一堵牆：數字背後的物理極限<a href="https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle#%E6%92%9E%E4%B8%8A%E9%82%A3%E4%B8%80%E5%A0%B5%E7%89%86%E6%95%B8%E5%AD%97%E8%83%8C%E5%BE%8C%E7%9A%84%E7%89%A9%E7%90%86%E6%A5%B5%E9%99%90" class="hash-link" aria-label="撞上那一堵牆：數字背後的物理極限的直接連結" title="撞上那一堵牆：數字背後的物理極限的直接連結" translate="no">​</a></h2>
<p>這場失敗的核心原因，可以總結成一組冷冰冰但現實的數字：<strong>3MB 與 25MB</strong>。</p>
<p>在 Cloudflare Pages / Workers 的環境下，有兩個我們無法迴避的硬指標：</p>
<ol>
<li class=""><strong>單一腳本限制 (3MB)</strong>：每個 Worker 的腳本大小（未壓縮）不能超過 3MB。當我們使用 <code>@opennextjs/cloudflare</code> 將 Next.js 編譯後，最重要的伺服器端邏輯（包括那些重型的 SDK）都會被打包進這個單一文件中。</li>
<li class=""><strong>全專案總合限制 (25MB)</strong>：如果你使用的是免費版，整個專案的靜態資產與腳本總合也有 25MB 的上限。對於一個內建了大量視覺組件與第三方庫的「旗艦版」CMS 來說，這個數字比想像中更脆弱。</li>
</ol>
<p>雖然 <strong>付費版 (Paid/Standard)</strong> 可以將單一腳本限制放寬到 <strong>10MB</strong>，但這通常意味著你需要每個月支付額外的費用，且依然要面對代碼膨脹導致的冷啟動（Cold Start）延遲問題。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-環境的基因差異-the-vercel-lock-in">3. 環境的基因差異 (The Vercel Lock-in)<a href="https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle#3-%E7%92%B0%E5%A2%83%E7%9A%84%E5%9F%BA%E5%9B%A0%E5%B7%AE%E7%95%B0-the-vercel-lock-in" class="hash-link" aria-label="3. 環境的基因差異 (The Vercel Lock-in)的直接連結" title="3. 環境的基因差異 (The Vercel Lock-in)的直接連結" translate="no">​</a></h3>
<p>除了數字上的限制，我們更深刻感受到的是「基因」的不同。Next.js 作為 Vercel 的親兒子，其 App Router 的許多行為本質上是為其原生平台量身打造的。搬家到 Cloudflare 不只是換個伺服器，更是一場「去 Vercel 化」的架構重構，這種框架與平台間的深度耦合，讓我們在遷移過程中如履薄冰。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-sdk-的重量">1. SDK 的重量<a href="https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle#1-sdk-%E7%9A%84%E9%87%8D%E9%87%8F" class="hash-link" aria-label="1. SDK 的重量的直接連結" title="1. SDK 的重量的直接連結" translate="no">​</a></h3>
<p>我們的應用中包含了一些功能強大但也「沉重」的工具：</p>
<ul>
<li class=""><strong>Shiki</strong>: 用於極致的代碼高亮。</li>
<li class=""><strong>React-Markdown / Rehype</strong>: 用於處理內容渲染。</li>
<li class=""><strong>Resend</strong>: 郵件服務。</li>
<li class=""><strong>Supabase SDK</strong>: 數據庫交互的核心。</li>
</ul>
<p>在 Vercel 上，這些 SDK 運行在 Node.js 環境中，幾乎沒有大小限制。但在 Cloudflare Edge 環境下，所有這些都必須塞進那個小小的 Worker 腳本裡。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-環境適應不良-nodejs-vs-edge-runtime">2. 環境適應不良 (Node.js vs Edge Runtime)<a href="https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle#2-%E7%92%B0%E5%A2%83%E9%81%A9%E6%87%89%E4%B8%8D%E8%89%AF-nodejs-vs-edge-runtime" class="hash-link" aria-label="2. 環境適應不良 (Node.js vs Edge Runtime)的直接連結" title="2. 環境適應不良 (Node.js vs Edge Runtime)的直接連結" translate="no">​</a></h3>
<p>Next.js 許多方便的功能（如某些特定模組的伺服器端渲染）依賴於完整的 Node.js API，而 Cloudflare 的 Edge Runtime 則是基於 V8 的受限環境。雖然 <code>open-next</code> 已經做了很多努力，但要讓整個 App 完美適應，需要大量的重構。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="我們嘗試過的解決方案那些我們走過的彎路">我們嘗試過的解決方案（那些我們走過的彎路）<a href="https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle#%E6%88%91%E5%80%91%E5%98%97%E8%A9%A6%E9%81%8E%E7%9A%84%E8%A7%A3%E6%B1%BA%E6%96%B9%E6%A1%88%E9%82%A3%E4%BA%9B%E6%88%91%E5%80%91%E8%B5%B0%E9%81%8E%E7%9A%84%E5%BD%8E%E8%B7%AF" class="hash-link" aria-label="我們嘗試過的解決方案（那些我們走過的彎路）的直接連結" title="我們嘗試過的解決方案（那些我們走過的彎路）的直接連結" translate="no">​</a></h2>
<p>雖然結果是失敗，但我們嘗試了所有能想到的優化手段：</p>
<ol>
<li class="">
<p><strong>動態導入 (Dynamic Imports)</strong>：
我們嘗試將重型的組件（如語法高亮的編輯器）改為 <code>next/dynamic</code> 僅在客戶端載入。這確實減小了 Server-side 的壓力，但對於某些強依賴服務端邏輯的頁面，優化空間依然有限。</p>
</li>
<li class="">
<p><strong>SDK 脫水 (SDK Stripping)</strong>：
我們嘗試移除某些非核心的重型 SDK，改用更輕量（但功能較少）的替代品。但對於追求「旗艦體驗」的我們來說，這種權衡（Trade-off）降低了產品的質感。</p>
</li>
<li class="">
<p><strong>OpenNext 精確配置</strong>：
調整 <code>open-next.config</code> 來排除某些不必要的 chunks，但 Next.js App Router 的構建邏輯有時像個黑盒子，難以精確拆分。</p>
</li>
<li class="">
<p><strong>與「看不見」的細節對抗</strong>：
我們在環境變數（Secrets）的遷移和 <strong>圖片優化 (next/image)</strong> 的配置上也耗費了大量心力。在 Vercel 點點介面就能搞定的事，在 Cloudflare 需要透過 <code>wrangler.toml</code> 重新佈署，甚至要額外建立 R2 儲存桶來支撐圖片處理。</p>
</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="給下一個挑戰者的-3-個建議">給下一個挑戰者的 3 個建議<a href="https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle#%E7%B5%A6%E4%B8%8B%E4%B8%80%E5%80%8B%E6%8C%91%E6%88%B0%E8%80%85%E7%9A%84-3-%E5%80%8B%E5%BB%BA%E8%AD%B0" class="hash-link" aria-label="給下一個挑戰者的 3 個建議的直接連結" title="給下一個挑戰者的 3 個建議的直接連結" translate="no">​</a></h2>
<p>如果你也正打算將 Next.js 應用部署到 Cloudflare，請務必先確認以下事項：</p>
<ol>
<li class=""><strong>模組化你的依賴</strong>：在引入任何庫（Library）之前，先去 <a href="https://bundlephobia.com/" target="_blank" rel="noopener noreferrer" class="">BundlePhobia</a> 看看它的體積。</li>
<li class=""><strong>優先考慮 Edge-first</strong>：從開發第一天起就以 Edge Runtime 為基準。如果你是到了開發中後期才決定切換環境，那代價可能會非常沉重。</li>
<li class=""><strong>功能權衡</strong>：如果你的應用需要大量重型的 SSR 渲染或依賴傳統 Node.js 庫，那麼 Vercel 或 Netlify 或許才是你更溫暖的家。</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="結語失敗是另一種形式的累積">結語：失敗是另一種形式的累積<a href="https://garden.liwen.studio/blog/nextjs-deployment-cloudflare-pages-struggle#%E7%B5%90%E8%AA%9E%E5%A4%B1%E6%95%97%E6%98%AF%E5%8F%A6%E4%B8%80%E7%A8%AE%E5%BD%A2%E5%BC%8F%E7%9A%84%E7%B4%AF%E7%A9%8D" class="hash-link" aria-label="結語：失敗是另一種形式的累積的直接連結" title="結語：失敗是另一種形式的累積的直接連結" translate="no">​</a></h2>
<p>雖然這次部署失敗了，但我們對於 LiwenBlog CMS 的性能邊界有了更深刻的認識。有些美是需要空間支撐的，而 Cloudflare 的邊緣計算目前更像是一個「精而小」的藝術館，不適合塞進所有的東西。</p>
<p>我們回到了熟悉的環境，繼續打磨我們的產品。下次再挑戰時，我們會帶著更精簡、更具適應性的代碼再次出發。</p>]]></content:encoded>
            <category>cloudflare</category>
            <category>NextJs</category>
            <category>雲端部署</category>
        </item>
        <item>
            <title><![CDATA[冒名頂替症候群 (Imposter Syndrome) 深度解析]]></title>
            <link>https://garden.liwen.studio/blog/imposter-syndrome</link>
            <guid>https://garden.liwen.studio/blog/imposter-syndrome</guid>
            <pubDate>Tue, 21 Apr 2026 06:46:36 GMT</pubDate>
            <description><![CDATA[深入探討冒名頂替症候群的定義、五種類型以及實用的心態調整方式，幫助開發者克服內心不安，建立穩健的專業自信。]]></description>
            <content:encoded><![CDATA[
<p><a href="https://gemini.google.com/share/419d34c2d3f6" target="_blank" rel="noopener noreferrer" class="">互動網站</a></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="一-定義什麼是冒名頂替症候群">一、 定義：什麼是冒名頂替症候群？<a href="https://garden.liwen.studio/blog/imposter-syndrome#%E4%B8%80-%E5%AE%9A%E7%BE%A9%E4%BB%80%E9%BA%BC%E6%98%AF%E5%86%92%E5%90%8D%E9%A0%82%E6%9B%BF%E7%97%87%E5%80%99%E7%BE%A4" class="hash-link" aria-label="一、 定義：什麼是冒名頂替症候群？的直接連結" title="一、 定義：什麼是冒名頂替症候群？的直接連結" translate="no">​</a></h2>
<p>冒名頂替症候群最早由心理學家 <strong>Pauline Clance</strong> 與 <strong>Suzanne Imes</strong> 於 1978 年提出。它並非一種精神疾病，而是一種<strong>心理現象</strong>。</p>
<ul>
<li class=""><strong>核心特徵：</strong> 個體無法將自己的成功歸因於能力，儘管有外部證據（如證書、好評、晉升），仍深信自己是「騙子」，認為成功只是因為運氣、時機或誤導了他人。</li>
<li class=""><strong>心理運作：</strong> 這種焦慮通常伴隨著「害怕被拆穿」的恐懼，覺得自己不配擁有目前的地位。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="二-常見的情況與徵兆">二、 常見的情況與徵兆<a href="https://garden.liwen.studio/blog/imposter-syndrome#%E4%BA%8C-%E5%B8%B8%E8%A6%8B%E7%9A%84%E6%83%85%E6%B3%81%E8%88%87%E5%BE%B5%E5%85%86" class="hash-link" aria-label="二、 常見的情況與徵兆的直接連結" title="二、 常見的情況與徵兆的直接連結" translate="no">​</a></h2>
<p>你可以對照以下表格，檢視自己是否有相關的心理感受：</p>
<table><thead><tr><th style="text-align:left">情況</th><th style="text-align:left">內心獨白示例</th><th style="text-align:left">行為表現</th></tr></thead><tbody><tr><td style="text-align:left"><strong>過度準備</strong></td><td style="text-align:left">「我必須比別人多花三倍時間準備，否則一定會搞砸。」</td><td style="text-align:left">容易導致精疲力竭 (Burnout)。</td></tr><tr><td style="text-align:left"><strong>忽視成就</strong></td><td style="text-align:left">「那份報告會成功只是因為主管心情好，沒什麼了不起。」</td><td style="text-align:left">將成功過度歸因於運氣或他人因素。</td></tr><tr><td style="text-align:left"><strong>害怕挑戰</strong></td><td style="text-align:left">「如果我接下這個新專案，大家就會發現我其實什麼都不懂。」</td><td style="text-align:left">為了避免曝露「無能」而逃避晉升機會。</td></tr><tr><td style="text-align:left"><strong>社交退縮</strong></td><td style="text-align:left">在厲害的人身邊不敢發言，擔心說錯話會顯露無知。</td><td style="text-align:left">隱藏真實觀點，僅採取安全的回應。</td></tr><tr><td style="text-align:left"><strong>完美主義</strong></td><td style="text-align:left">「只要有一點小錯誤，就覺得自己之前的努力全都白費了。」</td><td style="text-align:left">對自我評價極端，難以容忍合理的錯誤。</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="三-進階補充五種冒名頂替者類型-the-5-types">三、 進階補充：五種冒名頂替者類型 (The 5 Types)<a href="https://garden.liwen.studio/blog/imposter-syndrome#%E4%B8%89-%E9%80%B2%E9%9A%8E%E8%A3%9C%E5%85%85%E4%BA%94%E7%A8%AE%E5%86%92%E5%90%8D%E9%A0%82%E6%9B%BF%E8%80%85%E9%A1%9E%E5%9E%8B-the-5-types" class="hash-link" aria-label="三、 進階補充：五種冒名頂替者類型 (The 5 Types)的直接連結" title="三、 進階補充：五種冒名頂替者類型 (The 5 Types)的直接連結" translate="no">​</a></h2>
<p>根據 Valerie Young 的研究，冒名頂替症候群可以細分為五種典型，了解自己屬於哪一類有助於更精準地調整心態：</p>
<ol>
<li class=""><strong>完美主義者 (The Perfectionist)：</strong> 設定過高目標，即便達成 99% 仍會為了 1% 的瑕疵感到失敗。</li>
<li class=""><strong>超人 (The Superhuman)：</strong> 試圖在工作、家庭、社交等所有領域都達到頂尖，以此掩飾內心的不安。</li>
<li class=""><strong>天生天才 (The Natural Genius)：</strong> 習慣於迅速掌握新事物，若遇到需要努力苦練才能學會的事，會覺得自己「沒天賦、是騙子」。</li>
<li class=""><strong>獨行俠 (The Soloist)：</strong> 認為必須獨立完成所有事，請求幫助在他們眼中等同於「無能」。</li>
<li class=""><strong>專家 (The Expert)：</strong> 永遠覺得自己懂的不夠多，即便已非常有經驗，仍會不斷瘋狂進修以求安全感。</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="四-實用的解決方式">四、 實用的解決方式<a href="https://garden.liwen.studio/blog/imposter-syndrome#%E5%9B%9B-%E5%AF%A6%E7%94%A8%E7%9A%84%E8%A7%A3%E6%B1%BA%E6%96%B9%E5%BC%8F" class="hash-link" aria-label="四、 實用的解決方式的直接連結" title="四、 實用的解決方式的直接連結" translate="no">​</a></h2>
<p>克服此症候群並非要「消除」感覺，而是學習與之共處，並減少它對行動的阻礙。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-區分感覺與事實">1. 區分「感覺」與「事實」<a href="https://garden.liwen.studio/blog/imposter-syndrome#1-%E5%8D%80%E5%88%86%E6%84%9F%E8%A6%BA%E8%88%87%E4%BA%8B%E5%AF%A6" class="hash-link" aria-label="1. 區分「感覺」與「事實」的直接連結" title="1. 區分「感覺」與「事實」的直接連結" translate="no">​</a></h3>
<p>這是最重要的第一步。</p>
<ul>
<li class=""><strong>感覺：</strong> 「我覺得自己很弱，大家都在笑我。」</li>
<li class=""><strong>事實：</strong> 「我準時提交了專案，且目前沒有收到任何負面反饋。」</li>
<li class=""><strong>行動：</strong> 當焦慮來襲，試著寫下負面情緒，並在旁邊列出客觀數據來反駁。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-建立成就紀錄本-the-brag-document">2. 建立「成就紀錄本」 (The Brag Document)<a href="https://garden.liwen.studio/blog/imposter-syndrome#2-%E5%BB%BA%E7%AB%8B%E6%88%90%E5%B0%B1%E7%B4%80%E9%8C%84%E6%9C%AC-the-brag-document" class="hash-link" aria-label="2. 建立「成就紀錄本」 (The Brag Document)的直接連結" title="2. 建立「成就紀錄本」 (The Brag Document)的直接連結" translate="no">​</a></h3>
<p>人的大腦有「負面偏向」，容易忘記成功。</p>
<ul>
<li class=""><strong>記錄內容：</strong> 解決過的難題、學會的新技能、獲得的讚賞。</li>
<li class=""><strong>作用：</strong> 當你懷疑自己時，翻開紀錄，讓過去的成就成為現在的後盾。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-與他人分享感受">3. 與他人分享感受<a href="https://garden.liwen.studio/blog/imposter-syndrome#3-%E8%88%87%E4%BB%96%E4%BA%BA%E5%88%86%E4%BA%AB%E6%84%9F%E5%8F%97" class="hash-link" aria-label="3. 與他人分享感受的直接連結" title="3. 與他人分享感受的直接連結" translate="no">​</a></h3>
<p>冒名頂替症候群在「沈默」中長得最快。</p>
<ul>
<li class=""><strong>破除神話：</strong> 當你發現身邊的「大神」也會感到焦慮時，壓力會大幅減輕。</li>
<li class=""><strong>尋找導師：</strong> 與信任的 Mentor 分享，從客觀第三者的視角重新評估你的價值。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="4-重新定義失敗擁抱成長型思維">4. 重新定義失敗：擁抱「成長型思維」<a href="https://garden.liwen.studio/blog/imposter-syndrome#4-%E9%87%8D%E6%96%B0%E5%AE%9A%E7%BE%A9%E5%A4%B1%E6%95%97%E6%93%81%E6%8A%B1%E6%88%90%E9%95%B7%E5%9E%8B%E6%80%9D%E7%B6%AD" class="hash-link" aria-label="4. 重新定義失敗：擁抱「成長型思維」的直接連結" title="4. 重新定義失敗：擁抱「成長型思維」的直接連結" translate="no">​</a></h3>
<ul>
<li class="">將「我不會」改為 <strong>「我還沒學會」</strong>。</li>
<li class=""><strong>核心價值：</strong> 專業人士的價值不在於無所不知，而在於<strong>具備找到答案的能力</strong>。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="5-檢視環境因素-補充">5. 檢視環境因素 (補充)<a href="https://garden.liwen.studio/blog/imposter-syndrome#5-%E6%AA%A2%E8%A6%96%E7%92%B0%E5%A2%83%E5%9B%A0%E7%B4%A0-%E8%A3%9C%E5%85%85" class="hash-link" aria-label="5. 檢視環境因素 (補充)的直接連結" title="5. 檢視環境因素 (補充)的直接連結" translate="no">​</a></h3>
<p>有時這種感覺源於「環境」。若身處競爭過激烈或缺乏多元包容性的職場（如少數族裔、女性在傳統男性主導行業），這種心理感會被放大。理解這並非單純個人問題，有助於緩解自我批判。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="來源與參考資料">來源與參考資料<a href="https://garden.liwen.studio/blog/imposter-syndrome#%E4%BE%86%E6%BA%90%E8%88%87%E5%8F%83%E8%80%83%E8%B3%87%E6%96%99" class="hash-link" aria-label="來源與參考資料的直接連結" title="來源與參考資料的直接連結" translate="no">​</a></h2>
<ul>
<li class=""><strong>Clance, P. R., &amp; Imes, S. A. (1978):</strong> <em>The imposter phenomenon in high achieving women: Dynamics and therapeutic intervention.</em></li>
<li class=""><strong>Valerie Young (2011):</strong> <em>The Secret Thoughts of Successful Women.</em></li>
<li class=""><strong>Harvard Business Review:</strong> <a href="https://hbr.org/" target="_blank" rel="noopener noreferrer" class="">Stop Telling Women They Have Imposter Syndrome</a></li>
</ul>]]></content:encoded>
            <category>心理學</category>
            <category>職涯發展</category>
        </item>
        <item>
            <title><![CDATA[工程師評價心理學：從內在計分卡奪回成長主導權]]></title>
            <link>https://garden.liwen.studio/blog/engineer-evaluation-psychology</link>
            <guid>https://garden.liwen.studio/blog/engineer-evaluation-psychology</guid>
            <pubDate>Tue, 21 Apr 2026 06:46:35 GMT</pubDate>
            <description><![CDATA[深入探討工程師在面對職場評價時的心理機制（如生存本能、鏡像自我），並提供建立內在計分卡、自我與代碼解耦的實戰心法。]]></description>
            <content:encoded><![CDATA[<p>互動網站: <a href="https://gemini.google.com/share/6a9569c51762" target="_blank" rel="noopener noreferrer" class="">https://gemini.google.com/share/6a9569c51762</a></p>
<p>這份筆記整理了工程師在職場中面對「評價」時的心理機制、常見行為模式，以及如何建立健康的自我認同體系。</p>
<!-- -->
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="一核心問題為什麼我們如此在意評價">一、核心問題：為什麼我們如此在意評價？<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#%E4%B8%80%E6%A0%B8%E5%BF%83%E5%95%8F%E9%A1%8C%E7%82%BA%E4%BB%80%E9%BA%BC%E6%88%91%E5%80%91%E5%A6%82%E6%AD%A4%E5%9C%A8%E6%84%8F%E8%A9%95%E5%83%B9" class="hash-link" aria-label="一、核心問題：為什麼我們如此在意評價？的直接連結" title="一、核心問題：為什麼我們如此在意評價？的直接連結" translate="no">​</a></h2>
<p>工程師的工作產出（代碼、架構）高度抽象且具備創造性。當產出受到批評時，大腦往往無法區分「對工作的建議」與「對個人的否定」。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="心理學三大根源">心理學三大根源<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#%E5%BF%83%E7%90%86%E5%AD%B8%E4%B8%89%E5%A4%A7%E6%A0%B9%E6%BA%90" class="hash-link" aria-label="心理學三大根源的直接連結" title="心理學三大根源的直接連結" translate="no">​</a></h3>
<ul>
<li class="">
<p><strong>生存本能（Survival Instinct）</strong><br>
<!-- -->在演化過程中，被部落排斥意味著死亡。大腦邊緣系統會將「負面評價」視為物理威脅，觸發皮質醇分泌，導致心跳加速與焦慮。</p>
</li>
<li class="">
<p><strong>鏡像自我（Looking-glass Self）</strong><br>
<!-- -->查爾斯·庫利（Charles Cooley）提出。我們對自己的定義，其實是我們觀察到「別人如何看待我」的投影。評價成了我們確認自身能力的座標。</p>
</li>
<li class="">
<p><strong>社會比較理論（Social Comparison Theory）</strong><br>
<!-- -->利昂·費斯廷格（Leon Festinger）提出。在缺乏絕對標準時，人類傾向透過與同儕比較（如職級、薪資）來定義成功。</p>
</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="二工程師日常生動案例分析">二、工程師日常生動案例分析<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#%E4%BA%8C%E5%B7%A5%E7%A8%8B%E5%B8%AB%E6%97%A5%E5%B8%B8%E7%94%9F%E5%8B%95%E6%A1%88%E4%BE%8B%E5%88%86%E6%9E%90" class="hash-link" aria-label="二、工程師日常生動案例分析的直接連結" title="二、工程師日常生動案例分析的直接連結" translate="no">​</a></h2>
<p>透過具體場景，識別這些心理機制如何影響開發者的行為：</p>
<table><thead><tr><th>案例角色</th><th>核心情境</th><th>心理分析</th></tr></thead><tbody><tr><td><strong>老王的 PR 焦慮</strong></td><td>收到 Request Changes 或「邏輯笨」的評論</td><td>外在計分卡主導。將代碼品質與智力掛鉤，導致防禦心態</td></tr><tr><td><strong>小美的技術債恐懼</strong></td><td>擔心改壞代碼影響「穩重」形象，故不敢重構</td><td>生存本能與社交安全性。為了維持零失誤評價而犧牲技術價值</td></tr><tr><td><strong>阿強的技術焦慮</strong></td><td>盲目引入大廠新框架，追求技術流行</td><td>社會比較理論。在跟「社群幻覺」比較，試圖透過工具換取認可</td></tr><tr><td><strong>大力的救火英雄</strong></td><td>享受半夜第一個修 Bug 的「被需要感」</td><td>效用認可沉迷。成功建立在被需要的頻率，而非長期產出影響力</td></tr><tr><td><strong>曉芬的文檔完美主義</strong></td><td>花費過多時間潤飾文檔，擔心一個錯字毀專業感</td><td>完美主義下的評價權放大。在邊際效益極低的工作上消耗過度</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="三實踐解決方案奪回評價主導權">三、實踐解決方案：奪回評價主導權<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#%E4%B8%89%E5%AF%A6%E8%B8%90%E8%A7%A3%E6%B1%BA%E6%96%B9%E6%A1%88%E5%A5%AA%E5%9B%9E%E8%A9%95%E5%83%B9%E4%B8%BB%E5%B0%8E%E6%AC%8A" class="hash-link" aria-label="三、實踐解決方案：奪回評價主導權的直接連結" title="三、實踐解決方案：奪回評價主導權的直接連結" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="1-建立內在計分卡inner-scorecard">1. 建立「內在計分卡」（Inner Scorecard）<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#1-%E5%BB%BA%E7%AB%8B%E5%85%A7%E5%9C%A8%E8%A8%88%E5%88%86%E5%8D%A1inner-scorecard" class="hash-link" aria-label="1. 建立「內在計分卡」（Inner Scorecard）的直接連結" title="1. 建立「內在計分卡」（Inner Scorecard）的直接連結" translate="no">​</a></h3>
<p>華倫·巴菲特（Warren Buffett）提出的概念。重點在於你是用「自己的標準」還是「別力的標準」來衡量成功。</p>
<ul>
<li class=""><strong>內在指標</strong>：今天的我比三個月前更進步嗎？我解決了真實的問題嗎？</li>
<li class=""><strong>外在指標</strong>：GitHub Stars、主管的評分字母、名片上的頭銜。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="2-自我與代碼的解耦decoupling">2. 自我與代碼的解耦（Decoupling）<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#2-%E8%87%AA%E6%88%91%E8%88%87%E4%BB%A3%E7%A2%BC%E7%9A%84%E8%A7%A3%E8%80%A6decoupling" class="hash-link" aria-label="2. 自我與代碼的解耦（Decoupling）的直接連結" title="2. 自我與代碼的解耦（Decoupling）的直接連結" translate="no">​</a></h3>
<ul>
<li class=""><strong>心態重構</strong>：代碼離開編輯器後，它就是一個獨立的邏輯實體。</li>
<li class=""><strong>定義</strong>：被 Review 的是「代碼的時空複雜度」，而不是「你的人格」。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="3-擁抱凡人化心態">3. 擁抱「凡人化心態」<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#3-%E6%93%81%E6%8A%B1%E5%87%A1%E4%BA%BA%E5%8C%96%E5%BF%83%E6%85%8B" class="hash-link" aria-label="3. 擁抱「凡人化心態」的直接連結" title="3. 擁抱「凡人化心態」的直接連結" translate="no">​</a></h3>
<ul>
<li class="">承認自己也有不懂的地方，這並不會損害資深工程師的威信。</li>
<li class="">主動提問能建立團隊的「心理安全性」，讓溝通回到解決問題的本質。</li>
</ul>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="四總結與座右銘">四、總結與座右銘<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#%E5%9B%9B%E7%B8%BD%E7%B5%90%E8%88%87%E5%BA%A7%E5%8F%B3%E9%8A%98" class="hash-link" aria-label="四、總結與座右銘的直接連結" title="四、總結與座右銘的直接連結" translate="no">​</a></h2>
<blockquote>
<p><strong>「評價是一項工具，而不應是你的主人。」</strong></p>
</blockquote>
<p>當你專注於內在成長時，外部的認可會作為「副產品」自然隨之而來，而不再是你焦慮的源頭。</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="參考來源及進階閱讀">參考來源及進階閱讀<a href="https://garden.liwen.studio/blog/engineer-evaluation-psychology#%E5%8F%83%E8%80%83%E4%BE%86%E6%BA%90%E5%8F%8A%E9%80%B2%E9%9A%8E%E9%96%B1%E8%AE%80" class="hash-link" aria-label="參考來源及進階閱讀的直接連結" title="參考來源及進階閱讀的直接連結" translate="no">​</a></h2>
<ul>
<li class=""><strong>Festinger, L. (1954):</strong> <em>A theory of social comparison processes.</em> （社會比較理論）</li>
<li class=""><strong>Cooley, C. H. (1902):</strong> <em>Human Nature and the Social Order.</em> （鏡像自我理論）</li>
<li class=""><strong>Schroeder, A. (2008):</strong> <em>The Snowball.</em> （巴菲特傳記：內在計分卡概念）</li>
<li class=""><strong>Dweck, C. S. (2006):</strong> <em>Mindset: The New Psychology of Success.</em> （成長型思維）</li>
<li class=""><strong>Brooks, F. P. (1975):</strong> <em>The Mythical Man-Month.</em> （軟體工程心理協作）</li>
</ul>]]></content:encoded>
            <category>心理學</category>
            <category>職涯發展</category>
            <category>工程文化</category>
        </item>
        <item>
            <title><![CDATA[身為全公司的避風港：MIS 的無奈日常與工作邊界感]]></title>
            <link>https://garden.liwen.studio/blog/mis-daily-rant</link>
            <guid>https://garden.liwen.studio/blog/mis-daily-rant</guid>
            <pubDate>Tue, 21 Apr 2026 06:46:35 GMT</pubDate>
            <description><![CDATA[從一場突如其來的亞馬遜賣場求救事件，反思 MIS 職位在職場中被當成『避風港』的依賴心理，並探討如何建立工作邊界與專業所有權 (Ownership)。]]></description>
            <content:encoded><![CDATA[<p>這原本應該是個美好的補眠日。因為前一天沒睡好，索性請了一天假，打算好好充電後，再來專心處理最近一直沒空執行的資訊需求。沒想到，美好的早晨在八點多就被無情打斷。</p>
<!-- -->
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="在最後一刻才求救的亞馬遜賣場事件">在最後一刻才求救的「亞馬遜賣場」事件<a href="https://garden.liwen.studio/blog/mis-daily-rant#%E5%9C%A8%E6%9C%80%E5%BE%8C%E4%B8%80%E5%88%BB%E6%89%8D%E6%B1%82%E6%95%91%E7%9A%84%E4%BA%9E%E9%A6%AC%E9%81%9C%E8%B3%A3%E5%A0%B4%E4%BA%8B%E4%BB%B6" class="hash-link" aria-label="在最後一刻才求救的「亞馬遜賣場」事件的直接連結" title="在最後一刻才求救的「亞馬遜賣場」事件的直接連結" translate="no">​</a></h2>
<p>一大早被吵醒，居然是因為行銷部門今天要開賣場，才發現當初申請的亞馬遜帳號還需要再申請 Seller 的相關認證。這讓我滿頭問號：幾個月前帳號申請完不就已經移交了嗎？為什麼現在還要我來幫忙申請？</p>
<p>如果是我負責一個專案，拿到帳號的第一天，我一定會先登入進去點點看，確認能不能順利開賣場、熟悉一下流程。我實在無法理解，為什麼總是有人喜歡拖到「最後關頭」才在那邊驚慌求救，真的是會讓人理智線斷裂。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="缺東缺西的資料整理">缺東缺西的資料整理<a href="https://garden.liwen.studio/blog/mis-daily-rant#%E7%BC%BA%E6%9D%B1%E7%BC%BA%E8%A5%BF%E7%9A%84%E8%B3%87%E6%96%99%E6%95%B4%E7%90%86" class="hash-link" aria-label="缺東缺西的資料整理的直接連結" title="缺東缺西的資料整理的直接連結" translate="no">​</a></h2>
<p>本來想說直接把這件事放生不理，轉頭準備來專心處理我的資訊需求。結果一打開資料，又是一陣血壓飆升：資料缺東缺西，該連結的資料完全沒有對應起來。</p>
<p>我就問，這不過才 30 幾筆資料而已！操作邏輯不就是點個編輯、在下拉式選單選好分類、然後按下儲存嗎？這困難點到底在哪裡？</p>
<p>結果對方還說要再拉一個人進來確認。到底要確認什麼？介面上全部都是中文字！然後又開始扯說「我的代號跟他們習慣的不一樣」……阿你選下拉選單的時候明明看到的是中文啊，這到底關代號什麼事？</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="mis-不是沒有底線的避風港">MIS 不是沒有底線的「避風港」<a href="https://garden.liwen.studio/blog/mis-daily-rant#mis-%E4%B8%8D%E6%98%AF%E6%B2%92%E6%9C%89%E5%BA%95%E7%B7%9A%E7%9A%84%E9%81%BF%E9%A2%A8%E6%B8%AF" class="hash-link" aria-label="MIS 不是沒有底線的「避風港」的直接連結" title="MIS 不是沒有底線的「避風港」的直接連結" translate="no">​</a></h2>
<p>總之，今天就是充斥著這些令人無語的鳥事。</p>
<p>越想越覺得，待在這裡，我好像不知不覺變成了全公司的「避風港」。彷彿只要跟「電腦、系統、帳號」沾上一點邊，把東西往 MIS 身上一丟，剩下的事情就全部與他們無關了。</p>
<p>這不只是工作技能的差異，更多的是對自己工作業務<strong>缺乏所有權 (Ownership)</strong> 與<strong>責任感</strong>的問題。當每個人都預期「反正出包了、不會用了，最後 MIS 會幫忙擦屁股」，這種依賴心理就會無止盡地蔓延。</p>
<p>是時候重新建立工作上的邊界感了。不能再讓「太好說話」變成別人推卸責任的理由。</p>]]></content:encoded>
            <category>職場</category>
            <category>工程文化</category>
            <category>工作心法</category>
        </item>
    </channel>
</rss>