<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: guo king</title>
    <description>The latest articles on Forem by guo king (@guo_king_5d052f0d094fe6ca).</description>
    <link>https://forem.com/guo_king_5d052f0d094fe6ca</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3821717%2F7515d03c-5d13-4159-91db-fc69dd0d4446.png</url>
      <title>Forem: guo king</title>
      <link>https://forem.com/guo_king_5d052f0d094fe6ca</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/guo_king_5d052f0d094fe6ca"/>
    <language>en</language>
    <item>
      <title>I Shipped Fewer Bugs After I Started Writing Specs — Here's the Framework</title>
      <dc:creator>guo king</dc:creator>
      <pubDate>Wed, 01 Apr 2026 09:48:53 +0000</pubDate>
      <link>https://forem.com/guo_king_5d052f0d094fe6ca/i-shipped-fewer-bugs-after-i-started-writing-specs-heres-the-framework-4ll4</link>
      <guid>https://forem.com/guo_king_5d052f0d094fe6ca/i-shipped-fewer-bugs-after-i-started-writing-specs-heres-the-framework-4ll4</guid>
      <description>&lt;h1&gt;
  
  
  I Shipped Fewer Bugs After I Started Writing Specs — Here's the Framework
&lt;/h1&gt;

&lt;p&gt;Last March, we had a billing incident that cost us three days. A rounding error in our invoice calculation was silently overcharging customers by fractions of a cent. Not enough for anyone to notice on a single invoice — but multiplied across thousands of transactions over two months, it added up. We had to issue refunds, write a post-mortem, and rebuild trust with a handful of enterprise customers who did the math.&lt;/p&gt;

&lt;p&gt;The fix took 20 minutes. The actual bug was a &lt;code&gt;Math.floor()&lt;/code&gt; where we needed &lt;code&gt;Math.round()&lt;/code&gt; with banker's rounding.&lt;/p&gt;

&lt;p&gt;Here's what stung: if anyone had written down "use banker's rounding for currency calculations" before writing the code, this never would have shipped. The developer who wrote it didn't know about our rounding convention. The reviewer didn't think to check. Nobody was wrong — the requirement just lived in one person's head and never made it to the keyboard.&lt;/p&gt;

&lt;p&gt;That incident changed how our team builds software.&lt;/p&gt;

&lt;h2&gt;
  
  
  What spec-first actually means
&lt;/h2&gt;

&lt;p&gt;Spec-first development is simple: before you write code, you write a short document describing what you're building, what you're not building, and how you'll know it works.&lt;/p&gt;

&lt;p&gt;It's not waterfall. It's not Big Design Up Front. It's 10 minutes of structured thinking in a text file before you open your editor. Think of it as a conversation with your future self and your reviewers — except you have it before you've sunk 8 hours into an implementation.&lt;/p&gt;

&lt;p&gt;The spec travels with the PR. It's a living artifact, not a bureaucratic gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example: CRM contact deduplication
&lt;/h2&gt;

&lt;p&gt;One of our team members picked up a ticket to build contact deduplication for our internal CRM. On the surface, it seemed straightforward: find duplicate contacts, merge them. Here's the abbreviated spec she wrote before starting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Goal&lt;/span&gt;
Detect and merge duplicate contacts in the CRM based on email
and phone number matching.

&lt;span class="gu"&gt;## Non-goals&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Fuzzy name matching (phase 2)
&lt;span class="p"&gt;-&lt;/span&gt; Automated merging without user confirmation
&lt;span class="p"&gt;-&lt;/span&gt; Deduplication of company records

&lt;span class="gu"&gt;## Acceptance Criteria&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Two contacts with the same email (case-insensitive) are flagged as duplicates
&lt;span class="p"&gt;-&lt;/span&gt; Two contacts with the same phone number (normalized to E.164) are flagged
&lt;span class="p"&gt;-&lt;/span&gt; User sees a side-by-side comparison and chooses which fields to keep
&lt;span class="p"&gt;-&lt;/span&gt; Merge preserves all activity history from both records
&lt;span class="p"&gt;-&lt;/span&gt; Merge is reversible for 30 days

