I've been busy with outsourced development work, so I couldn't post for a while. I went to bed too early yesterday and woke up too early, so I'm posting some pointless chatter after a long time. 😁
Agile as a Pretty Medlar
In software engineering over the past 20 years, few words have been as enthusiastically praised and simultaneously bitterly cursed as agile.
"Respond agilely to change," "prioritize working software over documentation," "value individuals and interactions." The phrases from the 2001 Agile Manifesto were noble. However, the reality of agile that we encountered in actual practice was different.
Many organizations implemented agile by holding daily scrums every morning to interrogate developers about what mistakes they made yesterday, and became obsessed with moving Jira ticket status tabs. The worst part was a fake agile that combined the dogma of "we're agile so we can change our plans every day" and "we can't miss the release date" Waterfall-style control. What developers endured was working late nights and burnout while scope and time were simultaneously locked down with relentless requirement changes. Fake agile without an engineering foundation was a pretty medlar that legally squeezed developers dry.
Around the same time, DDD (Domain Driven Design) and TDD (Test-Driven Development) were considered either ivory tower theory or luxury goods enjoyed only by big tech companies. In a battlefield where plans flipped the next morning and deadlines were the following week, precisely defining domain boundaries and writing failing tests before actual code were dismissed as overhead.
As of 2026, the paradigm has shifted. We've entered the age of vibe coding, where LLMs understand natural language commands and churn out executable code in seconds. Ironically, now that we've reached an era where humans build software through intent alone without typing directly, the fake agile that tormented developers in the past and DDD and TDD once considered luxury goods are beginning to combine into a single ecosystem and gain substance.
Let's trace that combination. However, one thing: this article is not about a universal solution. There are domains where these methodologies work, and domains where they're difficult to apply. We'll also examine those boundaries.
DDD (Domain Driven Design): A Compass for Injecting Common Language into AI
In the age of vibe coding, a developer's primary job is not typing source code on a keyboard. The key work is clearly communicating business requirements and architectural intent to AI agents. Here, DDD becomes a compass that reduces AI hallucinations and draws out accurate code.
Rediscovering Universal Language
There's a problem that all developers who've worked with AI have experienced. When you mix different words for the same concept in prompts, AI misunderstands the context and generates wrong schemas and data flows.
First, Ubiquitous Language, a core practice of DDD, is a strict glossary of terms that domain experts, planners, and developers all use with the same meaning.
For example, suppose you're building a local search engine that searches AI agent sessions. If you vaguely instruct the AI about "conversation fragments," "search scores," and "combining results," the AI will each time produce arbitrary variable names like chunk, segment, score, rank, merge and tangled data flows.
However, if you define domain terms like this and inject them into AI's system prompt structure, things change.
Session: A single conversation with a terminal agent
Chunk: A piece of a session cut into search units. Includes overlap
BM25 score: Morpheme-based keyword matching score
Vector score: Embedding-based semantic matching score
RRF: A rank fusion method that combines two scores into one
Now, if a developer just says in one line "Write an adapter that cuts chunks based on Lindera tokenizer results so Korean morpheme boundaries don't break," the AI generates code that follows domain rules within universal language. DDD significantly reduces the communication cost with AI.
Strategic Design and Subdomain Isolation
No matter how good an LLM is, it's impossible to understand tens of thousands of lines of monolithic code all at once and produce a perfect revision. This is due to context window limitations, token consumption, and attention degradation.
DDD's Bounded Context strategy splits a massive system into independently isolated boundaries. Using a search engine as an example, it divides like this:
Core Domain: Hybrid search engine. BM25 + vector + RRF (src/search/)
Supporting Domain: Session parser. Processing log formats for Claude Code / Codex / Gemini respectively (src/parser/)
Generic Domain: Obsidian-compatible vault output (src/vault/)
When boundaries are isolated, you don't need to have AI read the entire project. You can feed only the type definitions of the search core domain and give a narrow and deep command: "Adjust the k constant in RRF fusion here and separate the normalization logic for BM25 and vector scores."
DDD is a strategic tool for slicing large projects into sizes digestible by AI.
One thing to note here: some projects have cleanly divided domain boundaries, while others don't. Systems with clear responsibilities like search engines have well-defined boundaries. However, projects in early exploration stages where the domain itself is still uncertain may be hampered by drawing boundaries prematurely. DDD is a tool that works best after the domain is somewhat established.
TDD (Test-Driven Development): A Safety Belt to Stop AI's Runaway
The greatest blessing of vibe coding is speed, but the greatest disaster is regression errors that AI produces. AI generates dozens of lines of seemingly grammatically perfect code that either throws runtime errors on specific edge cases or silently breaks previously working core functionality.
The practice that puts guardrails on this runaway is TDD.
From Typer to Validator
In the past, TDD was manual repetition where developers conceptualized logic → wrote tests (Red) → implemented (Green) → improved (Refactor). This is why it wasn't welcomed in speed-critical environments.
TDD in the vibe coding era changes flow.
[Human] Define business destination (failing test prompting)
│
▼
[AI] Ultra-fast implementation to pass tests (Green)
│
▼
[Human+AI] Run all existing tests for regression verification and refactoring
Developers don't type on keyboards all night to implement. Instead, they first create guardrails together with AI: "Write a unit test that validates when BM25 scores with morpheme analysis applied and BGE-M3 vector scores from a Korean query are fused with RRF, whether the correct document falls within the top 5."
After that, implementation is left to the AI. It doesn't matter whether the AI writes it sloppily or brilliantly. A test set that explicitly specifies domain rules already exists. The moment all tests turn Green, you gain confidence to deploy the code written by AI without doubt.
Removing the Fear of Refactoring
When developing with AI, spaghetti code is mass-produced and technical debt accumulates. As code becomes complex, the phenomenon of "can't fix it because we're afraid the existing stuff will break" occurs.
In an environment where TDD is established, refactoring becomes safe. You can command: "Replace the vector index from sqlite-vec to usearch HNSW while maintaining a state where all existing search tests pass." When the AI overhauls the index structure, you just run the test runner to verify. TDD is the guardrail that tames the wild horse that is AI.
However, there's also a boundary here. TDD is powerful in domains where inputs and outputs are clearly defined. Search accuracy, parsing results, and data transformation are examples. Conversely, domains where output is subjective or the answer is ambiguous, like the quality of wiki documents generated by LLMs or the user experience of UI, are difficult to guard with tests. In these domains, human eyes must still remain as validators. TDD doesn't automatically validate everything.
Agile: Nimbleness Blooming from Reduced Implementation Costs
The fundamental reason past agile was a pretty medlar was ignoring the triangle rule (scope-time-cost) and developers' typing speed couldn't keep up with the pace of planning changes. A planner's whims were a disaster for developers, not flexibility.
Agile in the vibe coding era with context secured through DDD and safety belts fastened through TDD finally solves that problem.
The Decline in Requirement Change Costs
In traditional engineering, it was common knowledge that requirement changes occurring later increased costs exponentially. This was because architecture got twisted, data broke, and people had to reanalyze.
In the vibe coding environment, this cost is significantly lowered.
Stage | Past Agile | Vibe Coding Era |
|---|
Feedback Reception | "Please put recent session weights in search results" | Received the same way |
Impact Analysis | Team gathers and looks at architecture documents for days | Organized with DDD universal language, fed to AI, understood immediately |
Code Modification | Modifying search logic overnight for days | AI writes modifications with natural language commands |
Stability Verification | Manual testing, bugs emerge | TDD pipeline running, side effects immediately identified |
The previously impossible "iterative cycle of changing plans and immediately applying feedback to products" has become possible without draining developers' blood.
However, while AI quickly writes implementation code, designing the domain, designing tests, and validating results still require human time and judgment. In fact, the proportion of that work increases. The design and verification costs fill the space left by vanished typing costs. The bottleneck of change has shifted from typing to thinking.
Still, this shift is significant. Agile is no longer a tool that squeezes developers, but rather a strategy that reduces business uncertainty through lowered implementation costs and delivers products that evolve in real time.
Trinity Practical Scenario
Let's see a concrete scenario of how DDD, TDD, agile, and vibe coding actually mesh together.
Suppose we're developing a local search engine that searches AI agent sessions. One day, a feature proposal comes in via GitHub issue.
Issue: When ingesting a session, if you extract the first line as a summary
and automatically put it in the frontmatter, it seems like
preview will be possible in search results.
In the past, this scenario would have dragged on for days with the team wondering whether the entire parser needed reworking. But a prepared team moves differently.
Step 1: Specification and Isolation with DDD
Refine the request in domain terms: summary is extracted from the first substantial line of a session, skipping blank lines and greetings; frontmatter applies YAML escaping; existing vault files only modify the frontmatter area while the body remains immutable. Inject this specification along with type definitions of the parser domain into the AI. Don't touch the search core or vault output domain.
Step 2: Writing Failing Guardrails with TDD
Have the AI write failing tests first. Sessions starting with blank lines, sessions with only greetings, first lines with YAML special characters. Create a test set that validates whether summary is properly extracted and escaped in these edge cases. Since there's no implementation, it's naturally Red.
Step 3: Implementation with Vibe Coding
Give the AI a vibe: "Attach frontmatter generation logic to the ingest pipeline to pass the summary extraction test you just created. Don't conflict with the existing reindex flow." The AI writes the implementation in tens of seconds. Running the test runner, both existing and new tests turn Green. This is the moment it's proven that the parser was fixed without breaking the search core and vault output.
Step 4: Agile Deployment and Feedback
Once verification is done, merge and deploy. Reply to the issue opener with "Thank you for the suggestion. I've implemented it right away," and additionally propose a backfill command to populate summary in existing vaults. Even if the suggester throws another request, you just open the prompt window.
Back to the Essence of Software Engineering
The advent of the vibe coding era is not the end of software development. It's a signal that simple labor like typing ends and the proportion of design and engineering increases.
Fake agile remained a pretty medlar because the architecture (DDD), verification infrastructure (TDD), and implementation speed (AI) to support it weren't in place. It was a result of technology not catching up with the ideal.
Now we have the weapons to some extent.
Establish conceptual order to communicate with AI through DDD
Create guardrails to control AI's runaway through TDD
On top of that, realize agile that breaks through uncertainty with AI as the implementation engine
However, these three are not a cure-all. DDD works best after the domain is established, TDD is strong in areas with clear answers, and agile only lowers change costs, not eliminates them. Those who understand both the operating domain and limitations of tools use tools as tools.
Design, verification, and judgment remain where the typing bottleneck disappears. That remaining space is ultimately human work. Agentic development is not headbutting an empty field. It's collaboration where human domain knowledge and AI's tireless work mesh together. It's time to abandon the medlar and return to the essence of engineering.