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

推荐订阅源

云风的 BLOG
云风的 BLOG
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家
Recent Announcements
Recent Announcements
B
Blog
D
Docker
V
V2EX
GbyAI
GbyAI
L
LangChain Blog
博客园 - Franky
U
Unit 42
T
The Blog of Author Tim Ferriss
A
About on SuperTechFans
博客园 - 【当耐特】
Google DeepMind News
Google DeepMind News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Vercel News
Vercel News
博客园_首页
D
DataBreaches.Net
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
量子位
Blog — PlanetScale
Blog — PlanetScale
罗磊的独立博客

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
AI Ships Your Code in Minutes. Your Team Pays for It for ...
Sandeep Singh · 2026-06-15 · via DEV Community

AI Writes Code Fast. That's Exactly the Problem.

Speed is not the enemy. Unmaintainable speed is.

AI coding assistants can ship a working endpoint in minutes. What they can't do by default is ship one you can still safely touch six months later.

I've seen this pattern repeatedly. Teams move fast, ship fast, celebrate fast. Then the codebase becomes a place people are afraid of. Every change breaks something unrelated. No one wants to be the one who touched it last.

The cause is almost never complexity. It's coupling.

What the AI Actually Hands You

Ask any AI assistant to build an order creation endpoint. Here's what comes back:

app.post('/orders', async (req, res) => {
  const customer = await db.query(
    'SELECT * FROM customers WHERE id = ?',
    [req.body.customerId]
  );

  if (customer[0].creditLimit < req.body.amount) {
    return res.status(400).send("Order rejected: credit limit exceeded");
  }

  await db.query(
    'INSERT INTO orders (customer_id, amount) VALUES (?, ?)',
    [req.body.customerId, req.body.amount]
  );

  res.status(201).send("Order created");
});

It works. It'll pass a demo. The PM will be happy.

Now look at what's jammed into one function: HTTP handling, raw SQL, business rule validation, and response formatting. One file. No boundaries. No separation.

That's tight coupling. And tight coupling is a time bomb with a slow fuse.


The Waiter Who Does Everything

Picture a restaurant where the waiter takes your order, sprints to the pantry, cooks the food, washes the dishes, and tracks inventory.

With five tables, it holds together. Barely.

With fifty tables, orders get dropped. Mistakes compound. Nobody knows who's responsible. Training a new person is nearly impossible because one person owns everything.

Now picture a well-run kitchen. The waiter handles the table. The chef runs the kitchen. The pantry staff manages ingredients. Each role has a clear boundary. Each person can be replaced, trained, and scaled independently.

That's what layered architecture does for your codebase. Same principle. Different medium.


Three Layers. Three Responsibilities.

Layer 1: The Controller

The controller handles HTTP. That's its only job.

// controllers/orderController.js
async function createOrder(req, res) {
  const result = await orderService.createOrder(req.body);
  return res.status(201).json(result);
}

It receives the request. It calls a service. It returns a response.

What it never does: write SQL, enforce business rules, or touch the database. The moment a controller starts deciding whether an order should be approved, it has crossed a boundary it doesn't own.

Controllers are translators. HTTP in, HTTP out. Nothing else.

Layer 2: The Service Layer

This is where the business logic lives. Pricing rules, credit checks, discount logic, approval workflows all of it belongs here.

// services/orderService.js
async function createOrder(orderData) {
  const customer = await customerRepository.getById(orderData.customerId);

  if (customer.creditLimit < orderData.amount) {
    throw new CreditLimitExceededError();
  }

  return orderRepository.create(orderData);
}

One question drives this layer: How should the business behave?

Not: How does the database work? That's someone else's job.

Notice the credit limit check throws a domain error not an HTTP status code. The service layer has no idea what HTTP is. That's by design.

Layer 3: The Repository

The repository owns data access. SQL queries, ORM calls, database-specific logic it all lives here and only here.

// repositories/customerRepository.js
async function getById(customerId) {
  return db.query(
    'SELECT * FROM customers WHERE id = ?',
    [customerId]
  );
}

One question drives this layer: How do we retrieve or store data?

Not: Should this order be approved? That answer belongs two layers up.


What You Actually Gain

Loose coupling means layers depend on contracts, not implementations. The call chain looks like this:

Controller
    ↓
Service
    ↓
Repository
    ↓
Database

Each layer is independently replaceable. Here's what that buys you in practice:

Testing. You can test business logic without a database. You can test HTTP behavior without mocking business rules. Tests become fast and targeted.

Refactoring. Migrating from MySQL to PostgreSQL means touching one layer the repository. Business logic is untouched. Nothing breaks accidentally.

Onboarding. A new engineer reads the service layer to understand what the business does. They read the repository to understand data access. No layer bleeds into another.

AI-assisted development. This one is underrated. When you ask an AI to regenerate a repository, it can do so without touching business logic. When you update an endpoint, you don't rewrite database code. Defined layers make AI tools significantly more precise and less dangerous.


Why AI Defaults to the Mess

AI coding assistants are trained on tutorials, quick-start guides, and Stack Overflow answers. That code is written to demonstrate a concept quickly not to model production architecture.

These tools optimize for the shortest path to a visible result. The output looks like this:

Route
 ├─ Validation
 ├─ Business Rules
 ├─ SQL Queries
 ├─ External API Calls
 └─ Response Formatting

Day one feels productive. You're shipping. It runs.

Month six: every feature touches every file. Bug fixes create side effects. Nobody wants to refactor because nobody knows what else will break.

The velocity you gained upfront was borrowed against your future team's sanity.


How to Use AI Without the Mess

Define the architecture first. Then ask AI to fill in the layers.

Be explicit with your prompts:

"Generate the service layer only. Assume a repository interface exists. No database queries. No HTTP handling."

"Write a repository for the orders table. Return raw data objects. No business logic."

AI tools are excellent at implementing patterns when the boundaries are clear. The boundaries however are your job to set. That's not changing anytime soon.


The Bottom Line

AI generates code. Architecture determines whether that code survives real usage.

Layered architecture isn't a large-team luxury. It's the structure that lets AI-generated applications grow without becoming a liability.

The faster we build, the more separation of concerns matters. Speed without structure is just debt with better marketing.

Define your layers. Enforce your boundaries. Then let the AI fill them in.


What's your approach to structuring AI-generated code? Drop it in the comments curious what's working across different stacks and team sizes.