opencode-workflow/skills/design-an-interface/SKILL.md

6.9 KiB

name description
design-an-interface Backend Agent uses this skill to explore multiple API interface design options. Based on 'Design It Twice' principle, generate multiple distinct designs, compare, and select the best option. Trigger: API design phase (Stage 4), called by be-api-design skill.

/design-an-interface — Interface Design Exploration

Backend Agent uses this skill to explore API interface design options.

Based on "Design It Twice" principle from "A Philosophy of Software Design": The first idea is usually not the best. Generate multiple distinct designs, then compare and choose.

Responsibilities

  1. Generate 2-3 distinct interface design options for module requirements
  2. Each option uses different design constraints
  3. Compare pros and cons of options
  4. Assist in selecting or synthesizing the best option

Input

  • Module description (functional requirements from PRD)
  • User stories and usage scenarios

Output

  • Multiple interface design options (including interface signatures, usage examples, pros/cons analysis)
  • Option comparison and recommendations

Flow

Collect requirements
    ↓
Generate 2-3 design options (parallel sub-agents)
    ↓
Present each option
    ↓
Compare options (interface simplicity, generality, implementation efficiency, depth)
    ↓
Synthesize best option or select most suitable

Step Details

1. Collect Requirements

Before designing, understand:

  • What problem does this module solve?
  • Who are the callers? (other modules, external users, tests)
  • What are the key operations?
  • What are the constraints? (performance, compatibility, existing patterns)
  • What should be hidden internally? What should be exposed externally?

Ask: "What does this module need to do? Who will use it?"

2. Generate Design Options (Parallel Sub-Agents)

Generate 3+ distinct options simultaneously. Each option must follow different constraints:

Option A: Minimize method count — target 1-3 methods
Option B: Maximize flexibility — support multiple use cases
Option C: Optimize for most common operations
Option D (optional): Reference specific paradigm or framework design

Each option should include:

  1. Interface signature (types/methods)
  2. Usage examples (how callers actually use it)
  3. What complexity this design hides
  4. Trade-offs of this option

3. Present Options

Present each option one by one, including:

  • Interface signature: types, methods, params
  • Usage examples: how callers actually use it
  • Hidden complexity: small interface hiding large implementation (good) vs large interface with thin implementation (bad)

Allow user to fully absorb each option before comparison.

4. Compare Options

Compare across dimensions:

  • Interface simplicity: Few methods, simple parameters → Easier to learn and use correctly
  • Generality vs Specificity: Flexibility vs focus, where are the trade-offs
  • Implementation efficiency: Does interface shape allow efficient internal implementation?
  • Depth: Small interface hiding large complexity (deep module, good) vs large interface with thin implementation (shallow module, bad)
  • Ease of correct usage vs ease of misuse

Discuss trade-offs in text, not just tables. Emphasize where options diverge most.

5. Synthesize Best Option

The best design often combines insights from multiple options. Ask:

  • "Which option fits your primary use case best?"
  • "Are there elements from other options worth incorporating?"

Evaluation Criteria

From "A Philosophy of Software Design":

Interface simplicity: Few methods, simple parameters = Easier to learn and use correctly.

Generality: Can handle future use cases without modification. But avoid over-generalization.

Implementation efficiency: Does interface shape allow efficient implementation? Or does it force awkward internal implementation?

Depth: Small interface hiding large complexity = deep module (good). Large interface with thin implementation = shallow module (avoid).

Deep module (good):
┌─────────────────────┐
│   Small Interface   │  ← Few methods, simple parameters
├─────────────────────┤
│                     │
│                     │
│  Deep Implementation│  ← Complex logic hidden inside
│                     │
│                     │
└─────────────────────┘

Shallow module (avoid):
┌─────────────────────────────────┐
│       Large Interface           │  ← Many methods, complex parameters
├─────────────────────────────────┤
│  Thin Implementation            │  ← Just a pass-through
└─────────────────────────────────┘

Anti-Patterns

  • Don't let sub-agents generate similar designs — force distinct ones
  • Don't skip comparison — value comes from contrast
  • Don't implement at this stage — this is pure interface design
  • Don't evaluate options based on implementation effort — only look at interface quality

Golang Interface Design Examples

// Option A: Minimize method count
type UserRepository interface {
    GetByID(ctx context.Context, id string) (*domain.User, error)
    Save(ctx context.Context, user *domain.User) error
}
// Pros: Simple, easy to mock
// Cons: Save handles both Create and Update, depends on whether it exists

// Option B: Separate read/write
type UserReader interface {
    GetByID(ctx context.Context, id string) (*domain.User, error)
    List(ctx context.Context, page, limit int) ([]*domain.User, error)
}

type UserWriter interface {
    Create(ctx context.Context, user *domain.User) error
    Update(ctx context.Context, user *domain.User) error
    Delete(ctx context.Context, id string) error
}
// Pros: CQRS friendly, separated concerns
// Cons: More methods, but each method has clearer semantics

// Option C: Optimize for common operations
type UserService interface {
    Register(ctx context.Context, email, password, name string) (*domain.User, error)
    Authenticate(ctx context.Context, email, password string) (*domain.User, error)
    GetProfile(ctx context.Context, id string) (*domain.User, error)
}
// Pros: Directly maps to business operations, most intuitive
// Cons: Need to add method for each new operation, less flexible

Integration with be-api-design

This skill is automatically called by be-api-design at step 3. API design flow:

be-api-design step 1: Read PRD
be-api-design step 2: Identify resources and operations
→ design-an-interface: Explore 2-3 API design options
be-api-design step 4: Select option, define OpenAPI spec
  • Prerequisite: write-a-prd (PRD complete)
  • Follow-up: be-api-design (API spec definition)