Designing for AI-Assisted Development
January 5, 2026 · observation
Follow-up to my December note about how AI changed my workflow. I've been thinking about what kind of code is easy for AI to generate well vs. poorly.
What AI Generates Well
- Self-contained functions with clear inputs and outputs. No hidden state, no global dependencies.
- CRUD operations. Database queries, API endpoints, form handling. Predictable structure.
- Transformations. Parse this format, convert to that format, map over this list.
- Boilerplate. Config files, test scaffolding, type definitions, repetitive patterns.
What AI Generates Poorly
- Cross-cutting concerns. Anything that touches 5 files simultaneously and requires understanding all their interactions.
- Subtle state management. Race conditions, cache invalidation, distributed coordination.
- Domain-specific heuristics. The "why" behind a magic number. The business logic that only makes sense if you've talked to users.
How This Changes Architecture
I'm now instinctively structuring code so that most of it falls into the "generates well" category:
- Smaller functions. More explicit interfaces. Less clever indirection.
- Configuration separated from logic (AI can generate logic from a config spec easily).
- Domain knowledge concentrated in a few files, not smeared across the codebase.
The code I write by hand is the hard part — the 10% that requires deep context, domain knowledge, or subtle reasoning. Everything else, I describe and let the AI implement.
The Irony
The practices that make code AI-friendly are the same practices we've preached for decades: separation of concerns, clear interfaces, small functions, explicit dependencies. AI doesn't reward new patterns — it rewards good engineering that we were already supposed to be doing.
The difference is that now there's an immediate, tangible reward for doing it right. Clean architecture isn't just "nice for the next developer" — it's "the AI can actually work with this."