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

推荐订阅源

N
Netflix TechBlog - Medium
罗磊的独立博客
H
Help Net Security
I
Intezer
G
Google Developers Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
Troy Hunt's Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
U
Unit 42
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News and Events Feed by Topic
J
Java Code Geeks
S
Security Affairs
T
The Blog of Author Tim Ferriss
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
D
Docker
The GitHub Blog
The GitHub Blog
F
Full Disclosure
N
News and Events Feed by Topic
Webroot Blog
Webroot Blog
S
Security @ Cisco Blogs
腾讯CDC
人人都是产品经理
人人都是产品经理
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
T
Threatpost
D
DataBreaches.Net
Recent Announcements
Recent Announcements
博客园 - 三生石上(FineUI控件)
MongoDB | Blog
MongoDB | Blog
博客园 - 【当耐特】
L
LINUX DO - 最新话题
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
S
Securelist
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Help Net Security
Help Net Security
P
Proofpoint News Feed
Project Zero
Project Zero
S
SegmentFault 最新的问题
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
Google DeepMind News
Google DeepMind News
宝玉的分享
宝玉的分享
Y
Y Combinator Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 叶小钗

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
Reviewing AI-Generated Code: Check Boundaries Before Logic
Pablo Ifrán · 2026-05-03 · via DEV Community

The code came back. It looks right. Do you ship it?

Post 2 gave you structured prompts that produce better AI output. But "better" isn't "perfect." Even a well-constrained prompt will occasionally slip a database call into an application service, or sneak a business rule into a route handler. You still have to review the diff.

Reviewing AI-generated code the same way you'd review a colleague's PR is slow, frustrating, and misses the real failures. Here's a workflow that's actually fast and checks the right things first.


Why Reviewing AI Code Is Different

When a colleague sends you a PR, you can ask them questions. You can understand their intent.

With AI output, you can't. The AI made decisions about where code lives, what it imports, how it structures logic based on pattern-matching from its context window. It had no architectural intent. It was optimizing for "generates code that compiles and passes the tests I can see."

With a colleague's code, you're asking: Does this solve the problem correctly?

With AI-generated code, you need to ask that but first: Does this code belong where it landed?

Logic bugs are easy to find. Boundary violations are quiet. A function that calculates the wrong total will fail a test. A business rule in the wrong layer will pass all the tests you wrote alongside it and only surface as a problem when you try to change something six months later.

The dangerous failures are structural, not logical.


The Review Order

Deliberately backward from how most code reviews go:

1. Check the file — does it belong in this layer?
2. Check the imports — does it import only what that layer allows?
3. Check the interface — does it match the contract you specified?
4. Check the body — is there logic here that shouldn't be?
5. Check the logic — is it actually correct?

Enter fullscreen mode Exit fullscreen mode

Most reviews go 5 → 4 → 3 → 2 → 1, or skip to 5 entirely.

Steps 1-4 take about 30 seconds combined. Step 5 can take minutes. If the code fails steps 1-4, the logic review is wasted you're regenerating anyway.

Spend 30 seconds on structure first.

The Review Order — Inverted Priority


The Five Structural Signals

The Five-Signal Review Card

Signal 1: The Wrong Import

Look at the import block. Does this file import from a layer it shouldn't depend on?

# application/order_service.py - WRONG
from fastapi import HTTPException        # ← API layer in application layer
from sqlalchemy.orm import Session       # ← infrastructure in application layer
from api.models import PlaceOrderRequest # ← importing from the layer above

Enter fullscreen mode Exit fullscreen mode

None of these cause a runtime error. The code works. But now you can't test the service without a database session, and you can't reuse it outside FastAPI.

# application/order_service.py — correct
from domain.models import Order, LoyaltyAccount
from domain.ports import OrderRepository, CustomerRepository

Enter fullscreen mode Exit fullscreen mode

Signal 1 — The Wrong Import Anatomy

What to do: Scan the first 10 lines. Wrong import? Stop. Don't review the logic. Ask the AI to regenerate with the explicit constraint.

Signal 2: Logic in the Wrong Place

The AI puts logic wherever it fits syntactically. Here's a loyalty points check that shouldn't be in the route:

# api/orders.py — business rule leaked into route handler
@router.post("/")
def place_order(body: PlaceOrderRequest, service: OrderService = Depends(get_order_service)):
    # This validation is a business rule — it belongs in domain/
    if body.redeem_points and body.loyalty_points < 100:
        raise HTTPException(status_code=400, detail="Not enough points to redeem")

    order = service.place_order(...)
    return {"order_id": order.id}

Enter fullscreen mode Exit fullscreen mode

That condition "must have at least 100 points" is a business rule. When it changes, you'll find it in the route handler, not the domain. And if you added a mobile API endpoint last week, there's a copy there too.

What to do: Look for conditionals in route handlers that involve domain concepts. If the condition only makes sense when you understand the business domain not just the HTTP request it's in the wrong place.

Signal 3: The Invented Abstraction

The AI introduces a new pattern that doesn't exist anywhere else in your codebase:

# First time this decorator appears anywhere
@router.post("/")
@validate_order(require_items=True, require_customer=True)
def place_order(body: PlaceOrderRequest, service: OrderService = Depends(get_order_service)):
    ...

Enter fullscreen mode Exit fullscreen mode

