Exploring Alternatives
Try 2-3 different approaches before implementing - don't settle for first design you think of
Best use case
Exploring Alternatives is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Try 2-3 different approaches before implementing - don't settle for first design you think of
Teams using Exploring Alternatives should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/exploring-alternatives/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How Exploring Alternatives Compares
| Feature / Agent | Exploring Alternatives | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Try 2-3 different approaches before implementing - don't settle for first design you think of
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Exploring Alternatives
## Overview
Don't settle for the first design you think of. Try multiple approaches, compare trade-offs, pick the best, THEN implement.
**Core principle:** Design is cheap to iterate. Code is expensive. Once you write code, emotional attachment makes it hard to throw away. Explore alternatives while iteration is still cheap.
**Violating the letter of this rule is violating the spirit of good design.**
## When to Use
**Always use before implementing:**
- Non-trivial features
- Complex algorithms
- System design decisions
- Refactoring approaches
- Architecture choices
- Data structure selection
**Especially when:**
- First idea feels complex
- Multiple viable approaches exist
- Stakes are high (production code, public APIs)
- Design will be hard to change later
**Warning signs you need this:**
- Jumping to implementation with first idea
- "This is the obvious way" (without considering alternatives)
- Solution feels forced or awkward
- Fighting the implementation
- Design keeps changing during coding
## The Exploration Process
### Step 1: Understand the Problem
**Before exploring solutions, clarify the problem:**
- What exactly are we solving?
- What are the constraints?
- What are the requirements?
- What are success criteria?
**If problem is unclear, exploring solutions is premature.**
### Step 2: Generate 2-3 Alternatives
**Don't stop at first idea. Generate at least 2 more.**
**Techniques for generating alternatives:**
1. **Different data structures:**
- Array vs linked list vs tree vs hash table
- List vs set vs dictionary
2. **Different algorithms:**
- Iterative vs recursive
- Brute force vs optimized
- Different algorithmic approaches (sort-based vs hash-based)
3. **Different levels of abstraction:**
- Direct implementation vs library
- Custom code vs existing pattern
- Simple specific vs generic flexible
4. **Different responsibility allocation:**
- One class vs multiple
- Function vs class
- Inline vs extracted
5. **Different error handling:**
- Exceptions vs return codes
- Fail fast vs continue with defaults
- Validate at boundary vs trust callers
**For each approach, sketch it in pseudocode or bullet points.**
### Step 3: Compare Trade-offs
**Evaluate each alternative against criteria:**
| Criterion | Alternative 1 | Alternative 2 | Alternative 3 |
|-----------|---------------|---------------|---------------|
| Simplicity | Simple | Complex | Medium |
| Performance | Fast | Slow | Medium |
| Maintainability | Easy to modify | Hard to change | Medium |
| Testability | Easy to test | Hard to test | Medium |
| Flexibility | Rigid | Very flexible | Some flex |
| Development time | Quick | Slow | Medium |
**Which criteria matter most for this problem?**
### Step 4: Pick the Best
**Choose based on:**
- Requirements (which criteria actually matter)
- Simplicity (default to simplest that meets requirements)
- Long-term maintainability (code is read 10x more than written)
**Document why you picked it:**
- "Chose approach 2 because performance is critical and measurements show approach 1 is too slow"
- "Chose approach 1 because simplicity matters more than flexibility we don't need yet"
### Step 5: Implement
Only after comparing alternatives, implement the chosen approach.
**If implementation fights you → return to Step 2. You might have picked wrong alternative.**
## Quick Reference
| When | What to Explore | Example Alternatives |
|------|-----------------|----------------------|
| **Data structure choice** | Different structures | Array, LinkedList, HashMap, Tree |
| **Algorithm choice** | Different algorithms | Iterative, Recursive, Different approach |
| **Error handling** | Different strategies | Exceptions, Return codes, Defaults |
| **Responsibility** | Different decompositions | One class, Multiple classes, Functions |
| **Abstraction level** | Build vs use | Custom implementation, Library, Framework |
| **Complexity trade-off** | Simple vs flexible | Specific solution, Generic solution |
## Example: Validation Function
**Problem:** Validate user registration data
### Alternative 1: Manual Validation
```python
def validate_registration(data: dict) -> tuple[bool, str]:
if 'email' not in data:
return False, "Missing email"
if not re.match(email_pattern, data['email']):
return False, "Invalid email"
# ... validate each field manually
```
**Trade-offs:**
- ✅ Simple, no dependencies
- ✅ Full control
- ❌ Verbose, repetitive
- ❌ Easy to miss fields
### Alternative 2: Pydantic Model
```python
from pydantic import BaseModel, EmailStr, Field
class RegistrationData(BaseModel):
email: EmailStr
password: str = Field(min_length=8)
username: str
age: int = Field(ge=18)
def validate_registration(data: dict) -> tuple[bool, str]:
try:
RegistrationData(**data)
return True, ""
except ValidationError as e:
return False, str(e)
```
**Trade-offs:**
- ✅ Declarative, clear
- ✅ Comprehensive validation
- ✅ Less code
- ❌ Adds dependency
- ❌ Learning curve for library
### Alternative 3: Validator Class
```python
class RegistrationValidator:
def __init__(self, data):
self.data = data
self.errors = []
def validate(self):
self._validate_email()
self._validate_password()
self._validate_username()
self._validate_age()
return len(self.errors) == 0, ", ".join(self.errors)
def _validate_email(self):
# Focused validation method
```
**Trade-offs:**
- ✅ Organized, testable
- ✅ Easy to extend
- ✅ No dependencies
- ❌ More boilerplate
- ❌ Over-engineering for simple case
### Comparison
**For this problem:**
- If project already uses Pydantic: Choose Alternative 2
- If no dependencies allowed: Choose Alternative 1
- If validation will grow complex: Choose Alternative 3
**By exploring all three, you make informed decision instead of defaulting to first idea.**
## Common Mistakes
**❌ Implementing first idea:**
```
Think of approach → implement immediately → discover problems → hack fixes
```
**✅ Exploring alternatives:**
```
Think of approach → sketch it → think of alternative → sketch it → compare → pick best → implement cleanly
```
---
**❌ "This is obviously the best way":**
Without exploring, you don't know if it's best. Your "obvious" solution might be suboptimal.
**✅ "Let me try two other approaches to confirm this is best":**
Even if first idea wins, exploring validates your choice.
---
**❌ Exploring in code:**
Writing full implementations of multiple approaches wastes time and creates emotional attachment.
**✅ Exploring in pseudocode/sketches:**
Quick, cheap, easy to discard.
## If You Already Implemented First Idea
**You implemented without exploring alternatives. Now what?**
**No exceptions:**
- Don't claim "it works so it's fine"
- Don't skip exploration "to save time"
- Don't just document why you picked this approach (you didn't pick, you defaulted)
**Required steps:**
1. **Acknowledge the sunk cost** - Hours spent are already gone
2. **Sketch 2 alternatives** - Don't look at your implementation while sketching
3. **Include current implementation as Alternative 1** - Describe what it does
4. **Compare all 3 honestly** - Is your implementation actually the best?
5. **Decide:**
- If current code is best approach: Keep it, document the alternatives you rejected
- If different approach is better: Implement it (sunk cost is already sunk)
**This isn't punishment. It's good engineering.**
Working code that's not the best approach = technical debt. Pay it now or pay interest later.
**Time investment:**
- Sketch 2 alternatives: 5 minutes
- Compare: 3 minutes
- Decision: 1 minute
- Total: 9 minutes to validate you chose well (or discover you didn't)
**9 minutes now vs hours of maintenance later.**
## Red Flags - STOP and Explore
**Before implementing:**
- First idea → ready to code (haven't explored alternatives)
- "This is the obvious approach" (without checking others)
- "Let's try this and see" (no comparison with alternatives)
- Solution feels forced (might be wrong approach)
- Can't articulate why this approach over others
**During implementing:**
- Fighting the implementation (wrong approach chosen?)
- Discovering limitations you didn't foresee
- Adding hack after hack to make it work
- Implementation much more complex than expected
**All of these mean: Stop. Explore alternatives in pseudocode.**
## Common Rationalizations
| Excuse | Reality |
|--------|---------|
| "First idea is obviously best" | Without exploring, you don't know. Try 2 more anyway. |
| "Don't want to waste time" | 5 minutes exploring saves hours of bad implementation. |
| "This approach already works" | Working ≠ best. Other approaches might be simpler. |
| "I'm experienced, I know the right approach" | Experience creates bias. Check your intuition. |
| "Problem is too simple to need alternatives" | Even simple problems benefit. Takes 2 minutes. |
| "Already started coding, too late" | Sunk cost fallacy. Still cheaper to explore now than debug later. |
| "Other approaches won't work" | How do you know without trying them? |
## Verification Checklist
Before marking design complete:
- [ ] Sketched at least 2 alternative approaches (3+ for critical code)
- [ ] Compared alternatives against relevant criteria
- [ ] Can articulate why chosen approach is best
- [ ] Documented trade-offs considered
- [ ] Consciously rejected other approaches (not just ignored them)
**Can't check all boxes? Return to Step 2 (generate alternatives).**
## When to Stop Exploring
**Explore 2-3 alternatives minimum. Stop when:**
1. **Clear winner emerges** - One approach obviously superior for your criteria
2. **Diminishing returns** - Alternative 4 and 5 aren't meaningfully different
3. **Good enough found** - Approach meets requirements simply and clearly
**Don't:**
- Stop at first idea (always explore at least 2)
- Explore forever (analysis paralysis)
- Explore 10 alternatives (2-3 usually sufficient)
**Balance:** Enough exploration to find good solutions, not so much you never implement.
## Quick Exploration Template
```markdown
## Problem
[State the problem clearly]
## Alternative 1: [Name]
[Sketch the approach]
Pros: ...
Cons: ...
## Alternative 2: [Name]
[Sketch the approach]
Pros: ...
Cons: ...
## Alternative 3: [Name]
[Sketch the approach]
Pros: ...
Cons: ...
## Decision
Chose [Alternative X] because [reasoning based on requirements and trade-offs]
```
**Use this template when designing non-trivial solutions.**
## Real-World Impact
From Code Complete:
- "Don't settle for the first design you think of"
- Design is nondeterministic - multiple valid solutions exist
- Trying alternatives in pseudocode is cheap
- Design mistakes caught before coding save time
From baseline testing:
- Agents implemented first idea immediately
- No evidence of exploring alternatives
- No consideration of libraries (Pydantic for validation)
- No comparison of approaches
- Grade: F for iteration
**With this skill:** Systematic exploration before implementation.
## Integration with Other Skills
**For design iteration:** See skills/designing-before-coding - exploring alternatives happens during the pseudocode phase (Step 7)
**For complexity:** See skills/architecture/reducing-complexity - simpler alternatives reduce complexityRelated Skills
Testing Anti-Patterns
Never test mock behavior. Never add test-only methods to production classes. Understand dependencies before mocking.
Test-Driven Development (TDD)
Write the test first, watch it fail, write minimal code to pass
Condition-Based Waiting
Replace arbitrary timeouts with condition polling for reliable async tests
Testing Skills With Subagents
RED-GREEN-REFACTOR for process documentation - baseline without skill, write addressing failures, iterate closing loopholes
Installing Skills System
Fork, clone to ~/.clank, run installer, edit CLAUDE.md
Gardening Skills Wiki
Maintain skills wiki health - check links, naming, cross-references, and coverage
Creating Skills
TDD for process documentation - test with subagents before writing, iterate until bulletproof
Getting Started with Skills
Skills wiki intro - mandatory workflows, search tool, brainstorming triggers
Verification Before Completion
Run verification commands and confirm output before claiming success
Systematic Debugging
Four-phase debugging framework that ensures root cause investigation before attempting fixes. Never jump to solutions.
Root Cause Tracing
Systematically trace bugs backward through call stack to find original trigger
Defense-in-Depth Validation
Validate at every layer data passes through to make bugs impossible