Back to blog

Vibe Coding vs Spec-Driven Development

vibe-codingaisoftware-engineeringproductivityopinion
Vibe Coding vs Spec-Driven Development

Bạn mở editor. Có một ý tưởng trong đầu. Bạn bắt đầu gõ vào AI chat — không spec, không ticket, không design doc. Chỉ là cảm hứng. Ba mươi phút sau có một prototype chạy được. Lộn xộn, nhưng chạy.

Rồi một tuần trôi qua. Codebase phình gấp ba. Không ai — kể cả bạn — hiểu tại sao nửa số code đó tồn tại. AI cứ hallucinate ra các function mâu thuẫn với những thứ nó generate hôm qua. Bạn đang debug context, không phải debug code.

Nghe quen không?

Đây là tension cốt lõi của AI-assisted development hiện đại: vibe coding (nhanh, trực giác, flow-state) vs spec-driven development (chủ động, có cấu trúc, predictable). Cả hai đều là workflow thực sự. Cả hai đều có chỗ đứng. Không cái nào đúng trong mọi tình huống.

Hãy phân tích thẳng vào: mỗi cái thực sự là gì, mỗi cái tỏa sáng ở đâu, và khi nào kết hợp chúng giúp bạn nhanh hơn 10x thay vì rối hơn 10x.


Vibe Coding Là Gì?

Vibe coding là cách build software thông qua một cuộc đối thoại liên tục, low-friction với AI — không có planning trước, không có spec chính thức, không có requirements có cấu trúc. Bạn mô tả những gì bạn muốn khi bạn cảm thấy nó. AI generate. Bạn react, điều chỉnh, iterate.

Thuật ngữ này được Andrej Karpathy đặt ra đầu năm 2025:

"Có một kiểu coding mới mà tôi gọi là 'vibe coding', nơi bạn hoàn toàn buông mình vào những rung cảm đó, đón nhận các công nghệ mũi nhọn, và quên đi việc code thậm chí tồn tại... Tôi chỉ thấy thứ gì đó, nói về nó, chạy nó, và copy-paste, và nó phần lớn là hoạt động được."

Vibe coding ủng hộ:

  • Speed over structure — ship thứ gì đó ngay bây giờ, lo architecture sau
  • Exploration over specification — tìm ra bạn muốn gì bằng cách build nó
  • Iteration over planning — draft sai đầu tiên là một phần của quá trình
  • Tin tưởng vào AI generation — để model xử lý syntax, boilerplate, và implementation details

Đây không phải sự cẩu thả. Ở trạng thái tốt nhất, vibe coding là creative engineering — giống như nhạc sĩ jazz improvise thay vì đọc bản nhạc. Constraint là mental model của bạn, không phải một tài liệu.


Spec-Driven Development Là Gì?

Spec-driven development (đôi khi gọi là specification-first hay design-first) đảo ngược trình tự. Trước khi bất kỳ code nào được viết — bởi người hay AI — bạn đầu tư thời gian viết một mô tả chính xác về những gì bạn đang build: behavior của nó, contract của nó, edge case của nó.

Spec đó có thể là:

  • Một API schema chính thức (OpenAPI, JSON Schema, Protobuf)
  • Một Product Requirements Document (PRD) với acceptance criteria
  • Một technical design doc với system diagram
  • Một bộ failing test được viết trước implementation (TDD)
  • Một structured prompt template được feed nhất quán cho AI agent

Với spec trong tay, code trở thành một bài tập điền vào chỗ trống — implement chính xác thế này, không hơn không kém. AI trở thành một execution engine mạnh mẽ thay vì một creative collaborator.

Spec-driven development ủng hộ:

  • Clarity over speed — hiểu rõ problem trước khi giải quyết nó
  • Contract over vibes — mỗi component biết chính xác cần expect gì từ component khác
  • Reviewability — spec là một communication artifact, không chỉ là input cho generation
  • Predictability — với cùng một spec, bạn sẽ nhận được kết quả tương tự

