Imported from rjmurillo/ai-agents (
.claude/skills/cva-analysis/SKILL.md). Install upstream withnpx skills add rjmurillo/ai-agents --skill cva-analysis. Copyright stays with the author (MIT).
CVA Analysis - Discover Natural Abstractions
Commonality Variability Analysis (CVA) is a systematic technique for discovering abstractions from requirements. Instead of choosing patterns first, you build a matrix showing what's COMMON (constant across use cases) vs what VARIES (differs between cases). Patterns emerge naturally from the matrix structure.
Core Insight: Rows (commonalities) map to Strategy pattern. Columns (variabilities) map to Abstract Factory pattern. The matrix reveals whether abstraction is needed at all.
From CLAUDE.md Design Philosophy: "Greatest vulnerability is wrong or missing abstraction." CVA prevents wrong abstractions by making pattern selection evidence-based, not intuition-based.
Triggers
Activate CVA when you encounter:
discover abstractions for {domain}run CVA analysis on {requirements}commonality variability analysisprevent wrong abstractionwhat patterns emerge from {use cases}
Quick Reference
| Phase | Purpose | Input | Output | Time |
|---|---|---|---|---|
| 1. Identify Commonalities | Find what's constant across ALL use cases | Use cases/requirements | List of commonalities (matrix rows) | 5-10 min |
| 2. Identify Variabilities | Find what VARIES between use cases | Commonalities + use cases | List of variabilities (matrix columns) | 5-10 min |
| 3. Build Matrix | Visualize commonality × variability relationships | Rows + columns | CVA matrix (Markdown table) | 5-15 min |
| 4. Map to Patterns | Translate matrix structure to design patterns | Completed matrix | Pattern recommendations + rationale | 5-10 min |
| 5. Validate & Handoff | Validate choices, route to appropriate agents | Pattern recommendations | Validation report + ADR stub | 5-10 min |
Total Time: Quick (15 min), Standard (30 min), Deep (60 min)
When to Use
Use CVA when:
- Facing 2+ similar but varying requirements
- About to select a design pattern (validate with CVA first)
- Refactoring code with duplicated logic
- Need evidence for abstraction decisions (ADR material)
- Team debates whether to abstract (make implicit explicit)
Do NOT use CVA when:
- Only 1 use case exists (wait for 2nd per YAGNI)
- Pattern is obvious and uncontested (don't over-analyze)
- Time-critical decision (<15 min available, use intuition)
- Requirements are still highly uncertain (premature)
Process
Phase 1: Identify Commonalities
Purpose: Establish what is ALWAYS true across ALL use cases. This becomes the stable foundation.
Steps:
- Start with first use case: What does it need? List all capabilities.
- Add second use case: What do BOTH need? Extract shared capabilities.
- For each additional use case: What do ALL cases need?
- Document as matrix ROWS: Each row is a commonality present in every use case.
Example (Payment Processing):
Use Case 1: Credit card payment
Use Case 2: PayPal payment
Use Case 3: Bank transfer
Commonalities (ALL cases need):
- Validate payment amount
- Authorize transaction
- Record transaction
- Handle transaction errors
Verification:
- Each commonality appears in ALL use cases
- At least 2 commonalities identified (if only 1, reconsider scope)
- Commonalities are capabilities/behaviors, not implementation details
Failure Handling: If no commonalities exist, use cases may be unrelated. Analyze separately or reconsider grouping.
Phase 2: Identify Variabilities
Purpose: Discover what VARIES between use cases. This reveals extension points where Strategy or Abstract Factory patterns may apply.
Steps:
- For each commonality, ask: "How does this vary across cases?"
- List variations: Document different implementations for each commonality.
- Document as matrix COLUMNS: Each column is a variation.
- Optional: Add "Future Variations" column for anticipated changes.
Example (continuing Payment Processing):
Commonality: Validate payment amount
Variations:
- Credit Card: Check card limit, validate CVV
- PayPal: Check PayPal balance, validate account status
- Bank Transfer: Check account balance, validate routing number
Commonality: Authorize transaction
Variations:
- Credit Card: Contact card issuer API
- PayPal: OAuth flow with PayPal
- Bank Transfer: ACH authorization
Verification:
- Each variability differs in at least 2 use cases
- Variations are concrete implementations, not abstract
- An all-identical ROW is NOT a variability: remove it and hoist it to a constant. Never use an identical-cell row to hide a real second axis. Only if the entire matrix has zero variability across all use cases (all cells identical) may abstraction not be needed
Failure Handling: If all variability (no commonality), design may be too broad. Narrow scope or reconsider.
Phase 3: Build CVA Matrix
Purpose: Create visual artifact showing commonality × variability relationships. Makes implicit design explicit for team discussion.
Steps:
- Create Markdown table: Commonalities as rows, variabilities as columns
- Fill each cell: Concrete implementation for that commonality/variability pair
- Highlight patterns: Where cells are identical (sharing opportunity), where they differ (extension point)
- Optional: Render the matrix as a Mermaid diagram by hand (a matrix exporter is planned, not yet implemented)
Example Matrix:
| Commonality | Credit Card | PayPal | Bank Transfer |
|---|---|---|---|
| Validate amount | Check card limit, CVV | Check PayPal balance, account | Check account balance, routing |
| Authorize | Card issuer API | PayPal OAuth | ACH authorization |
| Record | Log to CardTransactionDB | Log to PayPalTransactionDB | Log to BankTransactionDB |
| Handle errors | Card decline codes | PayPal error codes | ACH rejection codes |
Interpretation:
- Row perspective (Strategy pattern): "Authorize" varies across payment methods → Strategy pattern for authorization
- Column perspective (Abstract Factory pattern): Each payment method has consistent set of operations → Abstract Factory for payment providers
- Cell perspective: "Log to *TransactionDB" shows common pattern with variation → Template Method or Strategy
Verification:
- Matrix is at least 2×2 (minimum for pattern discovery)
- All cells are filled (no empty cells)
- Patterns becoming visible (some cells identical, some divergent)
Failure Handling: If matrix shows no useful patterns, abstraction may not be beneficial. Document rationale for concrete implementation.
Phase 4: Map to Patterns
Purpose: Translate matrix structure to design patterns. Patterns EMERGE from analysis, not imposed.
Steps:
-
Read ROWS (commonalities):
- If each row has different implementations across columns → Strategy pattern (vary algorithm for same operation)
- Example: "Authorize" row has 3 implementations →
IAuthorizationStrategy
-
Read COLUMNS (variabilities):
- If each column represents a coherent family of implementations → Abstract Factory pattern (vary implementations across product families)
- Example: "Credit Card" column has consistent set of card-specific operations →
CreditCardPaymentFactory
-
Check for multidimensional variability:
- If BOTH rows AND columns vary as meaningful axes, classify their relationship before picking the pattern.
- When two or more axes vary, give EACH axis its own co-equal first-class abstraction. Do NOT pick a dominant axis and do NOT defer the second axis to Extension Points:
- Independent axes (any combination is valid) → one Strategy hierarchy per axis; compose them so both vary at once.
- Correlated axes (one abstraction drives the other) → Bridge.
- Only some pairs are valid (sparse combinations) → Abstract Factory.
- Both axes are first-class NOW. Never relegate a co-equal second axis to Extension Points or to a future reassessment trigger.
-
Document recommendations:
- Which pattern(s) fit?
- WHY do they fit? (cite matrix structure)
- What are alternatives? (if any)
Example Output:
## Pattern Recommendations
### Primary: Abstract Factory Pattern
**Rationale**: Each payment method (Credit Card, PayPal, Bank Transfer) requires a coherent family of related operations. Matrix columns show consistent product families.
**Implementation**:
```csharp
public interface IPaymentFactory {
IAmountValidator CreateValidator();
ITransactionAuthorizer CreateAuthorizer();
ITransactionRecorder CreateRecorder();
IErrorHandler CreateErrorHandler();
}
public class CreditCardPaymentFactory : IPaymentFactory {
// Concrete implementations from "Credit Card" column
}
Alternative: Strategy pattern per row (4 separate strategies). Rejected because operations are not independent - they share payment method context. Factory keeps cohesion.
**Create ADR stub** for architect agent:
```markdown
# ADR-XXX: Payment Processing Abstraction
## Context
CVA matrix revealed 3 payment methods with 4 common operations, each varying by method.
## Decision
Use Abstract Factory pattern with `IPaymentFactory` per method.
## Rationale
- Matrix columns show coherent product families
- Operations share payment method context (not independent)
- New payment methods extend without modifying existing
## Alternatives Considered
- Strategy per operation: Rejected (operations not independent, loses cohesion)
- No abstraction: Rejected (3 methods with clear variations justify abstraction per YAGNI threshold)
Verification:
- Recommended patterns align with matrix structure
- Rationale explains WHY patterns fit (cites matrix evidence)
- Edge cases addressed (single use case → don't abstract, all variability → reconsider)
- Independent/co-equal axes each got their own first-class abstraction, not deferred to Extension Points
- ADR stub created with decision rationale
Failure Handling: If no patterns fit cleanly, document rationale for concrete implementation. Abstraction may not be warranted yet.
Phase 5: Validation and Handoff
Purpose: Validate abstraction choices and route to appropriate agents for review.
Steps:
-
Run validation script:
python3 .claude/skills/cva-analysis/scripts/validate-cva-matrix.py cva-matrix.md- Checks: ≥2 rows, ≥2 columns, all cells filled, patterns suggested
- Exit code 0 = pass, 10 = validation failure, 1 = error
-
Route to decision-critic (if abstraction recommended):
# Use decision-critic skill to validate abstraction choice /decision-critic "Validate Abstract Factory pattern for payment processing per CVA analysis" -
Route to architect agent (for ADR creation):
# Hand off ADR stub to architect agent Task(subagent_type="architect", prompt="Create ADR from CVA analysis stub") -
Document reassessment triggers:
## Reassessment Triggers Re-run CVA when: - 3+ new payment methods added - Major architectural shift (e.g., microservices split) - Performance issues with current abstraction - Team feedback: abstraction is too complex or not pulling weight
Outputs:
- Validation report (pass/fail with specific issues)
- Handoff to decision-critic and/or architect agent
- Reassessment triggers documented
Verification:
- Validation script exits with code 0
- Decision-critic review completed (if abstraction recommended)
- Reassessment triggers are specific, not vague
Failure Handling: If validation fails, return to earlier phase based on issue:
- Missing commonalities → Phase 1
- Incomplete matrix → Phase 3
- Pattern mismatch → Phase 4
Anti-Patterns
| Anti-Pattern | Why Bad | Example | Instead |
|---|---|---|---|
| Pattern-First Design | Violates CVA principle: patterns emerge, not imposed. Leads to wrong abstractions. | Decide "we need Strategy pattern" BEFORE running CVA | Run CVA first. Let matrix reveal pattern. If no pattern emerges, abstraction may not be needed. |
| Forcing Abstractions | Creates complexity without benefit. Worse than no abstraction per CLAUDE.md. | CVA shows no variability, but create Strategy anyway "for future" | When CVA shows no variability, explicitly document decision NOT to abstract. Revisit when variability emerges. |
| Skipping Matrix Visualization | Loses pedagogical and collaborative benefits. Matrix makes assumptions explicit. | Identify commonalities/variabilities mentally, skip matrix, jump to pattern | Always create visual matrix (Markdown table minimum). Use for team review, ADR rationale. |
| Analysis Paralysis | CVA is a tool, not an end. Over-analysis wastes time. | Spend 3 hours on CVA for 2 simple use cases | Use tiered approach: Quick (15 min) for simple, Standard (30 min) moderate, Deep (60 min) architectural. Set timer. |
| Ignoring Temporal Dimension | Today's constant may be tomorrow's variable. | CVA assumes "currency" constant (USD only). 6 months later, need multi-currency. | Include "Future Variations" column for anticipated changes. Balance YAGNI with known roadmap. |
| Using CVA for Single Use Case | CVA requires 2+ cases to identify commonality/variability. | Run CVA on payment before any other transaction exists | Wait for 2nd use case (YAGNI), OR document anticipated cases with stakeholder validation. |
Integration with Other Skills
architect Agent
CVA produces ADR stub with pattern rationale. Architect agent creates formal ADR.
Handoff Protocol:
Task(subagent_type="architect", prompt="Create ADR from CVA analysis at cva-payment-processing.md")
decision-critic Skill
Validates abstraction choices discovered via CVA. Applies inversion thinking to pattern recommendation.
Usage:
/decision-critic "Validate Abstract Factory pattern for payment processing per CVA matrix"
independent-thinker Agent
Challenges whether abstraction is needed at all. Use when CVA is borderline (minimal variability).
Usage:
Task(subagent_type="independent-thinker", prompt="Challenge whether payment abstraction is justified given only 2 current methods")
Verification Checklist
After completing CVA:
- Matrix has ≥2 rows (commonalities) and ≥2 columns (variabilities)
- All matrix cells are filled with concrete implementations
- Recommended patterns align with matrix structure (rows → Strategy, columns → Factory)
- Rationale explains WHY patterns fit (cites matrix as evidence)
- Edge cases handled (single use case, all variability, no commonality)
- Validation script passes:
python3 scripts/validate-cva-matrix.py [file] - ADR stub created with decision rationale
- Reassessment triggers documented (when to re-run CVA)
Reassessment Triggers
Re-run CVA when:
- 3+ new use cases added (may reveal new patterns or invalidate current abstraction)
- Major architectural shift (e.g., monolith → microservices)
- Performance issues with current abstraction (overhead not justified)
- Team feedback: Abstraction is too complex, not pulling weight, or forcing designs
- Quarterly review (align with retrospective cycle)
Tiered Depth Levels
Choose depth based on decision impact:
| Tier | Time | Use Cases | When to Use |
|---|---|---|---|
| Quick | 15 min | 2-3 | Simple decisions, clear patterns, low risk |
| Standard | 30 min | 3-5 | Moderate complexity, some uncertainty, medium risk |
| Deep | 60 min | 6+ | Architectural decisions, high uncertainty, high risk |
Time-boxing: Set timer, commit to best-available analysis when time expires. CVA is a tool, not a perfectionist exercise.
.NET Examples
See references/matrix-building-examples.md for complete .NET examples:
- ASP.NET Middleware Pipeline (commonality: process request, variability: authentication, logging, compression)
- Dependency Injection Providers (commonality: resolve dependencies, variability: lifetime scope, registration patterns)
- Data Access Patterns (commonality: CRUD operations, variability: SQL, NoSQL, in-memory)
References
- Pattern Mapping Guide - How to read matrix and map to Strategy, Abstract Factory, combinations
- Matrix Building Examples - .NET examples with complete CVA workflows
- Multidimensional CVA - Advanced: handling multiple axes of variability
- Coplien Multi-Paradigm Design - Academic foundation and further reading
- GoF Pattern Selection - Decision table for mapping CVA results to GoF patterns
Scripts
validate-cva-matrix.py
Check CVA matrix completeness and suggest patterns.
Usage:
python3 .claude/skills/cva-analysis/scripts/validate-cva-matrix.py cva-matrix.md
Exit Codes:
- 0: Valid matrix, patterns suggested
- 10: Validation failure (missing rows/columns, empty cells)
- 1: Error (file not found, invalid format)
Planned scripts (not yet implemented)
Two helpers are designed in references/SKILL_SPEC.md but not yet built. Create the matrix and any diagram by hand until they ship; do not invoke them.
- A template generator: produce an empty matrix from comma-separated commonalities and variabilities.
- A matrix exporter: convert the Markdown table to a Mermaid (or JSON/PlantUML/CSV) diagram for presentations.
Extension Points
-
Pattern Mapping: Add new pattern types beyond Strategy/Abstract Factory
- Edit
references/pattern-mapping-guide.md - Add Builder, Bridge, Visitor patterns with matrix signatures
- Edit
-
Matrix Formats: Add export formats beyond Markdown
- The planned matrix exporter would add
json,plantuml, andcsvformats
- The planned matrix exporter would add
-
Multidimensional Analysis: Handle complex cases with 3+ axes
- See
references/multidimensional-cva.md
- See
-
AI Integration: Automated pattern suggestion
- Route to decision-critic or independent-thinker for automated review