Software Design Reference Core Designer · Structuring for Stability

Lesson 0010 · Core Designer · Module 2

Guiding AI Toward Better Structure

Lesson 0005 taught you to review AI output. This lesson teaches you to steer it before it writes: specify the seams, then let the AI fill them in.

Mission tie-in: "guide AI toward better structure instead of patching bad outputs" — the exact skill that separates developers who stay in control from developers whose codebase becomes the AI's drafting table.

Knowledge: you are the architect, AI is the drafter

A drafter draws what the architect specifies. Ask an AI to "build a checkout" and you will get a god function with SDK calls inside — because you specified a feature, not a structure. Ask it to implement a structure you already designed and the output inherits your design.

The recipe — specify the seams first:

  1. Name the boundary. Which parts are domain, which are infrastructure? State it in the prompt: "domain code must not import the SDK."
  2. Declare the ports. Give the interfaces: PaymentGateway, OrderRepository. "Implement the adapter, not the port."
  3. State the invariants. "An order can never be confirmed twice." AI will encode what you tell it to protect.
  4. Ask for the tests. "Write the tests first, with an in-memory fake adapter." The tests document the structure as much as they verify it.
# prompt shape (paraphrased):
# Implement checkout for the CheckoutService below. Do NOT modify this
# class or the PaymentGateway port. Domain code must not import Stripe.
# Write StripeAdapter in infrastructure/, plus tests using a FakeGateway.

class PaymentGateway(Protocol):
    def charge(self, amount: Money, token: str) -> str: ...

class CheckoutService:
    def __init__(self, gateway: PaymentGateway, orders: OrderRepository): ...

Now the AI's freedom is bounded by your structure. Bad output is still possible — AI loves a helper explosion — but the defects are now in the filling, not the frame.

The review loop stays: even with a boundary spec, run the five-point checklist from lesson 0005 on the result. Steering reduces defects; it doesn't eliminate them.
Field notes · the sentence, and the defect it prevents
Put this in the promptWhat it pins downWhat you get without it
“domain/ must not import stripe”Dependency direction (lesson 0009).SDK calls inside the business rule.
“implement the adapter, not the port”The interface stays yours.A port quietly reshaped to match the SDK.
“an order cannot be confirmed twice”The invariant lives in the object.A status flag every caller must remember.
“tests first, with an in-memory fake”The seam is proven by a test.Tests that patch requests and freeze the defect.
“no parameters beyond this case”Speculative generality is blocked.A configurable framework for one use.

Skill: prompt with the design first

The best prompt for generating a feature specifies:

"Domain code must not import the SDK" is an instruction about:

Asking AI to write tests with a fake adapter serves to:

Practice on your own code

Pick a small feature you'd normally hand to AI. Write the boundary spec first — ports, invariants, file layout — then generate. Compare the output with the five-point checklist from lesson 0005: how many defects did the spec prevent?

Reveal: a before/after comparison

Before: "Write a function to sync inventory from the supplier API." Result: one function doing HTTP, parsing, merging, and saving, with requests imported throughout.
After: "Implement InventorySyncService using the SupplierFeed port below; adapters in infrastructure/; tests with a canned feed." Result: domain service with two injectable ports, thin adapter, and tests that run offline. Same feature, opposite structure.

Your win

You can now treat AI as a drafter with a brief: structure specified up front, defects reviewed after. The combination is the Core Designer's AI workflow.

Read and watch deeper

Draft a boundary spec with your agent-teacher for a feature you're about to generate — then compare the spec you'd have written alone.