Sự Khác Biệt Thực Sự: Thinking Diễn Ra Ở Đâu?

Đây là điểm khác biệt sắc nét nhất giữa hai approach:

Vibe Coding:     THINK → GENERATE → REACT → THINK → GENERATE → REACT → ...
Spec-Driven:     THINK → THINK → THINK → SPEC → GENERATE → DONE

Trong vibe coding, thinking được phân tán qua loop. Bạn không hiểu mình muốn gì cho đến khi AI cho bạn thấy thứ gì đó và bạn react với nó. Cái này hiệu quả khi domain knowledge của bạn thấp (bạn đang explore), hoặc khi output space đủ nhỏ để evaluate nhanh.

Trong spec-driven development, thinking được front-load. Bạn trả một chi phí upfront về clarity để mọi bước downstream đều rẻ hơn và predictable hơn. Cái này hiệu quả khi domain đã được hiểu rõ, hệ thống lớn, hoặc nhiều người cần collaborate.

Không approach nào tránh được việc thinking. Chúng chỉ lên lịch nó khác nhau.


Vibe Coding Thắng Ở Đâu

1. Rapid Prototyping và Exploration

Bạn chưa biết mình đang build gì. Bạn có một hypothesis — một product idea, một UI pattern mới, một potential integration. Cách nhanh nhất để validate là build một phiên bản thô và xem nó có potential không.

Vibe coding thực sự vượt trội ở đây. Viết spec cho thứ bạn chưa hiểu là lãng phí. Prototype chính là quá trình khám phá spec.

Khi nào dùng:

  • Hackathon và weekend project
  • Early-stage startup đang tìm product-market fit
  • Feasibility spike ("liệu chúng ta có làm được không?")
  • Personal tool bạn dùng một lần rồi bỏ

2. Solo Project Không Có Handoff

Nếu bạn là người duy nhất sẽ đụng vào code này, và project đủ nhỏ để giữ hoàn toàn trong đầu, spec chính thức là overhead. Vibe coding tôn trọng flow state của bạn.

3. UI/UX Iteration

Design về bản chất là visual và reactive. Bạn không thể hoàn toàn spec một UI trước khi nhìn thấy nó — nhận thức của con người react với rendered output. Vibe coding với một frontend AI thường là con đường nhanh nhất đến một design cảm thấy đúng.

4. Boilerplate và Scaffolding

Setup một project mới, configure một framework, viết CRUD endpoint cho một schema đã biết — những task này đã đủ well-understood để không cần spec chính thức. Chỉ cần mô tả và generate.


Spec-Driven Development Thắng Ở Đâu

1. Môi Trường Team

Ngay khi có hai developer, bạn có một coordination problem. Vibe coding tạo ra code chỉ có vibe-coder mới hiểu. Một spec tạo ra một artifact mà mọi người đều có thể đọc, thảo luận, và challenge trước khi implementation bắt đầu.

Spec không phải là documentation sau khi xong. Nó là một communication protocol trước khi bắt đầu.

2. AI Agent Chạy Autonomous

Khi AI agent có khả năng thực hiện các action nhiều bước — viết file, chạy command, gọi API — chi phí của một assumption sai tích lũy rất nhanh. Một agent vibe coding qua một task mơ hồ có thể gây hại thực sự.

Spec-driven prompting cho agent bounded agency: đây là những gì bạn được phép làm, đây là contract bạn phải thỏa mãn, đây là cái done trông như thế nào.

3. System Cần Interoperate

API, microservice, data pipeline — bất cứ đâu hai hệ thống giao tiếp với nhau, cả hai bên đều cần một shared contract. Một spec (OpenAPI schema, Protobuf definition, event schema) không phải overhead; nó là interface. Generate code từ spec, không phải spec từ code.

4. Codebase Sống Lâu

