Skip to content

The Art of Consistent Non-Stupidity

持續不愚蠢的藝術

"It is remarkable how much long-term advantage people like us have gotten by trying to be consistently not stupid, instead of trying to be very intelligent." — Charlie Munger

This quote from Warren Buffett's partner captures a counterintuitive truth: in most domains of life, success comes less from brilliant moves and more from avoiding catastrophic mistakes. This guide explores what "consistent non-stupidity" looks like in frontend development and in life — and how to build systems that make avoiding stupidity automatic.

「嘗試持續不愚蠢,而不是嘗試非常聰明,我們獲得了驚人的長期優勢。」—— Charlie Munger

Warren Buffett 的合夥人的這句話捕捉了一個反直覺的真相:在人生的大多數領域,成功較少來自於精彩的舉動,更多來自於避免災難性的錯誤。本指南探討「持續不愚蠢」在前端開發和人生中是什麼樣子——以及如何建立讓避免愚蠢成為自動化的系統。


1. The Philosophy: Why Non-Stupidity Beats Brilliance

1. 哲學:為什麼不愚蠢勝過聰明

1.1 The Amateur Tennis Principle

In his research on winning strategies, statistician Simon Ramo discovered a profound pattern:

Professional tennis: Points are won through brilliant plays — aces, perfect shots, impossible angles.

Amateur tennis: 80% of points are lost through errors — hitting into the net, out of bounds, double faults.

The implication is profound: In amateur contexts (and most of professional life is amateur), you win by not losing.

This is why tennis coaches teach beginners to keep the ball in play rather than hit perfect serves. Your opponent will beat themselves.

1.2 Charlie Munger's Insight

Munger and Buffett built Berkshire Hathaway into a $700+ billion company not by making brilliant investment picks, but by systematically avoiding:

  • Leverage that could destroy them
  • Investments in industries they didn't understand
  • Management teams with questionable integrity
  • Deals that were "too good to be true"

As Munger put it: "All I want to know is where I'm going to die, so I'll never go there."

1.3 The Asymmetry of Mistakes vs Wins

TypeExamplesRecovery
Small winsGood code review, nice optimizationIncremental progress
Big winsPerfect architecture decisionRare, hard to replicate
Small mistakesMinor bug, typoEasy fix
Big mistakesSecurity breach, data loss, broken productionCareer-defining, sometimes unrecoverable

The asymmetry: Big mistakes can undo years of small wins. One catastrophic error can destroy a reputation built over a decade. But big wins rarely compensate for big mistakes.

The strategy: Spend less time trying to be brilliant and more time trying to avoid obvious stupidity.

1.1 業餘網球原則

統計學家 Simon Ramo 在他對獲勝策略的研究中發現了一個深刻的模式:

專業網球:分數是通過精彩的打法贏得的——發球得分、完美的擊球、不可能的角度。

業餘網球:80% 的分數是因為失誤而輸掉的——打進網、出界、雙發失誤。

這個含義是深刻的:在業餘環境中(而大多數職業生活都是業餘的),你通過不輸來贏。

這就是為什麼網球教練教初學者保持球在場內,而不是打出完美的發球。你的對手會自己打敗自己。

1.2 Charlie Munger 的洞察

Munger 和 Buffett 將 Berkshire Hathaway 建成一家超過 7000 億美元的公司,不是通過做出精彩的投資選擇,而是通過系統性地避免:

  • 可能摧毀他們的槓桿
  • 他們不了解的產業投資
  • 誠信有問題的管理團隊
  • 「好得不像真的」的交易

正如 Munger 所說:「我只想知道我會死在哪裡,這樣我就永遠不會去那裡。」

1.3 錯誤與勝利的不對稱性

類型例子恢復
小勝利好的程式碼審查、不錯的優化漸進式進展
大勝利完美的架構決策罕見、難以複製
小錯誤小 bug、錯字容易修復
大錯誤安全漏洞、資料丟失、生產環境崩潰定義職涯、有時無法恢復

不對稱性:大錯誤可以抵消多年的小勝利。一個災難性的錯誤可以摧毀十年建立的聲譽。但大勝利很少能彌補大錯誤。