&lt;span class="gu"&gt;## Edge Cases&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Contact A has email X, Contact B has email X and email Y —
  what happens to email Y after merge?
&lt;span class="p"&gt;-&lt;/span&gt; Three-way duplicates: A matches B, B matches C, but A doesn't match C
&lt;span class="p"&gt;-&lt;/span&gt; Contact with 500+ activities — does the merge UI choke?
&lt;span class="p"&gt;-&lt;/span&gt; Merged contact is referenced in active automation workflows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That spec took about 12 minutes to write. But look at what it caught before a single line of code was written:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The three-way duplicate problem.&lt;/strong&gt; Without the spec, the developer would have built a pairwise merge and discovered the transitive matching issue during QA — or worse, in production when a user tried to merge a chain of duplicates and got inconsistent results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The automation workflow reference.&lt;/strong&gt; Contacts linked to active automations needed special handling. That requirement wasn't in the ticket. It came out of the developer thinking through edge cases while writing the spec. Without it, merging a contact mid-automation would have broken running workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reversibility requirement.&lt;/strong&gt; The original ticket said nothing about undo. But when you write "acceptance criteria," you start thinking about what happens when things go wrong. Thirty days of reversibility turned out to be a key requirement from the customer success team — the developer discovered this during a quick spec review before starting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The template
&lt;/h2&gt;

&lt;p&gt;After six months of iteration, our team settled on a lightweight template. Here's the version we use for any feature that takes more than a couple of hours:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Feature: [Name]&lt;/span&gt;
&lt;span class="gs"&gt;**Author:**&lt;/span&gt; [Your name]
&lt;span class="gs"&gt;**Date:**&lt;/span&gt; [Today]
&lt;span class="gs"&gt;**Status:**&lt;/span&gt; Draft / In Review / Approved

&lt;span class="gu"&gt;## Goal&lt;/span&gt;
One paragraph. What are we building and why?

&lt;span class="gu"&gt;## Non-goals&lt;/span&gt;
What are we explicitly NOT doing? (This prevents scope creep.)

&lt;span class="gu"&gt;## Acceptance Criteria&lt;/span&gt;
Numbered list. How do we know this is done?

&lt;span class="gu"&gt;## Edge Cases&lt;/span&gt;
Bullet list. What weird inputs, states, or timing issues could break this?

&lt;span class="gu"&gt;## Rollout&lt;/span&gt;
How does this get to production? Feature flag? Percentage rollout?
Who monitors it?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Five sections. One page. The non-goals section alone has saved us more rework than any other practice we've adopted. When someone suggests "hey, we should also handle X" during implementation, we check the non-goals list. If X is there, the answer is "not this PR." If it's not there and it should be, we update the spec and have that conversation before writing more code.&lt;/p&gt;

&lt;p&gt;I've published &lt;a href="https://spec-coding.dev/guides/spec-template-examples" rel="noopener noreferrer"&gt;the full template with examples&lt;/a&gt; if you want to grab it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Six months of results
&lt;/h2&gt;

&lt;p&gt;We started using specs consistently in October 2025 across a team of eight engineers. Here's what changed by April 2026:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P1 incidents dropped from ~3/month to ~1/month.&lt;/strong&gt; Not all of that is attributable to specs — we also improved our CI pipeline. But the incidents we did have were operational (infrastructure, scaling) rather than "we built the wrong thing" or "we missed an edge case."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code review cycles got shorter.&lt;/strong&gt; Average time from PR open to merge went from 2.1 days to 1.4 days. Reviewers stopped asking "what is this supposed to do?" because the spec was right there. Reviews focused on implementation quality instead of requirements discovery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Junior engineers ramped faster.&lt;/strong&gt; Two new hires in January were writing production specs within their second week. The specs gave them a structured way to demonstrate understanding before writing code — and gave senior engineers a concrete artifact to review instead of trying to evaluate whether someone "gets it" from a Slack conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope creep became visible.&lt;/strong&gt; When a feature grew beyond its original spec, we could point to the document and say "this is new scope — do we want to update the spec or save it for a follow-up?" Before specs, scope crept silently until the PR was twice the expected size.&lt;/p&gt;