System vibe-coded tích lũy cognitive debt nhanh hơn technical debt. Sáu tháng sau, không ai biết tại sao một module tồn tại, nó được cho là làm gì, hoặc liệu có an toàn để thay đổi không. Một spec cung cấp lớp archaeology — không chỉ code làm gì, mà còn tại sao nó được build theo cách này.

5. Domain Được Điều Tiết Hoặc High-Stakes

Healthcare, finance, security-critical system — những nơi mà "ôi, AI hallucinate một edge case" không phải câu trả lời chấp nhận được. Bạn cần requirements rõ ràng, reviewable trước khi bất kỳ code nào được generate hay deploy.


Failure Mode Của Từng Cái

Vibe Coding Failures

Vibe drift: Mỗi session generation mới diễn giải lại context trước đó một chút. Theo thời gian, codebase trở nên internally inconsistent — các module khác nhau dùng convention khác nhau, naming style khác nhau, và assumption khác nhau vì chúng được generate trong những "vibe" khác nhau.

Hallucination tích lũy: AI tự tin generate function tham chiếu đến function khác không tồn tại. Trong project nhỏ, bạn bắt được ngay. Trong project lớn, bạn phát hiện ra lúc runtime.

Refactor abyss: Code chạy được nhưng không thể hiểu được. Thay đổi bất kỳ phần nào có nguy cơ phá vỡ hidden dependency. Architecture vibe-coded thường phẳng và coupled — nhanh để generate, đau đớn để evolve.

Bẫy "Tôi sẽ clean up sau": Bạn sẽ không.

Spec-Driven Failures

Analysis paralysis: Một số team viết spec hàng tháng và không bao giờ ship. Một spec không bao giờ generate code còn tệ hơn không có spec — nó tiêu tốn thời gian và tạo ra cảm giác tiến bộ giả tạo.

Spec-reality divergence: Spec đúng sáu tháng trước. Code đã evolve. Không ai update spec. Giờ spec gây hiểu lầm, và developer mới tin vào nó thay vì code.

Over-specification: Viết một design doc 40 trang cho một feature cần 200 dòng code. Overhead giết chết momentum, đặc biệt trong early-stage project.

Coi spec là luật bất biến: Requirement thay đổi. Một team spec-driven không thể update spec của mình chỉ là bureaucracy với từ vựng kỹ thuật.


Framework Quyết Định Thực Tế

Trước khi bắt đầu một feature hay project mới, hỏi những câu hỏi này:

Bạn có hiểu bạn đang build gì không?

  • Không → Vibe code một prototype trước, rồi extract spec từ những gì bạn học được
  • Có → Viết spec, rồi generate từ nó

Ai khác cần hiểu hoặc maintain cái này?

  • Chỉ mình tôi → Vibe coding ổn, document tối thiểu
  • Team → Viết spec trước khi chạm vào keyboard

Code này sẽ sống bao lâu?

  • Vài giờ đến vài tuần → Vibe coding chấp nhận được
  • Vài tháng đến vài năm → Đầu tư vào spec

Chi phí của việc sai là gì?

  • Thấp (UI tweak, personal tool) → Vibe code và iterate
  • Cao (data migration, public API, billing logic) → Spec trước, luôn luôn

Bạn có dùng AI agent với tool access không?

  • Không, interactive chat → Vibe coding với course correction có thể quản lý được
  • Có, autonomous execution → Spec-driven prompting là bắt buộc

Hybrid Workflow Thực Sự Hoạt Động

Các team tốt nhất không chọn giữa vibe coding và spec-driven development. Họ dùng cả hai — theo đúng trình tự.

Phase 1: Vibe để Học

Khi một problem còn mới hoặc mơ hồ, hãy dành 1-2 giờ vibe code một prototype throwaway. Mục tiêu không phải code chạy được — mà là information extraction. Bạn học được gì về problem? Assumption nào hóa ra sai? Điều gì bất ngờ?

Treat prototype như một spike, không phải foundation.

