Vibe Coding vs Specification-Driven Development: Kenapa Engineer Senior Mulai Pindah
Pelajari perbedaan mendasar vibe coding dan SDD. Kenapa engineer senior beralih ke specification-driven development dengan Claude Code untuk proyek Golang mereka.
Perdebatan vibe coding vs specification-driven development bukan soal tren, tapi soal apa yang terjadi pada kode kamu enam bulan setelah AI menuliskannya. Kita semua pernah melakukannya: buka terminal, ketik claude, lalu tulis “Buatin REST API order management pakai Golang, PostgreSQL, clean architecture.” Claude langsung menghasilkan ratusan baris kode. Copy-paste, jalankan — works. Rasanya seperti sihir.
Dua minggu kemudian, saat menambah fitur payment gateway, situasinya berubah. Struktur folder sedikit beda. Naming convention bergeser. Pattern tidak konsisten dengan kode lama. Dan yang paling menyakitkan: kita tidak bisa menjelaskan ke AI kenapa kode sebelumnya dibuat seperti itu — karena kita juga tidak tahu. AI yang menulis, bukan kita.
Inilah masalah inti vibe coding — dan Specification-Driven Development (SDD) hadir sebagai jawabannya. Di artikel pertama seri ini, kita bedah tuntas perbedaannya dari pengalaman nyata engineer yang sudah merasakan keduanya.
01.1 Apa Itu Vibe Coding dan Kenapa Awalnya Terasa Enak
Istilah vibe coding dipopulerkan Andrej Karpathy awal 2025. Konsepnya sederhana: deskripsikan apa yang kamu mau ke AI dalam bahasa natural, AI eksekusi, kamu review sekilas, lanjut. Alur percakapan berikut merangkum siklus khas vibe coding dalam praktik sehari-hari.
1Kamu: "Buatin endpoint POST /orders yang terima JSON, validasi,
2 simpan ke DB, terus kirim event ke Kafka"
3AI: [menulis 200 baris kode]
4Kamu: [copy-paste, jalankan, works, commit]Perhatikan tidak ada satu pun titik di alur itu yang memaksa kamu memutuskan behavior secara eksplisit — semua diserahkan ke tebakan AI. Ini terasa revolusioner, dan memang revolusioner untuk use case tertentu: prototyping cepat, eksplorasi teknologi baru, PoC untuk demo. Masalahnya muncul ketika pendekatan yang sama dipakai untuk membangun sistem yang hidup di production selama bertahun-tahun.
Ada tiga alasan kenapa vibe coding terasa enak di awal:
Umpan balik instan. Kamu dapat kode yang jalan dalam hitungan detik. Dopamine hit-nya nyata dan tidak bisa dipungkiri.
Barrier to entry turun drastis. Junior developer bisa menghasilkan kode yang terlihat seperti hasil senior. Tidak perlu hafal semua API atau pattern.
Eksplorasi tanpa beban. Mau coba library baru? Tanya AI. Mau lihat bagaimana implementasi pattern tertentu? Tanya AI sambil ngopi.
Semua ini nyata dan valuable. Masalahnya adalah ketika vibe coding bukan lagi eksplorasi tapi jadi cara utama membangun sistem production.
01.2 Di Mana Vibe Coding Mulai Runtuh
Vibe coding punya titik kegagalan yang sistematis — bukan kebetulan, tapi konsekuensi logis dari cara kerjanya.
Ambiguitas yang Menumpuk Secara Diam-diam
Saat kamu bilang “buatkan fitur order management,” AI tidak tahu:
- Apakah order bisa dicancel setelah confirmed?
- Siapa yang bisa cancel — hanya user atau juga admin?
- Apa yang terjadi ke stok saat order dicancel?
- Format harga: integer sen atau float desimal?
- Apakah ada batas waktu cancel?
AI akan menebak. Kadang tebakannya bagus, kadang tidak. Semakin kompleks sistem, semakin sering tebakan meleset — dan setiap tebakan yang salah menjadi asumsi tersembunyi di dalam kode.
Konteks yang Menguap Seiring Sesi Berlanjut
Dalam sesi yang panjang, AI mulai “lupa” keputusan arsitektur yang dibuat di awal. Dua potongan handler berikut diambil dari proyek yang sama, hanya berbeda beberapa sesi — perhatikan bagaimana disiplin layer perlahan runtuh.
1// Sesi 1: AI mengikuti clean architecture dengan benar
2func (h *OrderHandler) Create(c echo.Context) error {
3 // handler hanya parse request dan delegate ke usecase
4 return h.useCase.Create(c.Request().Context(), req)
5}
6
7// Sesi 3 (setelah panjang): AI mulai campuraduk layer
8func (h *OrderHandler) Cancel(c echo.Context) error {
9 // logika bisnis nyasar ke handler — kode jalan tapi arsitektur rusak
10 order, _ := h.db.QueryRow("SELECT * FROM orders WHERE id = $1", id)
11 if order.Status != "PENDING" {
12 return c.JSON(400, "cannot cancel")
13 }
14 // dan seterusnya, langsung DB call dari handler...
15}Kode di atas masih jalan, tapi arsitekturnya sudah mulai rusak. Dan yang menakutkan: kamu tidak menyadarinya sampai technical debt menumpuk terlalu banyak untuk diperbaiki dengan murah.
Tidak Ada Titik Verifikasi yang Objektif
Bagaimana kamu tahu kode yang dihasilkan AI sudah benar? Di vibe coding, jawabannya: “kelihatannya benar.” Tidak ada spec yang bisa dijadikan checklist. Tidak ada acceptance criteria yang bisa di-verify. Hanya feeling.
01.3 Definisi Operasional SDD
Specification-Driven Development (SDD) adalah pendekatan di mana spesifikasi tertulis hadir sebelum kode, menjadi single source of truth yang menentukan behavior sistem secara eksplisit.
Ada tiga komponen wajib dalam SDD. Komponen pertama, User Story, menjawab siapa yang butuh apa dan mengapa — seperti contoh berikut.
1Sebagai customer Santekno Shop, saya ingin membuat order dari item
2yang ada di cart agar barang tersebut dipesan dan dikirim ke alamat saya.User story menjaga fokus pada nilai bisnis, bukan detail teknis — ini titik awal yang memaksa setiap keputusan implementasi punya alasan. Komponen kedua, Acceptance Criteria (AC), menerjemahkan story itu menjadi kondisi terukur yang harus dipenuhi agar fitur dianggap selesai.
1AC1: System menerima POST /orders dengan cart_id dan shipping_address_id
2AC2: System memvalidasi semua item di cart masih tersedia (stok > 0)
3AC3: System membuat order record dengan status PENDING
4AC4: System mengurangi stok produk secara atomic
5AC5: System mempublish event ORDER_CREATED ke Kafka topic "orders"
6AC6: System mengembalikan order_id dan total_amount_centsSetiap AC di atas bisa langsung dijadikan checklist verifikasi maupun test case — inilah yang hilang di vibe coding. Komponen ketiga, Edge Cases, menangkap kondisi batas yang paling sering terlewat saat coding tanpa spec.
1EC1: Jika salah satu item kehabisan stok saat checkout, tolak seluruh order
2EC2: Jika user tidak punya shipping address, kembalikan 422
3EC3: Concurrent checkout untuk item stok terakhir — hanya satu yang berhasilDengan ketiga komponen ini, setiap keputusan implementasi punya dasar yang jelas dan AI tidak perlu menebak apa pun.
01.4 Perbandingan Langsung: Skenario Nyata di Santekno Shop
Mari kita lihat perbedaan konkret dengan skenario yang sama: implementasi fitur “tambah produk ke cart.”
Pendekatan Vibe Coding
Dengan vibe coding, kita langsung melempar prompt satu kalimat ke AI. Prompt berikut terlihat cukup, padahal menyembunyikan sederet keputusan penting yang tidak pernah dijawab.
1Prompt: "Buatkan endpoint POST /cart/items untuk tambah produk ke cart"
2
3[AI menghasilkan kode tanpa tahu:]
4- Apakah satu produk bisa ditambah berkali-kali (qty += 1) atau create entry baru?
5- Berapa maksimum item per cart?
6- Apa yang terjadi jika produk tidak aktif?
7- Apakah user yang belum login bisa punya cart (guest cart)?
8- Format response setelah tambah — hanya cart_item_id atau seluruh cart?Hasilnya mungkin jalan, tapi behavior-nya tidak terdefinisi dengan jelas. Dan dua bulan kemudian, saat ada bug “user bisa tambah produk inactive,” tidak ada yang tahu apakah itu bug atau intentional.
Pendekatan SDD
Di SDD, sebelum prompt ke AI kita tulis spec dulu di specs/cart/add-to-cart.md. Spesifikasi berikut menjawab setiap pertanyaan yang tadi menggantung di pendekatan vibe coding.
1### User Story
2Sebagai customer, saya ingin menambahkan produk ke cart
3agar saya bisa membelinya nanti dalam satu transaksi.
4
5### Acceptance Criteria
6- AC1: POST /cart/items menerima { product_id, quantity }
7- AC2: Jika produk sudah ada di cart, tambahkan quantity (qty += input.quantity)
8- AC3: Jika produk belum ada, buat cart_item baru
9- AC4: Maksimum total item unik per cart: 50 — tolak dengan 422 jika melebihi
10- AC5: Produk dengan status INACTIVE tidak bisa ditambah — 422
11- AC6: Stok tidak dikurangi di sini, hanya saat checkout
12- AC7: Response: cart_item { id, product_id, product_name, quantity, price_cents }
13
14### Edge Cases
15- EC1: quantity input <= 0 → 400 Bad Request
16- EC2: quantity input > stok tersedia → 422 dengan pesan "stok tidak cukup"
17- EC3: product_id tidak ada → 404
18- EC4: User belum login → 401 (tidak ada guest cart untuk sekarang)Perhatikan tidak ada satu pun keputusan behavior yang diserahkan ke AI — semuanya sudah kamu putuskan lebih dulu. Barulah setelah spec siap, kita kirim prompt yang mereferensikan spec dan pola kode yang sudah ada.
1Berdasarkan spec di specs/cart/add-to-cart.md, implementasikan POST /cart/items.
2Stack: Echo v4, pgx/v5, Clean Architecture.
3Referensi pattern: internal/usecase/product/add_product.goHasilnya kode yang ter-traceable ke setiap AC, tanpa ambiguitas — dan kalau ada bug, kamu tahu persis AC mana yang dilanggar.
01.5 Mengapa Engineer Senior Lebih Produktif dengan SDD
Counter-intuitive tapi nyata: engineer senior yang sudah expert justru lebih antusias mengadopsi SDD dibanding junior yang baru coba AI. Kenapa?
Mereka tahu cost of ambiguity. Senior engineer pernah merasakan bug production yang terjadi bukan karena kode salah, tapi karena behavior yang diasumsikan berbeda antar tim. Spec mengeliminasi class of bug ini sepenuhnya.
Mereka berpikir dalam sistem, bukan fungsi. SDD memaksa kita berpikir tentang bagaimana komponen berinteraksi sebelum detail implementasi — persis seperti cara senior engineer berpikir secara natural.
Mereka menghargai reviewability. Saat code review, “apakah kode ini sesuai spec?” jauh lebih objektif dan efisien daripada “apakah kode ini yang kita inginkan?” SDD membuat code review lebih cepat dan kurang politik.
Mereka sudah pernah bayar technical debt. Senior engineer tahu bahwa 10 menit menulis spec sekarang bisa menghemat 2 hari debugging nanti. Math-nya jelas.
Mereka paham bahwa AI butuh context. Setelah beberapa bulan pakai AI coding assistant, engineer yang experienced tahu bahwa kualitas output AI sangat bergantung pada seberapa jelas context yang diberikan. Spec adalah cara paling efisien memberikan context tersebut.
01.6 Tabel Perbandingan Komprehensif
Setelah membahas keduanya dari sisi pengalaman, tabel berikut menyandingkan vibe coding dan SDD pada dimensi-dimensi yang paling menentukan di proyek production.
| Dimensi | Vibe Coding | Specification-Driven Development |
|---|---|---|
| Titik Mulai | Langsung prompt ke AI | Tulis spec dulu, baru prompt |
| Konteks AI | Bergantung ingatan sesi | Selalu ada di file spec |
| Verifikasi | “Kelihatannya benar” | Checklist AC yang terukur |
| Edge Cases | Sering terlewat | Didefinisikan eksplisit |
| Debugging | Tidak ada baseline “behavior benar” | Bandingkan dengan spec |
| Onboarding tim | Baca kode, tebak intensi | Baca spec, intensi langsung jelas |
| Refactoring | Berbahaya tanpa test | Aman — spec adalah safety net |
| Code Review | Subjektif dan politis | Objektif — vs spec |
| AI Context | Menguap di sesi panjang | Konsisten — selalu reference spec |
| Skalabilitas | Sulit di tim besar | Dirancang untuk tim |
| Best for | Prototyping, eksplorasi | Production systems |
| Learning curve | Rendah | Sedang (worth it) |
Pola dari tabel ini jelas: vibe coding menang di kecepatan awal dan barrier rendah, sementara SDD unggul di setiap dimensi yang menentukan umur panjang dan kesehatan sistem.
01.7 Kapan Vibe Coding Masih Masuk Akal
SDD bukan solusi untuk semua situasi. Ada konteks di mana vibe coding masih lebih tepat:
Prototyping dalam 2-4 jam. Ketika kamu cuma mau validasi apakah sebuah ide teknikal layak dilakukan, spec bisa menunggu.
Script sekali pakai. Migrasi data satu kali, utility internal yang hidup sehari — tidak perlu spec formal.
Eksplorasi library baru. Mau lihat bagaimana cara pakai library X? Vibe coding untuk belajar, SDD untuk build.
Solo project yang tidak akan ke production. Side project experiment pribadi — bebas pilih pendekatan manapun.
Aturan praktisnya: Jika kode itu akan disentuh lebih dari satu orang, atau akan berjalan di production lebih dari satu bulan, gunakan SDD.
01.8 Peta Seri Ini: 20 Artikel yang Akan Kita Tempuh
Topik 1 ini terdiri dari 20 artikel yang dibagi empat part:
Part 1 — Mindset Shift (Artikel 01–04) Dari cara berpikir lama ke cara berpikir baru. Kenapa SDD, apa itu spec sebagai source of truth, landscape tools 2025, dan setup CLAUDE.md.
Part 2 — Menulis Spesifikasi Efektif (Artikel 05–09) Anatomi spec yang baik, prompt engineering untuk spec, teknik klarifikasi, OpenAPI contract-first design, dan spec non-fungsional.
Part 3 — Dari Spec ke Go Code (Artikel 10–15) Plan Mode, task breakdown, iterative code generation, TDD dari spec, code review berbasis spec, dan refactoring yang aman.
Part 4 — SDD di Skala Tim (Artikel 16–20) Microservice API contract, spec drift detection, SDD di tim, studi kasus end-to-end, dan bridge ke topik selanjutnya.
Proyek yang kita bangun sepanjang seri ini: Santekno Shop — platform e-commerce dengan Order Service, Product Service, dan User Service menggunakan Go 1.22+, PostgreSQL dengan pgx/v5, Echo v4, dan Kafka.
01.9 Pergeseran Mindset yang Dibutuhkan
Adopsi SDD bukan hanya perubahan workflow — ini perubahan cara berpikir tentang apa artinya “memulai” sebuah fitur.
Sebelum SDD: “Fitur dimulai saat kode pertama ditulis.” Setelah SDD: “Fitur dimulai saat spec pertama diklarifikasi.”
Pergeseran ini punya implikasi besar pada di mana waktu kamu habiskan. Kedua timeline berikut membandingkan alur kerja yang sama dari sisi durasi tiap tahap.
1Vibe Coding Timeline:
2[Prompt] → [Code] → [Test] → [Bug] → [Fix] → [Bug lagi] → [Prod]
3 5 min 5 min 30 min 2 jam 4 jam 2 jam ...
4
5SDD Timeline:
6[Spec] → [Review] → [Plan] → [Code] → [Test vs Spec] → [Prod]
7 20 min 15 min 10 min 30 min 30 min ✓Perhatikan SDD punya investasi di depan lebih besar, tapi mengeliminasi siklus bug yang berulang. Net result: lebih cepat sampai production dengan kualitas lebih tinggi.
Pergeseran kedua yang sama pentingnya: AI adalah executor, bukan decision-maker. Di vibe coding, AI memutuskan bagaimana fitur bekerja karena tidak ada panduan lain. Di SDD, kamu yang memutuskan (via spec), AI yang mengeksekusi. Perbedaan ini fundamental — dan menentukan siapa yang sebenarnya “in control” atas sistem yang kamu bangun.
01.10 Memulai SDD Tanpa Mengubah Seluruh Workflow
Kabar baiknya: kamu tidak perlu grand transformation untuk mulai. Ada satu kebiasaan sederhana yang bisa dimulai hari ini.
Sebelum menulis satu prompt pun ke AI, tuliskan tiga hal ini:
- Satu kalimat user story (siapa, apa, mengapa)
- Tiga acceptance criteria minimum (AC1, AC2, AC3)
- Satu edge case minimum
Itu saja — bahkan tanpa tool khusus, cukup teks di notepad, 10 menit sebelum coding. Contoh minimal berikut untuk fitur “update profil user” menunjukkan seberapa ringkas spec yang sudah cukup berguna.
1# Feature: Update profil user
2
3User story: Sebagai user terdaftar, saya ingin update nama dan foto profil
4agar informasi akun saya selalu terkini.
5
6AC1: PUT /users/me menerima { name?, avatar_url? } — keduanya opsional
7AC2: name tidak boleh kosong jika disertakan (min 2, max 100 karakter)
8AC3: Setelah update, return profil terbaru dengan semua field
9
10EC1: avatar_url harus valid URL format — 422 dengan pesan jelas jika tidakMinimal, tapi cukup untuk membuat AI menghasilkan kode yang jauh lebih tepat sasaran. Tidak ada lagi tebak-tebakan tentang validasi dan response format.
01.11 Santekno Shop: Proyek yang Akan Kita Bangun Bersama
Sepanjang 20 artikel ini, kita membangun satu proyek nyata: Santekno Shop, platform e-commerce sederhana dengan arsitektur microservice. Daftar stack berikut adalah pondasi teknikal yang akan kita pakai konsisten di seluruh seri.
1Language: Go 1.22+
2Framework: Echo v4 (HTTP), chi (alternative)
3Database: PostgreSQL (pgx/v5), Redis (go-redis/v9)
4Messaging: Apache Kafka (confluent-kafka-go)
5Auth: JWT (golang-jwt/jwt/v5)
6Testing: testify/suite, gomock
7ID: github.com/google/uuid
8Linting: golangci-lintStack ini sengaja dipilih karena mewakili setup production Go yang umum di industri Indonesia, sehingga polanya langsung relevan dengan pekerjaan harianmu. Di atas fondasi itu, dua domain entity inti berikut menjadi model utama yang berkembang sepanjang seri.
1// internal/domain/product/entity.go
2package product
3
4import (
5 "time"
6 "github.com/google/uuid"
7)
8
9type Status string
10const (
11 StatusActive Status = "ACTIVE"
12 StatusInactive Status = "INACTIVE"
13)
14
15type Product struct {
16 ID uuid.UUID
17 Name string
18 SKU string
19 PriceCents int64 // harga dalam sen, bukan float
20 Stock int
21 CategoryID uuid.UUID
22 Status Status
23 CreatedBy uuid.UUID
24 CreatedAt time.Time
25 UpdatedAt time.Time
26}
27
28// internal/domain/order/entity.go
29package order
30
31type Status string
32const (
33 StatusPending Status = "PENDING"
34 StatusConfirmed Status = "CONFIRMED"
35 StatusShipped Status = "SHIPPED"
36 StatusDelivered Status = "DELIVERED"
37 StatusCancelled Status = "CANCELLED"
38)
39
40type Order struct {
41 ID uuid.UUID
42 UserID uuid.UUID
43 Status Status
44 TotalAmountCents int64
45 Items []OrderItem
46 CreatedAt time.Time
47 UpdatedAt time.Time
48}
49
50type OrderItem struct {
51 ID uuid.UUID
52 OrderID uuid.UUID
53 ProductID uuid.UUID
54 ProductName string // snapshot saat order dibuat
55 Quantity int
56 PriceCents int64 // snapshot harga saat order dibuat
57}Perhatikan detail seperti PriceCents int64 dan snapshot harga di OrderItem — keputusan sekecil ini justru yang paling sering ambigu di vibe coding, dan justru yang paling tegas didefinisikan lewat spec. Struktur ini akan terus berkembang seiring artikel, dan setiap fitur yang kita bangun berasal dari spesifikasi yang jelas.
01.12 SDD dan Kecepatan: Mitos vs Realita
Keberatan paling umum terhadap SDD: “Nulis spec dulu lambat, vibe coding lebih cepat.” Mari kita ukur secara realistis dengan skenario “implementasi fitur cancel order.” Rincian waktu berikut adalah versi vibe coding, lengkap dengan biaya bug yang jarang ikut dihitung.
1Prompt + AI generate: 5 menit
2Revisi karena behavior salah: 30 menit
3Bug ditemukan QA: 2 jam debug
4Bug di production edge case: 4 jam + rollback + hotfix
5Dokumentasi yang akhirnya
6diperlukan juga: 1 jam
7Total: ~7.5 jamYang membuat vibe coding mahal bukan generate awalnya yang cepat, tapi ekor panjang revisi, debug, dan hotfix yang mengikutinya. Bandingkan dengan versi SDD untuk fitur yang sama berikut ini.
1Tulis spec + review: 20 menit
2Prompt ke AI dengan spec: 5 menit
3Review kode vs spec: 15 menit
4Test dari spec: 20 menit
5Total: ~1 jamIni bukan angka teoretis, melainkan pengalaman nyata tim engineering yang sudah mengadopsi SDD — investasi di depan (spec) selalu lebih murah dari biaya bug di belakang. Ada satu catatan penting: angka ini untuk fitur yang sudah punya spec yang baik. Jika spec-nya buruk atau ambigu, waktu bisa membengkak — dan inilah kenapa Part 2 seri ini (Artikel 05–09) fokus pada teknik menulis spec yang efektif.
01.13 SDD di Konteks High-Traffic System
Di perusahaan e-commerce Indonesia dengan jutaan transaksi per hari, SDD bukan luxury — ini necessity. Skenario berikut menggambarkan apa yang terjadi saat fitur checkout di-deploy tanpa spec tentang concurrency.
11. Feature checkout di-deploy tanpa spec tentang concurrent order handling
22. Flash sale produk limited edition: 10.000 concurrent request dalam 10 detik
33. Dua (atau lebih) request berhasil "beli" stok terakhir
4 karena tidak ada pessimistic locking atau proper transaction isolation
54. Hasilnya: oversell, manual refund, customer angry, reputasi rusak
65. Fix: 4 jam kerja emergency + rollback + hotfix deploymentRantai kegagalan itu bermula dari satu asumsi yang tidak pernah ditulis: “pasti aman kalau banyak yang checkout bersamaan.” Dengan SDD, edge case concurrent checkout wajib ada di spec sebelum coding, seperti potongan spec berikut.
1### Edge Cases untuk Create Order (Santekno Shop)
2
3- EC3: Concurrent checkout untuk item stok terakhir
4 → Implementasi: SELECT ... FOR UPDATE di dalam transaction
5 → Behavior: hanya satu request berhasil, yang lain mendapat 409 Conflict
6 → Error message: "produk {name} sudah habis terjual"
7
8- EC4: Checkout saat flash sale (request rate > 500 req/s untuk endpoint ini)
9 → Implementasi: rate limiting per user per endpoint (10 req/min)
10 → Behavior: 429 Too Many Requests jika melebihi limitKetika edge case ini ada di spec sebelum coding, developer tahu persis apa yang harus diimplementasikan. Tidak ada lagi asumsi “ah pasti handle sendiri” yang berujung insiden production.
01.14 Integrasi SDD dengan Existing Workflow
SDD tidak perlu menggantikan seluruh workflow yang sudah ada. Ini cara mengintegrasikannya secara bertahap tanpa disruption:
Sprint Planning: Tambahkan “spec review” sebagai bagian DoD (Definition of Done). Ticket tidak bisa masuk sprint kecuali specnya sudah ditulis dan di-review oleh minimal satu orang lain.
Code Review: Tambahkan kolom spec compliance ke PR template. Reviewer mengecek: apakah setiap AC punya implementasi yang bisa ditelusuri? Apakah setiap EC di-handle?
Daily Standup: Ganti “kemarin saya coding X” dengan “kemarin saya finalisasi spec X dan implementasi AC1-AC3, hari ini lanjut AC4-AC6.” Progress lebih terukur.
Retrospective: Track berapa bug production yang terjadi karena “spec tidak jelas” vs “implementasi salah.” Data ini biasanya mengejutkan — dan langsung meyakinkan tim bahwa SDD worth it.
Perubahan ini incremental. Dalam 2-3 sprint, tim biasanya sudah mulai merasakan bedanya tanpa merasa dipaksa.
01.15 Hubungan SDD dengan TDD dan BDD
SDD bukan pengganti TDD (Test-Driven Development) atau BDD (Behavior-Driven Development) — ia komplementer terhadap keduanya.
SDD + TDD: Spec menyediakan test cases yang jelas. Setiap AC menjadi satu test function, setiap edge case menjadi test scenario. TDD menjadi lebih terarah karena tahu persis apa yang harus dites. Perhatikan bagaimana AC dan EC dari spec add-to-cart langsung menjelma menjadi nama-nama test berikut.
1// Dari spec add-to-cart.md
2// AC2: "jika produk sudah ada di cart, tambahkan quantity"
3func TestAddToCart_ExistingProduct_IncrementQuantity(t *testing.T) {
4 // Given: cart dengan produk A (qty=2)
5 // When: tambah produk A dengan qty=3
6 // Then: cart_item produk A memiliki qty=5
7}
8
9// EC1: "quantity input <= 0 → 400 Bad Request"
10func TestAddToCart_ZeroQuantity_Returns400(t *testing.T) { ... }
11func TestAddToCart_NegativeQuantity_Returns400(t *testing.T) { ... }Nama test yang menempel pada nomor AC/EC membuat traceability dua arah: dari spec kamu tahu test mana yang menutupinya, dari test kamu tahu behavior mana yang diverifikasi. SDD + BDD: BDD tools seperti Gherkin bisa digunakan untuk menulis spec dalam format Given-When-Then — SDD memberikan konten, BDD memberikan format yang lebih structured. Di seri ini kita fokus pada pendekatan pragmatis: spec sebagai Markdown dengan AC yang clear dan explicit, tanpa framework BDD penuh, tapi idenya sama.
01.16 Tooling: Apa yang Dibutuhkan untuk Mulai
Kabar baiknya: tooling minimum untuk SDD hampir tidak ada. Struktur direktori berikut sudah cukup untuk memulai hari ini.
1├── specs/ ← folder ini saja sudah cukup untuk mulai
2│ └── domain/
3│ └── cart/
4│ └── add-to-cart.md
5├── CLAUDE.md ← panduan untuk Claude Code (Artikel 04)
6└── [kode kamu]Satu folder specs/ dan satu CLAUDE.md sudah membuat spec hidup berdampingan dengan kode di repo yang sama. Seiring proyek membesar, struktur berikut memberi ruang untuk template dan governance yang lebih rapi.
1├── specs/
2│ ├── README.md ← panduan cara baca & tulis spec
3│ ├── _templates/
4│ │ └── feature-spec.md ← template standar
5│ └── domain/
6│ ├── product/
7│ ├── order/
8│ └── cart/
9├── CLAUDE.md
10├── .github/
11│ └── PULL_REQUEST_TEMPLATE.md ← dengan kolom spec compliance
12└── scripts/
13 └── spec-audit.sh ← cek spec vs kodePerhatikan bahwa tidak ada satu pun elemen di struktur itu yang butuh tool berbayar atau layanan eksternal. Yang justru tidak dibutuhkan malah cukup panjang:
- Tool spec management khusus
- Jira plugin atau extension apapun
- Framework BDD
- Code generator dari spec
- Database atau backend khusus untuk menyimpan spec
SDD adalah pendekatan, bukan tool. Semua yang kamu butuhkan sudah ada di filesystem dan editor favoritmu.
01.17 Kesalahan Umum yang Perlu Dihindari
Dari pengalaman tim yang mengadopsi SDD, ada beberapa pitfall yang konsisten muncul.
Kesalahan 1: Spec terlalu detail tentang implementasi. Spec yang baik mendeskripsikan what, bukan how — bandingkan dua gaya penulisan berikut.
1❌ "Gunakan SELECT FOR UPDATE dengan isolation level SERIALIZABLE"
2✅ "Concurrent checkout untuk stok terakhir — hanya satu yang berhasil"Spec tentang what membebaskan implementer (atau AI) untuk memilih solusi terbaik tanpa terkunci pada satu teknik. Kesalahan 2: AC yang tidak measurable. AC harus bisa diverifikasi dengan angka atau kondisi konkret, seperti perbandingan berikut.
1❌ AC: "Sistem harus cepat dan responsif"
2✅ AC: "Response time < 500ms untuk 95th percentile di load test 100 concurrent users"AC yang measurable bisa langsung dijadikan test dan gate CI, sementara AC yang kabur hanya jadi bahan debat subjektif. Tiga kesalahan berikutnya lebih bersifat kebiasaan tim:
Kesalahan 3: Spec tidak di-update setelah implementasi berubah. Spec yang stale lebih berbahaya dari tidak ada spec — karena menciptakan false confidence. Setiap perubahan behavior harus diikuti update spec, bukan hanya update kode.
Kesalahan 4: Spec terlalu panjang dan monolitik. Spec yang butuh 30 menit untuk dibaca perlu dipecah. Target: satu spec bisa dibaca dan dipahami dalam 5-10 menit.
Kesalahan 5: Skip spec untuk fitur “kecil”. Tidak ada fitur yang terlalu kecil untuk punya AC. Bahkan endpoint sederhana bisa punya 3-4 AC yang non-obvious dan menjadi sumber bug.
01.18 Tips & Gotchas
💡 Tip 1: Mulai dari edge case, bukan happy path. Happy path biasanya intuitif — developer sudah membayangkannya secara otomatis. Yang sering bikin bug production adalah edge case yang tidak terpikir saat coding. Tulis EC dulu, AC akan lebih mudah menyusul.
💡 Tip 2: Gunakan angka spesifik di AC. “Response time yang baik” tidak jelas; “< 200ms untuk p95 di 100 RPS” jelas dan testable. Angka spesifik juga membantu AI menghasilkan implementasi yang tepat.
💡 Tip 3: Satu PR, satu spec (atau satu bagian spec). Jangan campur implementasi dua fitur berbeda dalam satu PR. Satu PR harus bisa di-trace ke satu spec — ini membuat code review dan rollback jauh lebih mudah.
💡 Tip 4: Review spec dengan orang non-teknikal. Jika product manager atau QA tidak bisa mengerti spec kamu, spec itu terlalu teknikal. Spec yang baik bisa dipahami oleh siapapun yang memahami bisnis domain.
💡 Tip 5: Jadikan spec review bagian dari ritual tim, bukan afterthought. Blokir 15-30 menit di awal setiap sprint untuk spec review bersama. Ini investasi yang return-nya langsung terasa dalam minggu-minggu berikutnya.
⚠️ Gotcha 1: Spec bukan pengganti komunikasi. Spec mengurangi ambiguitas, tapi tidak menghilangkan kebutuhan diskusi. Tetap butuh sync dengan stakeholder sebelum spec di-finalize — spec adalah output dari diskusi, bukan pengganti diskusi.
⚠️ Gotcha 2: AI bisa salah interpretasi spec yang sudah jelas sekalipun. Bahkan dengan spec yang jelas, AI kadang salah interpretasi edge case yang subtle. Selalu review output AI vs spec secara manual untuk setiap AC kritis. Jangan assume AI sudah benar.
⚠️ Gotcha 3: Spec debt sama buruknya dengan technical debt. Menumpuk spec yang belum di-update sama berbahayanya dengan menumpuk technical debt. Budget waktu untuk maintain spec sama seperti maintain kode — ini bukan optional.
⚠️ Gotcha 4: Jangan biarkan AI menulis spec dari deskripsi yang ambigu. AI bisa draft spec, tapi kamu yang harus memutuskan setiap keputusan bisnis di dalamnya. Jangan delegate keputusan produk ke AI — AI bisa bantu format spec, bukan konten bisnis spec.
01.19 SDD untuk Engineer dengan Background Laravel/PHP
Banyak pembaca Santekno datang dari background Laravel. Ada beberapa analogi yang membantu transisi ke SDD mindset dalam konteks Go.
Laravel Form Request ≈ Acceptance Criteria untuk validasi input. Di Laravel, FormRequest mendefinisikan apa yang valid lewat method rules(), seperti contoh berikut.
1// Laravel FormRequest
2public function rules(): array {
3 return [
4 'product_id' => 'required|uuid|exists:products,id',
5 'quantity' => 'required|integer|min:1',
6 ];
7}Rules di atas ringkas, tapi hanya menutup validasi input dan menyembunyikan behavior lain di dalam controller. Di SDD, AC mendefinisikan hal yang sama secara lebih eksplisit dan mencakup behavior menyeluruh.
1AC1: POST /cart/items menerima { product_id (UUID, wajib), quantity (int, min 1, wajib) }
2EC1: quantity <= 0 → 400 dengan message "quantity harus lebih dari 0"
3EC3: product_id tidak ada di DB → 404 dengan message "produk tidak ditemukan"Perhatikan AC menuliskan status code dan pesan error secara gamblang — hal yang di Laravel sering tersirat lewat konvensi. Laravel Policy ≈ AC untuk authorization. Policy::authorize() menentukan siapa boleh melakukan apa, dan di SDD ini menjadi AC eksplisit seperti berikut.
1AC: Hanya user dengan role ADMIN atau role PRODUCT_MANAGER yang bisa
2 mengubah status produk. User dengan role lain → 403 Forbidden.Aturan otorisasi yang eksplisit begini menghilangkan zona abu-abu “siapa sebenarnya yang boleh” yang sering jadi sumber bug keamanan. Laravel Resource ≈ AC untuk response format. JsonResource mendefinisikan bentuk data yang dikembalikan, dan di SDD ini ditulis sebagai AC response berikut.
1AC6: Response sukses mengembalikan:
2 { cart_item_id, product_id, product_name, quantity, price_cents, subtotal_cents }Dengan response format ditetapkan di spec, frontend dan backend bisa bekerja paralel tanpa saling menunggu implementasi. Perbedaan mendasarnya: Laravel punya conventions kuat yang sering menggantikan spec eksplisit, sedangkan Go lebih minimalis — conventions tidak se-kuat Laravel, sehingga spec menjadi lebih penting untuk menjaga konsistensi tim. Transition advice: di proyek Laravel lama yang mau di-port ke Go, jadikan behavior eksisting sebagai starting point spec — “bagaimana Laravel menangani ini sekarang?” ditulis sebagai AC untuk versi Go.
01.20 Ringkasan
Di artikel pembuka ini, kita telah membangun fondasi pemahaman tentang SDD:
Vibe coding efektif untuk eksplorasi, berbahaya untuk production — karena ambiguitas menumpuk, konteks AI menguap, dan tidak ada baseline verifikasi yang objektif.
SDD membalikkan urutan: spec dulu, code kemudian. Tiga komponen wajib: User Story, Acceptance Criteria, dan Edge Cases. Dengan ketiganya, AI menjadi executor yang terarah, bukan pengambil keputusan yang menebak-nebak.
Engineer senior mengadopsi SDD bukan karena ingin lambat, tapi karena sudah pernah merasakan cost of ambiguity di production. Investasi 20 menit menulis spec menghemat jam-jam debugging dan hotfix.
Mulai sekarang dengan kebiasaan sederhana: sebelum prompt ke AI, tulis 1 user story + 3 AC + 1 EC. Tidak perlu tool khusus. Tidak perlu mengubah seluruh workflow. Hanya kebiasaan kecil yang dampaknya besar.
Di artikel berikutnya, kita akan mendalami konsep spesifikasi sebagai source of truth — apa artinya secara operasional, mengapa ini penting di tim yang bergerak cepat, dan bagaimana membangun sistem governance spec yang tidak memberatkan.