Locally clean. But now you have a pattern that needs to be understood, maintained, and either adopted everywhere or deleted. The AI introduced it because it was convenient not because it fits your codebase's patterns.

What to do: Ask: "Does anything else in this codebase do this?" If the answer is no, consider simplifying. Not always wrong but it should be a conscious choice.

Signal 4: The Silent State Mutation

Looks pure, isn't:

# domain/models.py looks like it returns a new LoyaltyAccount
def earn(self, spend_amount: float) -> "LoyaltyAccount":
    self.points += int(spend_amount * self.POINTS_PER_DOLLAR)  # ← mutation
    return self                                                  # ← returns self

Enter fullscreen mode Exit fullscreen mode

Compare to correct:

def earn(self, spend_amount: float) -> "LoyaltyAccount":
    earned = int(spend_amount * self.POINTS_PER_DOLLAR)
    return LoyaltyAccount(points=self.points + earned)  # ← new instance

Enter fullscreen mode Exit fullscreen mode

Signal 4 - Pure vs. Mutating Method

The mutating version passes every test the AI wrote alongside it. It fails the immutability test but only if you wrote that test before reviewing the code.

What to do: For any domain method the prompt said should be "pure", check the return statement. Returns self → mutating. Creates a new instance → pure. Five-second check.

Signal 5: The Missing Error Path

# application/order_service.py happy path works, error path is silent
def place_order(self, customer_id: str, items: list, redeem_points: bool) -> Order:
    customer = self.customer_repo.find_by_id(customer_id)
    # What if customer is None? AttributeError waiting to happen.
    loyalty = LoyaltyAccount(points=customer.loyalty_points)
    ...

Enter fullscreen mode Exit fullscreen mode

When find_by_id() returns None, this crashes with an AttributeError. The correct behavior is raise KeyError(customer_id) so the route handler can return a 404. The AI wrote the happy path and left the error case unhandled.

What to do: For every data fetch in a service method, ask: "What happens if this returns nothing?" The answer should be raise KeyError(id). If it's not there, add it.


The Workflow in Practice

You asked for GET /orders/{order_id}. The AI generates:

# api/orders.py — first attempt
@router.get("/{order_id}")
def get_order(order_id: str, db: Session = Depends(get_db)):
    order = db.query(Order).filter_by(id=order_id).first()
    if not order:
        raise HTTPException(status_code=404)
    customer = db.query(Customer).filter_by(id=order.customer_id).first()
    loyalty_balance = customer.loyalty_points if customer else 0
    return {
        "order_id": order.id,
        "status": order.status,
        "total": order.total,
        "loyalty_points": loyalty_balance,
    }

Enter fullscreen mode Exit fullscreen mode

Signal 1 check: db: Session = Depends(get_db) route is importing the database session directly. Infrastructure in the API layer.

Stop. You don't need to read the rest. Send a corrected prompt:

Revise GET /{order_id} in api/orders.py.

Route should call service.get_order(order_id) and return the result.
Convert KeyError to 404. No direct DB calls. Route body: 10 lines or fewer.

Also add get_order(order_id: str) to application/order_service.py.
Fetch order and customer via repos. Raise KeyError if order not found.
Return a dict with order_id, status, total, loyalty_points.
No FastAPI. No SQLAlchemy types.

Enter fullscreen mode Exit fullscreen mode

The AI regenerates:

# application/order_service.py
def get_order(self, order_id: str) -> dict:
    order = self.order_repo.find_by_id(order_id)
    if order is None:
        raise KeyError(order_id)
    customer = self.customer_repo.find_by_id(order.customer_id)
    loyalty_points = customer.loyalty_points if customer else 0
    return {
        "order_id": order.id,
        "status": order.status,
        "total": order.total().amount,
        "loyalty_points": loyalty_points,
    }

Enter fullscreen mode Exit fullscreen mode

# api/orders.py
@router.get("/{order_id}")
def get_order(order_id: str, service: OrderService = Depends(get_order_service)):
    try:
        return service.get_order(order_id)
    except KeyError:
        raise HTTPException(status_code=404)

Enter fullscreen mode Exit fullscreen mode

Five-signal check on the second version: passes all five. Now review the logic. Two minutes total.

The Full Workflow — Two Passes


The Two Antipatterns

Rubber-stamping: Accepting AI output without running the structural check because "it looks fine". The imports are at the top where you'd skip them. The logic reads correctly. The tests pass. Six weeks later you're finding copied loyalty logic across three route handlers. The five-signal check takes 30 seconds. Do it every time.

Over-scrutinizing style: Spending 10 minutes debating whether the AI should have used a dataclass or a TypedDict for the return type. Style matters in final polish. The first-pass question is: is this code in the right place doing the right job? Note style issues, move on, address them in a cleanup pass.


The Feedback Loop

After a few weeks of this workflow, something shifts. You stop bracing for surprise. You have a systematic check five signals, 30 seconds. Either it passes or it doesn't.

You also start calibrating your prompts based on what slips through. If Signal 2 keeps flagging logic in route handlers, your prompts for that type of feature need better negative constraints. If Signal 1 keeps catching wrong imports in application services, your architectural context block needs a stronger rule.

The review and the prompting are a feedback loop. Each failed review tells you what to add to the next prompt.