策略:花更少時間嘗試變得聰明,花更多時間嘗試避免明顯的愚蠢。


2. Non-Stupidity in Frontend Development

2. 前端開發中的不愚蠢

2.1 The Technical Stupidities to Avoid

These aren't subtle mistakes — they're patterns that cause most bugs and maintainability nightmares:

1. Derived State and Redundant State

typescript
// STUPID: Creating state for values that can be derived from props
const [filteredItems, setFilteredItems] = useState(
  items.filter(item => item.active)
)

// Problem: filteredItems can diverge from items
// You now have to sync them manually in useEffect

// NOT STUPID: Just derive it
const filteredItems = items.filter(item => item.active)

Cost of this mistake: Hours debugging "why did the UI show the wrong data?"

2. useEffect Dependency Hell

typescript
// STUPID: Missing or incorrect dependencies
useEffect(() => {
  fetchData(userId) // userId not in dependency array
}, [])

// NOT STUPID: Use exhaustive-deps eslint rule religiously
useEffect(() => {
  fetchData(userId)
}, [userId])

// EVEN BETTER: Question whether you need the effect at all
// Often you can move logic into event handlers

Cost: Memory leaks, stale closures, cascading re-renders

3. Breaking Memoization

typescript
// STUPID: Inline function defeats memo
<MemoizedChild callback={() => handleClick(id)} />

// NOT STUPID: Stable reference
const handleChildClick = useCallback(() => handleClick(id), [id])
<MemoizedChild callback={handleChildClick} />

Cost: Performance degradation you won't notice until your app handles thousands of items

4. The Conditional Rendering Trap

typescript
// STUPID: Renders "0" on the screen when empty
{items.length && <ItemList items={items} />}

// NOT STUPID: Explicit boolean check
{items.length > 0 && <ItemList items={items} />}

Cost: Confused users seeing "0" randomly in the UI

5. Server/Client Component Confusion (Next.js)

typescript
// STUPID: Trying to use client features in Server Components
// This will fail silently or throw confusing errors

// NOT STUPID: Understand the mental model
// Server Components: Run once on server, no state, no effects
// Client Components: Run in browser, can use hooks
// Keep providers in separate 'use client' files

6. Not Revalidating After Mutations

typescript
// STUPID: Mutate data, forget to revalidate
async function deleteItem(id: string) {
  await db.items.delete(id)
  // Users see stale data!
}

// NOT STUPID: Every mutation needs a revalidation buddy
async function deleteItem(id: string) {
  await db.items.delete(id)
  revalidatePath('/items')
}

2.1 要避免的技術愚蠢

這些不是微妙的錯誤——它們是導致大多數 bug 和維護噩夢的模式:

1. 衍生狀態和冗餘狀態

typescript
// 愚蠢:為可以從 props 衍生的值創建狀態
const [filteredItems, setFilteredItems] = useState(
  items.filter(item => item.active)
)

// 問題:filteredItems 可能與 items 不同步
// 你現在必須在 useEffect 中手動同步它們

// 不愚蠢:直接衍生它
const filteredItems = items.filter(item => item.active)

這個錯誤的代價:花數小時除錯「為什麼 UI 顯示了錯誤的資料?」

2. useEffect 依賴地獄

typescript
// 愚蠢:缺少或不正確的依賴
useEffect(() => {
  fetchData(userId) // userId 不在依賴陣列中
}, [])

// 不愚蠢:虔誠地使用 exhaustive-deps eslint 規則
useEffect(() => {
  fetchData(userId)
}, [userId])

// 更好:質疑你是否真的需要這個 effect
// 通常你可以把邏輯移到事件處理器中

代價:記憶體洩漏、過時的閉包、連鎖重新渲染

3. 破壞記憶化

typescript
// 愚蠢:內聯函數破壞 memo
<MemoizedChild callback={() => handleClick(id)} />

// 不愚蠢:穩定的引用
const handleChildClick = useCallback(() => handleClick(id), [id])
<MemoizedChild callback={handleChildClick} />

代價:你不會注意到的效能下降,直到你的應用處理數千個項目

4. 條件渲染陷阱