&lt;p&gt;The biggest surprise: specs made estimation better. When you force yourself to list acceptance criteria and edge cases upfront, you have a much clearer picture of the actual work. Our sprint velocity predictions got noticeably more accurate — not because we got better at estimating, but because we got better at understanding what we were estimating.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;If you've never written a spec before, don't try to change your whole team overnight. Start with yourself, on one feature. Pick something you're about to build that has at least a couple of moving parts. Spend 10 minutes filling in the template above. Share it with whoever would review your PR and ask: "Does this match your understanding?"&lt;/p&gt;

&lt;p&gt;That one conversation will tell you whether spec-first development is worth adopting more broadly. In my experience, it always is.&lt;/p&gt;

&lt;p&gt;I've written a &lt;a href="https://spec-coding.dev/blog/what-is-spec-first-development-complete-guide" rel="noopener noreferrer"&gt;complete guide to spec-first development&lt;/a&gt; that covers the philosophy, the process, and the common objections. And the &lt;a href="https://spec-coding.dev/blog/software-spec-template-free-download" rel="noopener noreferrer"&gt;template is free to download&lt;/a&gt; — take it, modify it, make it yours.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Daniel Marsh is a software engineer and the author of &lt;a href="https://spec-coding.dev" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;, a resource for teams adopting spec-first development.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>documentation</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>What Is Spec-First Development? (Complete Guide)</title>
      <dc:creator>guo king</dc:creator>
      <pubDate>Sat, 14 Mar 2026 02:43:23 +0000</pubDate>
      <link>https://forem.com/guo_king_5d052f0d094fe6ca/what-is-spec-first-development-complete-guide-41nd</link>
      <guid>https://forem.com/guo_king_5d052f0d094fe6ca/what-is-spec-first-development-complete-guide-41nd</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://spec-coding.dev/blog/what-i&amp;lt;br&amp;gt;%0A%20%20s-spec-first-development-complete-guide" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Spec-first development becomes clearer when the team makes the &lt;strong&gt;hidden&lt;br&gt;
  decisions visible before coding starts&lt;/strong&gt;. This article focuses on those&lt;br&gt;
  decisions and why they matter in delivery.&lt;/p&gt;

&lt;p&gt;## 1. Why Teams Usually Get This Wrong&lt;/p&gt;

&lt;p&gt;The problem appears the moment more than one role depends on the answer.&lt;br&gt;
  Product wants speed, engineering wants boundaries, QA wants testability, and&lt;br&gt;
  operations wants something that can be rolled back without improvisation. If&lt;br&gt;
  the spec never resolves those tensions, the work moves downstream as rework.&lt;/p&gt;

&lt;p&gt;The real decision behind spec-first is &lt;strong&gt;ownership&lt;/strong&gt;. Who approves the&lt;br&gt;
  boundary? Who validates acceptance criteria? Who can stop a rollout? Without&lt;br&gt;
  those answers in writing, teams ship with blurred accountability.&lt;/p&gt;

&lt;p&gt;## 2. A Concrete Delivery Situation&lt;/p&gt;

&lt;p&gt;Test your spec against one realistic delivery path. Ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What can the reviewer &lt;strong&gt;reject&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;What can the tester &lt;strong&gt;verify&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;What can the operator &lt;strong&gt;roll back&lt;/strong&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the document cannot answer those three angles, it is not ready. Stop asking&lt;br&gt;
   whether the team "understands the idea" and start asking whether the written&lt;br&gt;
  spec would survive handoff.&lt;/p&gt;

&lt;p&gt;## 3. What the Spec Needs to Say Out Loud&lt;/p&gt;

