惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
V2EX - 技术
V2EX - 技术
T
Threat Research - Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tor Project blog
Project Zero
Project Zero
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
P
Privacy & Cybersecurity Law Blog
AWS News Blog
AWS News Blog
Scott Helme
Scott Helme
C
Cisco Blogs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
O
OpenAI News
P
Privacy International News Feed
Google Online Security Blog
Google Online Security Blog
SecWiki News
SecWiki News
The Last Watchdog
The Last Watchdog
NISL@THU
NISL@THU
Attack and Defense Labs
Attack and Defense Labs
G
GRAHAM CLULEY
Security Latest
Security Latest
Help Net Security
Help Net Security
C
Cyber Attacks, Cyber Crime and Cyber Security
Hugging Face - Blog
Hugging Face - Blog
月光博客
月光博客
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
Arctic Wolf
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Security @ Cisco Blogs
腾讯CDC
S
Secure Thoughts
WordPress大学
WordPress大学
P
Proofpoint News Feed
H
Help Net Security
Simon Willison's Weblog
Simon Willison's Weblog
小众软件
小众软件
M
MIT News - Artificial intelligence
博客园 - 叶小钗
IT之家
IT之家
G
Google Developers Blog
博客园 - 聂微东
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Google DeepMind News
Google DeepMind News
N
News and Events Feed by Topic
N
News and Events Feed by Topic

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Writing Features Not Tasks
Steve McDoug · 2026-05-19 · via DEV Community

If you have ever looked at a ticket in your backlog and felt genuinely unsure where to start, there is a good chance the ticket was written as a task rather than a feature. It is one of the most common sources of confusion for junior developers, and it is almost never talked about directly.

The difference matters more than you might think. Tasks describe what to build. Features describe why it needs to exist and what it should enable. That distinction changes everything from how you estimate work, to how you test it, to how you know when you are actually done.

In this article we are going to look at what a properly written feature actually looks like, introduce the concept of user stories as a tool for capturing them, and apply all of it to Clarity using the confirmed assumptions we established in the last article.

Tasks vs Features

Let me show you the difference with a concrete example.

Here is a task:

Add a status column to the requests table.

Here is the same thing written as a feature:

As a client, I want to see the current status of my submitted request, so that I know whether the team has started working on it.

The task tells a developer to do something. The feature tells everyone involved why it matters, who benefits from it, and what outcome it is trying to produce.

That distinction has real consequences. If I hand you a task, you can complete it and technically be done. You can add the column, run the migration, and close the ticket. But you have not built anything a user can actually interact with. The feature, on the other hand, only counts as done when a client can log in, find their request, and read a meaningful status value. That is a fundamentally different definition of done.

The format I just used has a name. It is a user story.

What a User Story Actually Is

A user story follows a simple template:

As a [type of user], I want to [do something], so that [I achieve some goal].

Each part of that template is doing a specific job.

The actor ("as a client") anchors the story to a real person in your system with a real perspective. It forces you to think about who is actually going to use this thing, rather than thinking about it in the abstract.

The action ("I want to see the current status") describes the behaviour the system needs to support. It is written from the user's point of view, not the developer's. You will notice it says "see the status", not "query the status from the database". That is deliberate. Implementation details do not belong in a user story.

The goal ("so that I know whether the team has started working on it") is the part most people skip, and it is often the most valuable. The goal is what gives you a basis for questioning whether you are building the right thing. If you cannot articulate a meaningful goal for a feature, that is a signal worth paying attention to.

Acceptance Criteria

A user story on its own is not quite enough to build from. You also need acceptance criteria: a concrete list of conditions that must be true for the story to be considered complete.

Acceptance criteria answer the question: "how do we know this is done?"

Here is the status visibility story with acceptance criteria added:

Story: As a client, I want to see the current status of my submitted request, so that I know whether the team has started working on it.

Acceptance criteria:

  • The request detail page displays the current status
  • The status reflects one of the defined values: submitted, in review, in progress, on hold, completed
  • The status updates in real time when a team member changes it, without requiring a page refresh
  • The client cannot change the status themselves; the field is read-only for them

Now you have something you can actually build against. You have a clear definition of done, a set of testable conditions, and a user perspective that keeps you grounded in what actually matters.

Writing Stories for Clarity

Let us take the confirmed assumptions from the last article and turn them into a proper set of user stories. I am going to organise them by actor, because that is the most natural way to think about the scope of work.

Client stories

Submitting a request

As a client, I want to submit a project request with a title, description, and optional attachments, so that I can communicate what I need from the team.

Acceptance criteria:

  • The submission form requires a title and description
  • Attachments are optional and support common file types
  • After submission, the request status is set to "submitted" automatically
  • The client is redirected to the request detail page after a successful submission

Editing a request

As a client, I want to edit my request while it is in the submitted state, so that I can correct mistakes or add information before the team begins reviewing it.

Acceptance criteria:

  • Edit controls are visible only when the request is in the "submitted" state
  • Once the status moves past "submitted", the edit controls are hidden
  • Edits do not reset the request status

Tracking request status

As a client, I want to see the current status of my request and who it has been assigned to, so that I have visibility into where things stand without needing to chase the team.

Acceptance criteria:

  • The request detail page shows the current status and the assigned developer's name
  • If no developer has been assigned yet, a placeholder is shown rather than a blank field
  • Status changes are reflected without requiring a page refresh

Adding a comment

As a client, I want to add a comment to my request, so that I can ask questions or provide additional context as the work progresses.

Acceptance criteria:

  • Clients can post a comment on any request they own
  • Comments appear in chronological order
  • Internal comments marked by team members are not visible to clients

Team member stories

Reviewing and updating request status

As a team member, I want to update the status of a request, so that clients and colleagues have an accurate picture of where the work stands.

Acceptance criteria:

  • Team members can move a request to any valid status
  • Status changes are logged with a timestamp and the team member's name
  • The client is notified when the status changes

Assigning a request

As a team member, I want to assign a request to a developer, so that ownership is clear and the developer knows what they are responsible for.

Acceptance criteria:

  • Any team member can assign a request
  • Only one developer can be assigned at a time
  • Reassigning a request replaces the previous assignment rather than stacking them

Adding an internal comment

As a team member, I want to mark a comment as internal, so that I can communicate with colleagues about a request without the client seeing the discussion.

Acceptance criteria:

  • Internal comments are visually distinct in the team view
  • Internal comments are completely hidden in the client view
  • A team member can toggle the internal flag before submitting a comment

Admin stories

Managing team members

As an admin, I want to invite and manage team members, so that I can control who has access to the system and what role they hold.

Acceptance criteria:

  • Admins can invite users by email
  • Invitations expire after 48 hours if not accepted
  • Admins can change a team member's role or deactivate their account

What This Set of Stories Gives You

Look at what we have built here. From a single vague paragraph in a client brief, we now have a complete set of structured, testable, actor-anchored stories that describe the entire surface area of the Clarity application.

Every story has a clear definition of done. Every story is written from a user's perspective. And every story is independent enough that a developer could pick one up and work on it without needing to understand the whole system first.

That last point matters a lot when you are working in a team. Vague tasks create dependencies and confusion. Well-written stories create clarity (no pun intended) and autonomy.

Putting It Into Practice

Take the project from the last article's exercise and write three user stories from it. Pick stories from different actors if you can. For each story, write at least three acceptance criteria.

Then ask yourself honestly: could someone else on your team pick up one of those stories and know exactly what done looks like? If the answer is no, the story needs more work.

In the next article, we are going to move from user stories to feature shaping, and look at how the Shape Up methodology gives you a practical framework for deciding what to build and how much time it is worth.