typescript
// 愚蠢:當為空時在螢幕上渲染 "0"
{items.length && <ItemList items={items} />}

// 不愚蠢:明確的布林檢查
{items.length > 0 && <ItemList items={items} />}

代價:困惑的使用者在 UI 中隨機看到「0」

5. Server/Client 元件混淆(Next.js)

typescript
// 愚蠢:試圖在 Server Components 中使用客戶端功能
// 這會靜默失敗或拋出令人困惑的錯誤

// 不愚蠢:理解心智模型
// Server Components:在伺服器上運行一次,沒有狀態,沒有 effects
// Client Components:在瀏覽器中運行,可以使用 hooks
// 將 providers 保存在單獨的 'use client' 檔案中

6. 變更後不重新驗證

typescript
// 愚蠢:變更資料,忘記重新驗證
async function deleteItem(id: string) {
  await db.items.delete(id)
  // 使用者看到過時的資料!
}

// 不愚蠢:每個變更都需要一個重新驗證夥伴
async function deleteItem(id: string) {
  await db.items.delete(id)
  revalidatePath('/items')
}

2.2 Architectural Stupidities — Technical Debt Patterns

1. Spaghetti Architecture (Circular Dependencies)

Component A imports from B imports from A. No one can change anything without breaking something.

Early warning signs: You're hesitant to refactor because "it touches too much"

Not-stupid approach: Unidirectional data flow. Components don't reach into each other's internals.

2. Tight Coupling Between Modules

typescript
// STUPID: Payment component directly modifies global state
function PaymentForm() {
  const { setGlobalUser } = useGlobalStore()
  // Now this component can't be moved without bringing the store

  // NOT STUPID: Props and callbacks
  function PaymentForm({ onPaymentComplete }: Props) {
    // Component is independently testable
  }
}

3. No Design System

Every developer creates buttons differently. "This button is padding-8, that one is padding-10."

Cost: Inconsistent UI, massive refactors when you want to change button color everywhere

Not-stupid: Define a design system early. Save hundreds of hours of busywork.

4. Ignoring Semantic HTML

html
<!-- STUPID: div soup -->
<div class="button" onclick="...">Click me</div>
<div class="nav">
  <div class="link">Home</div>
</div>

<!-- NOT STUPID: semantic elements -->
<button onclick="...">Click me</button>
<nav>
  <a href="/">Home</a>
</nav>