Phase 2: Spec để Align

Lấy những gì bạn học được và viết một spec ngắn gọn. Nó không cần là một tài liệu 50 trang. Chỉ cần một structured prompt mô tả:

  • System chấp nhận input gì
  • Nó tạo ra output gì
  • Invariant nào phải được giữ
  • Edge case nào bạn đã nghĩ đến

...là đủ để cải thiện đáng kể chất lượng AI generation.

Phase 3: Generate để Ship

Bây giờ chạy AI với spec của bạn. Generation sẽ nhất quán hơn, đầy đủ hơn, và dễ review hơn. Khi AI drift khỏi spec, bạn có một correction anchor — không chỉ là cảm giác mơ hồ rằng có gì đó sai.

Phase 4: Giữ Spec Sống

Khi code evolve, update spec. Đây là discipline mà hầu hết team bỏ qua — và đó là lý do spec-reality divergence giết chết các spec-driven project. Một living spec là một valuable asset. Một stale spec là thông tin sai lệch.


Điều Này Có Nghĩa Gì Với AI-Assisted Development

Sự xuất hiện của AI code generation không làm spec trở nên lỗi thời — nó làm chúng có giá trị hơn.

Đây là lý do: AI generation rẻ. Human review đắt. Càng nhiều code AI có thể generate mỗi đơn vị thời gian, càng quan trọng hơn để đảm bảo mỗi đơn vị generation được chỉ đúng hướng. Một spec là một steering mechanism cho cheap generation.

Không có spec, bạn đang lái xe nhanh mà không có đích đến. AI sẽ vui vẻ đưa bạn đến đâu đó — chỉ là không nhất thiết là nơi bạn muốn đến.

Với spec, bạn đang lái xe nhanh với bản đồ. Tốc độ của AI làm việc cho lợi ích của bạn thay vì tích lũy sự nhầm lẫn.

Những engineer thịnh vượng trong kỷ nguyên AI sẽ không phải là người generate nhiều code nhất. Họ sẽ là người có thể viết spec chặt chẽ nhất — những người có thể chắt lọc human intent mơ hồ thành các contract chính xác, machine-executable.


Tóm Tắt và Bài Học Chính

✅ Vibe coding nhanh, exploratory, và lý tưởng cho prototype, personal tool, và UI iteration
✅ Spec-driven development có chủ đích, có cấu trúc, và thiết yếu cho team, agent, và long-lived system
✅ Sự khác biệt cốt lõi: vibe coding phân tán thinking qua loop; spec-driven front-load nó
✅ Vibe coding failure: drift, hallucination tích lũy, refactor abyss, cleanup debt
✅ Spec-driven failure: analysis paralysis, spec-reality divergence, over-specification
✅ Hybrid approach: vibe để học → spec để align → generate để ship → giữ spec sống
✅ AI generation rẻ; steering nó tốt là phần đắt tiền, thuộc về con người


Suy Nghĩ Cuối

Vibe coding không phải là sự lười biếng. Spec-driven development không phải là bureaucracy. Chúng là những công cụ khác nhau cho những problem khác nhau — và những developer hiểu cả hai sẽ liên tục vượt trội hơn những người cam kết với một ideology.

Câu hỏi không phải là "Tôi có nên vibe code hay viết spec?"

Câu hỏi là: "Ở đâu trong project này tôi đang explore, và ở đâu tôi đang execute?"

Explore với vibes. Execute với spec. Biết cái nào bạn đang làm tại bất kỳ thời điểm nào.

Đó không phải là workflow. Đó là judgment.

📬 Đăng ký nhận bản tin

Nhận những bài viết mới nhất qua email mỗi tuần. Không spam, hủy đăng ký bất cứ lúc nào.

Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất cứ lúc nào.

💬 Comments

Đăng nhập để bình luận

Chúng tôi sẽ không đăng bất cứ điều gì mà không có sự cho phép của bạn.