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, authors

  • domain: data models and types

  • logic: business functions and expected behavior

  • components: service/module boundaries

  • ui: user-facing pages and controls

  • workflow: ordered or conditional logic sequences

  • security: roles and permissions

  • mapping: where logic is implemented

  • metadata: 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 the logic defined.”

  • “Create backend code for everything in this DSL file.”

  • “Does CreateInvoice already exist in billing_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.

0
Subscribe to my newsletter

Read articles from Alessandro Annini directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Alessandro Annini
Alessandro Annini