Cost: Accessibility fails (real users can't use your app), SEO suffers, code readability drops

5. Over-Engineering Before Understanding Requirements

Building a complex state management system before you know if you need it.

The rule: Start simple. Add complexity only when you feel the pain.

2.3 The Not-Stupid Code Review Checklist

When reviewing code or making architecture decisions, invert the question:

Instead of: "Is this clever? Does this show skill?" Ask: "How will this break? What bad thing could this enable?"

Practical checklist:

  • [ ] Does this create duplicate state that could diverge?
  • [ ] Are we making assumptions about data that could be violated?
  • [ ] Could this cause a memory leak?
  • [ ] Does this logic depend on values we're not tracking?
  • [ ] Is there tight coupling here?
  • [ ] Could we understand this in 6 months without the author explaining?
  • [ ] What's the worst-case scenario if this code is wrong?

2.2 架構愚蠢——技術債模式

1. 義大利麵架構(循環依賴)

元件 A 從 B 導入,B 從 A 導入。沒有人能改變任何東西而不破壞其他東西。

早期警告信號:你猶豫是否要重構,因為「它涉及太多」

不愚蠢的方法:單向資料流。元件不深入彼此的內部。

2. 模組之間的緊密耦合

typescript
// 愚蠢:Payment 元件直接修改全域狀態
function PaymentForm() {
  const { setGlobalUser } = useGlobalStore()
  // 現在這個元件不帶上 store 就無法移動

  // 不愚蠢:Props 和 callbacks
  function PaymentForm({ onPaymentComplete }: Props) {
    // 元件可以獨立測試
  }
}

3. 沒有設計系統

每個開發者創建的按鈕都不一樣。「這個按鈕是 padding-8,那個是 padding-10。」

代價:不一致的 UI,當你想到處改變按鈕顏色時需要大量重構

不愚蠢:提早定義設計系統。節省數百小時的繁瑣工作。

4. 忽略語義化 HTML

html
<!-- 愚蠢:div 湯 -->
<div class="button" onclick="...">點擊我</div>
<div class="nav">
  <div class="link">首頁</div>
</div>

<!-- 不愚蠢:語義化元素 -->
<button onclick="...">點擊我</button>
<nav>
  <a href="/">首頁</a>
</nav>

代價:無障礙失敗(真實使用者無法使用你的應用)、SEO 受損、程式碼可讀性下降

5. 在理解需求之前過度工程化

在你知道是否需要之前就建立一個複雜的狀態管理系統。

規則:從簡單開始。只有當你感到痛苦時才增加複雜性。

2.3 不愚蠢的程式碼審查清單

審查程式碼或做架構決策時,反轉問題:

不要問:「這很聰明嗎?這顯示了技巧嗎?」 要問:「這會怎麼壞掉?這可能導致什麼壞事?」

實用清單:

  • [ ] 這是否創建了可能發散的重複狀態?
  • [ ] 我們是否在對可能被違反的資料做假設?
  • [ ] 這可能導致記憶體洩漏嗎?
  • [ ] 這個邏輯是否依賴於我們沒有追蹤的值?
  • [ ] 這裡有緊密耦合嗎?
  • [ ] 6 個月後我們能在沒有作者解釋的情況下理解這個嗎?
  • [ ] 如果這段程式碼是錯的,最壞的情況是什麼?

2.4 Career Stupidities for Frontend Developers

1. Jumping Technologies Constantly

Learning Vue, then React, then Svelte, staying shallow in all.

Cost: You'll never build expertise. Companies want T-shaped people — deep in one thing, broad knowledge elsewhere.

Not-stupid: Pick React (currently the market leader), go deep. Build 5+ real projects. That's 2-3 years minimum.

2. Not Sharing Your Work

Building amazing projects, showing no one.

Cost: No professional network, hiring managers have never heard of you.

Not-stupid: Write about what you learn. Build public projects. Speak at meetups. One technical blog post per month compounds.

3. Over-Optimizing for Hiring Tests

Grinding LeetCode for algorithm problems, ignoring communication and system design.

Cost: You get hired for a job you fail at. 60% of hiring failures are soft skills, not technical.

Not-stupid: Learn the fundamentals, but spend more time on communication, code review skills, and mentoring.

4. Ignoring the Business Context

Making purely technical decisions without understanding the "why."

Cost: Building over-engineered solutions, missing real user needs.

Not-stupid: Understand the business problem before the technical solution. Talk to product and users.

5. Burning Out to Prove Your Value

Taking on too much to prove you belong.

Cost: Burnout. Mistakes from being overextended. Not taking time to actually learn.

Not-stupid: Companies hire you because they want you to succeed. Lean on colleagues. Ask for help.

2.4 前端開發者的職涯愚蠢

1. 不斷跳換技術

學 Vue,然後 React,然後 Svelte,在所有方面都保持淺層。

代價:你永遠不會建立專業。公司想要 T 型人才——在一件事上深入,在其他方面有廣泛的知識。

不愚蠢:選擇 React(目前的市場領導者),深入學習。建立 5 個以上的真實專案。這至少需要 2-3 年。

2. 不分享你的工作

建立了很棒的專案,卻不給任何人看。

代價:沒有專業網絡,招聘經理從未聽說過你。

不愚蠢:寫下你學到的東西。建立公開專案。在聚會上演講。每月一篇技術部落格文章會複利。

3. 過度優化招聘測試

刷 LeetCode 的演算法問題,忽略溝通和系統設計。

代價:你獲得了一份你會失敗的工作。60% 的招聘失敗是軟技能問題,而非技術問題。

不愚蠢:學習基礎知識,但花更多時間在溝通、程式碼審查技能和指導他人上。

4. 忽略業務背景

做純技術決策而不理解「為什麼」。

代價:建立過度工程化的解決方案,錯過真正的使用者需求。

不愚蠢:在技術解決方案之前理解業務問題。與產品和使用者交談。

5. 燃盡自己來證明你的價值

承擔太多來證明你屬於這裡。

代價:倦怠。因為過度擴展而犯錯。沒有時間真正學習。

不愚蠢:公司僱用你是因為他們希望你成功。依靠同事。尋求幫助。


3. Non-Stupidity in Life

3. 人生中的不愚蠢

3.1 Common Life Mistakes Intelligent People Make

1. Overconfidence (The "I'm-not-biased" Bias)

Intelligent people are aware of cognitive biases, so they think they're immune. The irony: the smartest people are often the most overconfident because they can construct elaborate justifications for their beliefs.

Real cost: Bad marriages, terrible business decisions, massive financial losses.

Not-stupid approach: Assume you're biased. Ask others to challenge your thinking. Demand evidence that contradicts your view.

2. Staying Outside Your Circle of Competence

Your success in one domain (engineering) makes you think you understand other domains (real estate, picking stocks, relationships).

Munger's rule: "If I want to hold a view, I must be able to refute it better than the smartest person on Earth could, or I shouldn't hold it."

Not-stupid: Know your boundaries ruthlessly. Admit ignorance.

3. Confusing Effort with Outcomes

Putting in massive effort and assuming that guarantees results.

Cost: Grinding on the wrong problem, staying in bad situations too long.

Not-stupid: Results matter. If effort isn't producing results, change approach, not just effort level.

4. Ignoring Incentive Structures

Expecting people to act against their incentives.

Example: Expecting a salesman to recommend what's best for you when they're paid on commission.

Not-stupid: Design your own incentives. Don't rely on willpower. Make the right choice the easy choice.

5. Psychological Denial

Knowing something is wrong but refusing to acknowledge it.

Cost: Staying in bad jobs, bad relationships, bad investments for years.

Not-stupid: Create forcing mechanisms. Set decision dates. Use external accountability.

3.2 Inversion in Daily Life

Traditional thinking vs. Inversion:

DomainForward QuestionInverted Question
Career"What's the perfect job?""What job would make me miserable?"
Relationships"Will this be a great relationship?""What patterns destroy relationships? Do we have these?"
Health"How do I optimize my health?""What destroys health? How do I avoid those?"
Money"How do I get rich?""How do I go broke? How do I avoid that?"
Business"What's the brilliant idea?""What kills businesses? What's least likely to face those?"

The result of inversion: You eliminate 80% of bad options, leaving good ones. You catch dealbreakers early. You don't need genius — just discipline.

3.1 聰明人常犯的人生錯誤

1. 過度自信(「我沒有偏見」的偏見)

聰明人知道認知偏誤,所以他們認為自己免疫。諷刺的是:最聰明的人往往最過度自信,因為他們可以為自己的信念構建精心設計的理由。

真實代價:糟糕的婚姻、可怕的商業決策、巨大的財務損失。

不愚蠢的方法:假設你有偏見。請他人挑戰你的想法。要求與你觀點相矛盾的證據。

2. 停留在你的能力圈之外

你在一個領域(工程)的成功讓你認為你理解其他領域(房地產、選股、人際關係)。

Munger 的規則:「如果我想持有一個觀點,我必須能夠比地球上最聰明的人更好地反駁它,否則我不應該持有它。」

不愚蠢:無情地了解你的邊界。承認無知。

3. 將努力與結果混淆

投入大量努力並假設這保證結果。

代價:在錯誤的問題上埋頭苦幹,在糟糕的情況下停留太久。

不愚蠢:結果很重要。如果努力沒有產生結果,改變方法,而不僅僅是努力程度。

4. 忽視激勵結構

期望人們違背他們的激勵行事。

例子:期望一個按佣金支付的銷售員推薦對你最好的東西。

不愚蠢:設計你自己的激勵。不要依賴意志力。讓正確的選擇成為容易的選擇。

5. 心理否認

知道某事是錯的但拒絕承認。

代價:在糟糕的工作、糟糕的關係、糟糕的投資中停留數年。

不愚蠢:創建強制機制。設定決策日期。使用外部問責。

3.2 日常生活中的反向思維

傳統思維 vs. 反向思維:

領域正向問題反向問題
職涯「什麼是完美的工作?」「什麼工作會讓我痛苦?」
人際關係「這會是一段很棒的關係嗎?」「什麼模式會摧毀關係?我們有這些嗎?」
健康「我如何優化我的健康?」「什麼會摧毀健康?我如何避免那些?」
金錢「我如何變富?」「我如何破產?我如何避免那個?」
商業「什麼是精彩的想法?」「什麼會殺死企業?什麼最不可能面臨那些?」

反向思維的結果:你排除了 80% 的壞選項,留下好的。你提早抓住致命問題。你不需要天才——只需要紀律。

3.3 Examples of Success Through Non-Stupidity

Warren Buffett and Berkshire Hathaway

  • Systematic avoidance of: leverage, overvalued assets, bad management, industries they don't understand
  • Result: 60+ years of outperformance without being the cleverest investor

Amazon Under Jeff Bezos

  • Early inversion: "What would kill e-commerce? Slow shipping, high prices, limited selection"
  • System: Obsessive focus on fast shipping, low prices, vast selection
  • Result: Not brilliant, but systematic avoidance of failure modes

Aviation Safety

  • The stupidity: Assuming expert pilots remember every step
  • The system: NASA-style checklists before every flight
  • Result: Aviation is the safest form of transportation despite being complex

Google's Engineering Culture

  • The inversion: "What breaks code quality?"
  • The system: Mandatory code reviews, tests before deployment, coding standards
  • Result: Can hire from anywhere, still produce reliable code

3.3 通過不愚蠢獲得成功的例子

Warren Buffett 和 Berkshire Hathaway

  • 系統性地避免:槓桿、高估的資產、糟糕的管理層、他們不了解的產業
  • 結果:60 多年的超越表現,而不是成為最聰明的投資者

Jeff Bezos 領導下的 Amazon

  • 早期的反向思維:「什麼會殺死電商?慢速配送、高價格、有限的選擇」
  • 系統:對快速配送、低價格、廣泛選擇的執著
  • 結果:不是天才,而是系統性地避免失敗模式

航空安全

  • 愚蠢:假設專家飛行員會記住每一步
  • 系統:每次飛行前的 NASA 式清單
  • 結果:儘管複雜,航空是最安全的交通方式

Google 的工程文化

  • 反向思維:「什麼會破壞程式碼品質?」
  • 系統:強制性的程式碼審查、部署前的測試、編碼標準
  • 結果:可以從任何地方招人,仍然產出可靠的程式碼

4. Building Systems for Non-Stupidity

4. 建立不愚蠢的系統

4.1 The Pre-Mortem Exercise

How to run a pre-mortem (30 minutes):

  1. Set the scene: "It's 6 months from now. This [project/decision/career move] has failed spectacularly."

  2. Brainstorm failure modes (10 minutes):

    • Each person writes: "Why did this fail?"
    • No filtering. Even crazy ideas count.
  3. Organize and discuss (15 minutes):

    • Group similar failure modes
    • Pick the 2-3 most likely
    • Ask: "What could we do NOW to prevent this?"
  4. Create action items (5 minutes):

    • For each major risk, assign one person to mitigate it

Example for a frontend project redesign:

Failure modes:

  • "Developers didn't migrate because migration was too painful"
  • "We broke backward compatibility"
  • "We solved the wrong problem — didn't talk to actual users"
  • "Someone left mid-project and no one understood the architecture"

Mitigations:

  • Plan codemods that auto-migrate 80% of cases
  • Strict rule: deprecation warnings for 2 versions before removal
  • Talk to 5 teams about pain points before starting
  • Document architecture decisions, pair program on critical parts

4.2 Decision-Making Checklist

Before making a technical decision:

  • [ ] Do I understand the problem we're solving?
  • [ ] Is this within my circle of competence?
  • [ ] Have I studied how this technology failed elsewhere?
  • [ ] What's the simplest solution that could work?
  • [ ] If I pick the "boring" option, what does success look like?
  • [ ] What would make this choice disastrous?
  • [ ] Have I talked to someone who's made the opposite choice?
  • [ ] Can we defer this decision?
  • [ ] What's the switching cost if we're wrong?
  • [ ] Am I choosing this because it's clever or because it solves the problem?

Before accepting a job opportunity:

  • [ ] Do I understand what problems I'll solve?
  • [ ] Who's the team? Are they people I want to learn from?
  • [ ] What's the company's actual business model?
  • [ ] What could go wrong here?
  • [ ] Is this moving me toward expertise or away from it?
  • [ ] If this company fails in 18 months, will I regret this decision?
  • [ ] What would make me miserable in this role?
  • [ ] Can I leave in 1 year without massive consequences?

4.3 Identifying Your Personal Stupidity Patterns

Step 1: Review your past (2-3 hours)

  • Think of 5-10 decisions you regret
  • Write down: What went wrong? What did I miss?
  • Look for patterns. Do you:
    • Always overcommit?
    • Rush decisions?
    • Fall in love with your ideas and not listen to feedback?
    • Stay in bad situations too long?
    • Make decisions when tired/emotional?
    • Not ask for help?

Step 2: Ask people who know you well

  • "What patterns do you see in my mistakes?"
  • "Where should I be more careful?"
  • Listen. Don't defend.

Step 3: Create your personal stupidity checklist

Example for a developer:

PatternTriggerPrevention System
Over-engineering"This could be more elegant"Ask "Do we need this right now?" before every abstraction
Skipping documentation"The code is self-explanatory"No PR approved without docs
Not testing edge casesHappy-path thinkingTest list includes 3 edge cases minimum
Chasing new tech"This framework is exciting"Same tech as last project unless specific pain point
Waiting for perfect infoFear of being wrongDecision deadline: decide by Friday regardless

4.1 事前驗屍練習

如何進行事前驗屍(30 分鐘):

  1. 設定場景:「現在是 6 個月後。這個 [專案/決策/職涯轉變] 慘敗了。」

  2. 腦力激盪失敗模式(10 分鐘)

    • 每個人寫下:「為什麼這失敗了?」
    • 不過濾。即使是瘋狂的想法也算。
  3. 組織和討論(15 分鐘)

    • 將相似的失敗模式分組
    • 選出 2-3 個最可能的
    • 問:「我們現在可以做什麼來防止這個?」
  4. 創建行動項目(5 分鐘)

    • 對於每個主要風險,指派一個人來緩解它

前端專案重新設計的例子:

失敗模式:

  • 「開發者沒有遷移,因為遷移太痛苦了」
  • 「我們破壞了向後兼容性」
  • 「我們解決了錯誤的問題——沒有與實際使用者交談」
  • 「有人在專案中途離開,沒人理解架構」

緩解措施:

  • 計劃可以自動遷移 80% 案例的 codemods
  • 嚴格規則:移除前提供 2 個版本的棄用警告
  • 開始前與 5 個團隊討論痛點
  • 記錄架構決策,在關鍵部分進行配對程式設計

4.2 決策清單

做技術決策之前:

  • [ ] 我理解我們要解決的問題嗎?
  • [ ] 這在我的能力圈內嗎?
  • [ ] 我研究過這項技術在其他地方是如何失敗的嗎?
  • [ ] 最簡單可行的解決方案是什麼?
  • [ ] 如果我選擇「無聊」的選項,成功會是什麼樣子?
  • [ ] 什麼會讓這個選擇成為災難?
  • [ ] 我有沒有和做過相反選擇的人交談過?
  • [ ] 我們可以推遲這個決定嗎?
  • [ ] 如果我們錯了,轉換成本是什麼?
  • [ ] 我選擇這個是因為它很聰明還是因為它解決了問題?

接受工作機會之前:

  • [ ] 我理解我將解決什麼問題嗎?
  • [ ] 團隊是誰?他們是我想學習的人嗎?
  • [ ] 公司的實際商業模式是什麼?
  • [ ] 這裡可能出什麼問題?
  • [ ] 這是讓我走向專業還是遠離專業?
  • [ ] 如果這家公司在 18 個月內失敗,我會後悔這個決定嗎?
  • [ ] 什麼會讓我在這個角色中痛苦?
  • [ ] 我能在 1 年內離開而沒有巨大後果嗎?

4.3 識別你的個人愚蠢模式

步驟一:回顧你的過去(2-3 小時)

  • 想 5-10 個你後悔的決定
  • 寫下:什麼出了問題?我錯過了什麼?
  • 尋找模式。你是否:
    • 總是過度承諾?
    • 倉促決策?
    • 愛上你的想法而不聽取反饋?
    • 在糟糕的情況下停留太久?
    • 在疲倦/情緒化時做決定?
    • 不尋求幫助?

步驟二:問了解你的人

  • 「你在我的錯誤中看到什麼模式?」
  • 「我應該在哪裡更小心?」
  • 傾聽。不要辯護。

步驟三:創建你的個人愚蠢清單

開發者的例子:

模式觸發器預防系統
過度工程化「這可以更優雅」每次抽象前問「我們現在需要這個嗎?」
跳過文件「程式碼是自解釋的」沒有文件就不批准 PR
不測試邊緣情況快樂路徑思維測試清單至少包含 3 個邊緣情況
追逐新技術「這個框架很令人興奮」除非有特定痛點,否則使用與上個專案相同的技術
等待完美資訊害怕犯錯決策截止日期:無論如何在週五前決定

5. The 5-Year Roadmap for Consistent Non-Stupidity

5. 持續不愚蠢的 5 年路線圖

For a Mid-20s Frontend Developer

Year 1 (Now):

  • Pick React. Go deep. Build 3 real projects
  • Read one technical book (e.g., Designing Data-Intensive Applications)
  • Write monthly blog posts about what you learn
  • Master your stupidity patterns from code review feedback

Year 2:

  • Become the person who asks "What could break this?"
  • Learn system design basics (databases, caching, scaling)
  • Start mentoring one junior developer
  • Practice inversion: ask inverted questions before deciding

Year 3:

  • You should know the boundaries of your competence
  • You should have a reputation for reliability, not brilliance
  • You should understand the business your code serves
  • You should be able to code review effectively

Year 4-5:

  • Decide: deep frontend expertise or broad leadership?
  • Whatever you choose, choose deliberately
  • You should be able to explain architectural tradeoffs to non-technical people

Daily Practice

Before every code decision: "How will this break?"

Before every career decision: "What would I regret?"

Before committing code: Run through your stupidity patterns checklist

Before accepting tasks: "Am I overcommitting?"

The Compounding Benefit

If you're 25 and avoid the major stupidities that derail other developers, you'll be ahead by 30. Not because you're brilliant — because you're reliably not stupid.

That's Munger's insight: Consistent non-stupidity beats sporadic brilliance.

The race goes not to the clever, but to the disciplined.

給 20 多歲前端開發者

第一年(現在):

  • 選擇 React。深入學習。建立 3 個真實專案
  • 閱讀一本技術書籍(例如《Designing Data-Intensive Applications》)
  • 每月撰寫部落格文章關於你學到的東西
  • 從程式碼審查反饋中掌握你的愚蠢模式

第二年:

  • 成為那個會問「這會怎麼壞掉?」的人
  • 學習系統設計基礎(資料庫、快取、擴展)
  • 開始指導一名初級開發者
  • 練習反向思維:決定之前問反向問題

第三年:

  • 你應該知道你能力的邊界
  • 你應該有可靠的聲譽,而不是聰明的聲譽
  • 你應該理解你的程式碼所服務的業務
  • 你應該能夠有效地進行程式碼審查

第四至五年:

  • 決定:深入前端專業還是廣泛的領導力?
  • 無論你選擇什麼,都要有意識地選擇
  • 你應該能夠向非技術人員解釋架構權衡

日常練習

每次程式碼決策之前:「這會怎麼壞掉?」

每次職涯決策之前:「我會後悔什麼?」

提交程式碼之前:運行你的愚蠢模式清單

接受任務之前:「我是否過度承諾?」

複利效益

如果你 25 歲,並且避免了讓其他開發者脫軌的主要愚蠢,你在 30 歲時會領先。不是因為你聰明——而是因為你可靠地不愚蠢

這就是 Munger 的洞察:持續的不愚蠢勝過零星的聰明。

比賽不是給聰明人的,而是給有紀律的人的。