&lt;p&gt;A stronger spec is not longer by accident — it is more explicit exactly where&lt;br&gt;
  projects tend to drift. At minimum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The intended outcome, explicit &lt;strong&gt;non-goals&lt;/strong&gt;, and the decision owner for
scope changes&lt;/li&gt;
&lt;li&gt;Acceptance criteria that can be judged &lt;strong&gt;pass or fail&lt;/strong&gt; without tribal
knowledge&lt;/li&gt;
&lt;li&gt;Failure behavior, fallback paths, and which logs or metrics will surface
them after release&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;## 4. Acceptance Criteria That Remove Guesswork&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Given the approved scope and dependencies
When the team executes the primary flow
Then success can be verified with a concrete result and observable evidence&lt;/li&gt;
&lt;li&gt;Given an exception, retry, or permission boundary is hit
When the system takes the fallback path
Then the user-facing behavior and operational response remain explicit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to force every team into the same wording. The goal is to&lt;br&gt;
  force decisions about &lt;strong&gt;input, trigger, and expected behavior&lt;/strong&gt; while there is&lt;br&gt;
   still time to change course cheaply.&lt;/p&gt;

&lt;p&gt;## 5. Review Questions Before Implementation Starts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which decision would still be &lt;strong&gt;ambiguous&lt;/strong&gt; to a reviewer seeing the change
for the first time?&lt;/li&gt;
&lt;li&gt;Can QA derive the main-flow, failure-path, and regression cases &lt;strong&gt;without
interviewing the author&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;If the release fails, does the document tell operations what to watch and
when to stop?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you cannot answer these without a side conversation, the draft is still&lt;br&gt;
  carrying unpriced uncertainty.&lt;/p&gt;

&lt;p&gt;## 6. Rollout, Monitoring, and Rollback&lt;/p&gt;

&lt;p&gt;Good specs do not stop at merge readiness. They tell the team how to release&lt;br&gt;
  safely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stage to the &lt;strong&gt;smallest useful audience&lt;/strong&gt; first — don't treat review
approval as a substitute for runtime evidence&lt;/li&gt;
&lt;li&gt;Name the &lt;strong&gt;stop-loss threshold&lt;/strong&gt; before release: error rate, latency, data
mismatch, or override volume&lt;/li&gt;
&lt;li&gt;Record what rollback actually means: code revert, config switch, job pause,
or data repair&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;## 7. Common Mistakes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treating scope as obvious and leaving the real policy decision for
implementation review&lt;/li&gt;
&lt;li&gt;Hiding risky edge behavior behind vague phrases like &lt;em&gt;reasonable&lt;/em&gt;,
&lt;em&gt;friendly&lt;/em&gt;, or &lt;em&gt;handled elsewhere&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Publishing a document that sounds complete but never states how success or
rollback will be judged&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;## 8. When to Go Deep vs. Stay Lightweight&lt;/p&gt;

&lt;p&gt;The right amount of detail is the amount that &lt;strong&gt;prevents expensive invention&lt;br&gt;
  later&lt;/strong&gt;. If a missing sentence would force engineering, QA, or operations to&lt;br&gt;
  guess — that sentence belongs in the spec.&lt;/p&gt;

&lt;p&gt;What matters is not document length. What matters is whether the document&lt;br&gt;
  prevents the team from rediscovering the same decision in implementation,&lt;br&gt;
  testing, and release review.&lt;/p&gt;

&lt;p&gt;## 9. Final Takeaway&lt;/p&gt;

&lt;p&gt;Spec-first development becomes easier once the spec names the risky decisions&lt;br&gt;
  early enough for someone to challenge them. That is the practical value:&lt;br&gt;
  &lt;strong&gt;less improvisation, fewer surprises in review, and cleaner evidence when it&lt;br&gt;
  is time to ship&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Daniel Marsh is a senior software engineer with 12 years of experience,&lt;br&gt;
  specializing in spec-first development. More articles at&lt;br&gt;
  &lt;a href="https://spec-coding.dev" rel="noopener noreferrer"&gt;spec-coding.dev&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
