AI Writes Better Code When You Stop Thinking in Code


From Code to Concept
Working with AI on software projects is no longer a futuristic dream, it’s already here. But if you’ve tried building something serious with tools like Cursor, Claude Code or Windsurf, you’ve likely hit a wall: when the project is complex the AI gets lost in the code. Too many files, too many side effects, too many implicit assumptions.
That’s because code is not the best way to reason about systems for humans or AIs. We need a better abstraction layer. Something precise, high-level, shorter and deterministic. That’s where LayeredDSL comes in.
Repo: https://github.com/AlessandroAnnini/layereddsl
Try yourself: copy this guide and give it to your AI assistant.
The Problem With Code-First AI
When you ask an AI to generate or modify code, it struggles with:
Ambiguity: Codebases are filled with partial implementations, hacks, and assumptions.
Scale: Large projects span hundreds of files... which ones should be changed or even read?
Alignment: AI doesn’t always understand the why behind your design so sometimes it change it slightly.
Validation: It’s hard to check if code is “correct” without rerunning full tests.
The result? Fragile interactions, unpredictable outputs, and hallucinated features. Even when it works, you can’t fully trust it. Larger, better models used in agentic fashon solve the problems, but only partially because even if they are enough to manage a large codbase, something could be overlooked and, in the end you will pay a very high price to keep playing with a lot of tokens.
The Shift: Map-First, Code-Later
Photo by Venti Views on Unsplash
Framework to work with AI like you would with a agile team are effective and all, and I really think there is a lot of potential there but something is still too clunky, there is too much struggle and it not feels right to me. I was thinking about a way to literally work-around this and I started to wonder what would happen if, instead of reasoning through the code, you described your system’s intent in a structured, formal language? A Domain-Specific Language (DSL) that acts as a single source of truth, designed for collaboration between humans and AI
That’s the idea behind LayeredDSL.
Rather than asking AI to navigate or rewrite your codebase blindly, you collaborate with it at the design layer, where the system is defined clearly and unambiguously. The DSL becomes the contract, and code is just an implementation detail.
Why This Matters
Shifting to DSL-first development brings long-term strategic advantages:
Determinism: No more guessing what the AI will do: if the DSL is complete and accurate, so will the code.
Clarity: Stakeholders, devs, and AIs all work from the same shared model.
Traceability: Every logic function is mapped to a real component so nothing is implied or lost.
Maintenance: When requirements change, you change the DSL. AI updates only the affected code.
Bootstrap speed: New modules or microservices can be generated from zero with confidence.
Code validation: The AI can also act as a linter, checking if the current code matches the spec.
Safety: Less chance of hallucinations or shadow logic because the DSL is always the source of truth.
Cross-language portability: You can implement the same DSL-defined system in a completely different programming language or framework with minimal changes to the map.
And just as importantly: a small, focused DSL document outperforms a massive codebase when reasoning with AI. Instead of re-reading thousands of tokens just to understand how a system works, the AI can rely on a compact, unambiguous, layered definition. It’s faster, clearer, and more reliable for both humans and machines.
What is LayeredDSL?
LayeredDSL is a structured YAML-based metamodel. It doesn’t describe code but instead it describes projects. Any kind of software project: web apps, APIs, microservices, mobile apps or even hybrid systems.
It includes layers such as:
project
: name, version, authorsdomain
: data models and typeslogic
: business functions and expected behaviorcomponents
: service/module boundariesui
: user-facing pages and controlsworkflow
: ordered or conditional logic sequencessecurity
: roles and permissionsmapping
: where logic is implementedmetadata
: change history
Why It Works: Design Goals
LayeredDSL was designed with the following principles:
Layered by intent: business logic is separate from data and UI
Readable: every part is easy to understand for both humans and AI
Generative + Validatable: the same DSL can be used to produce or check code
Immutable source of truth: AI never freelances beyond what the DSL says
Deterministic mapping: same DSL = same code = same behavior
Summing it all up AI can work with it so confidently. It knows what to do and what not to.
The Core Structure of LayeredDSL
Here’s a compact example that defines an invoicing app:
project:
name: InvoiceManager
version: 0.1.0
description: Track invoices and notify clients
domain:
Invoice:
id: UUID
customerId: UUID
amount: float
status: enum[draft, sent, paid]
createdAt: datetime
logic:
CreateInvoice:
inputs: [customerId, amount]
output: Invoice
modifies: Invoice
description: Creates a new invoice.
components:
- id: billing_service
type: module
language: python
responsibilities:
- CreateInvoice
ui:
pages:
- name: Dashboard
route: "/"
components:
- type: table
source: Invoice
columns: [customerId, amount, status]
- type: form
fields:
- name: customerId
type: uuid
- name: amount
type: float
onSubmit: CreateInvoice
No code yet, just a clear description of what should exist. From here, the AI can:
Scaffold the backend
Generate UI pages
Validate the current implementation
Identify missing logic
Auto-create test cases
No worries about AI creating something you didn’t discuss before and even if this would be the case, you can easily tell the assistant to remove that part from the DSL in no time, using a minimal amount of tokens.
Human + AI Cycle: Define → Validate → Generate
Working with LayeredDSL involves a clear three-phase loop:
Define
The human developer discuss the idea with the AI that drafts the DSL file. AI assists by suggesting completions or pointing out gaps.
Validate
When the DSL map is complete the AI checks whether existing code satisfies the map. If everything matches nothing more is needed.
Generate
If something is missing, the AI generates only the missing code, and only according to the DSL. No freelancing. No feature creep.
It’s like building software from a precise architectural drawing, not a fuzzy conversation.
This cycle can be repeated across sprints, services, or even different teams. The DSL becomes your living contract with the AI.
The “One Rule”
Layered DSL map and code should always be aligned, if they are not, ask your trusted assistant to align them back by modifying the DSL or the code.
Examples: Real-World DSL in Action
Here’s a simplified workflow
example from a CRM:
workflow:
- name: LeadProcessing
steps:
- call: ValidateLead
condition: lead.source == "web"
- call: NotifySalesTeam
loop: each user in SalesUser[]
condition: user.region == lead.region
- branch:
when:
- condition: lead.score > 80
call: AssignPriorityRep
- condition: lead.score <= 80
call: AddToNewsletter
This structure captures control flow, decisions, and team logic in a way that is trivial for AI to interpret and clear to every human on the team.
AI Prompt Engineering for DSL
Because LayeredDSL is so explicit, you can talk to your AI assistant in terms like:
“Suggest missing
workflow
steps based on thelogic
defined.”“Create backend code for everything in this DSL file.”
“Does
CreateInvoice
already exist inbilling_service
?”“Generate a test plan for this logic based on inputs and output.”
“Refactor this DSL to separate customer-facing and admin UI.”
You’re no longer wrangling unpredictable LLM behavior when the code is at stake you’re using AI to make development much more deterministic by planning this on paper, with a structured document.
🧠 Final Thought
AI won’t replace developers. But it will change the way we describe, evolve, and verify software.
Many frameworks are being created to fragment ai working into specialized agents and this is super effective, but they would be a lot more effective if they could plan the work ahead and know in advance the full picture and not “blinsided” by some patchwork code they find on the code when they try to complete a task.
By moving from code to concept by describing intent instead of implementation you unlock a new level of AI-assisted development power.
And LayeredDSL might just be the missing bridge.
👨🏻💻 About the Author
I’m Alessandro Annini, a software engineer with 15+ years of experience across sectors from aviation entertainment systems to large-scale platforms. My work is grounded in one goal: make powerful tech accessible and practical.
Follow me on GitHub or LinkedIn to keep up with the future of portable development.
Subscribe to my newsletter
Read articles from Alessandro Annini directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
