Skip to content

Implement circular dependency quality check with dependency inversion enforcement #64

@devill

Description

@devill

Problem

Circular dependencies create maintenance challenges and can indicate poor architectural design. RefakTS currently lacks automated detection for:

  1. File-level circular dependencies - Files that import each other directly or indirectly
  2. Directory-level circular dependencies - Directories that depend on each other
  3. Class-level circular dependencies - Classes with circular references

These dependencies can lead to:

  • Build issues and import ordering problems
  • Testing difficulties and mocking complexity
  • Tight coupling that makes refactoring harder
  • Architectural erosion over time

Proposed Solution

Create a comprehensive circular dependency quality check that:

Detection Levels

1. File-Level Circular Dependencies

❌ BAD: A.ts → B.ts → C.ts → A.ts
✅ GOOD: A.ts → B.ts → C.ts (no cycles)

2. Directory-Level Circular Dependencies

❌ BAD: 
src/core/commands/ → src/core/services/ → src/core/commands/
src/core/ → src/command-line-parser/ → src/core/

✅ GOOD: Hierarchical dependencies only

3. Class-Level Circular Dependencies

// ❌ BAD: Circular class dependencies
class A {
  constructor(private b: B) {}
}
class B {
  constructor(private a: A) {}
}

// ✅ GOOD: Dependency inversion
interface IB { doSomething(): void; }
class A {
  constructor(private b: IB) {}
}
class B implements IB {
  doSomething(): void {}
}

Dependency Inversion Guidance

When circular dependencies are detected, suggest dependency inversion solutions:

  • Extract interfaces to break circular references
  • Introduce abstractions at dependency boundaries
  • Use dependency injection patterns
  • Apply observer patterns for loose coupling

Implementation Approach

Detection Algorithm

  1. Build dependency graph from import/export analysis
  2. Apply cycle detection (e.g., depth-first search with cycle tracking)
  3. Report circular paths with specific file/class chains
  4. Suggest solutions based on dependency inversion patterns

Directory-Level Analysis

Treat each directory as a logical unit and detect cycles at the directory level:

src/core/commands/ ↔ src/core/services/     # ❌ Circular
src/core/ ↔ src/command-line-parser/       # ❌ Circular  
src/core/ → src/command-line-parser/       # ✅ Unidirectional

Quality Check Output

🚨 Circular Dependencies Detected:

File-level cycles:
  • src/core/ast/location-range.ts → src/core/services/ast-service.ts → src/core/ast/location-range.ts

Directory-level cycles:  
  • src/core/commands/ ↔ src/core/services/

Suggested fixes:
  • Extract interface from ASTService to break location-range cycle
  • Move shared abstractions to src/core/interfaces/

Advanced Features (Optional Discussion)

Explicit Dependency Direction Enforcement

Question for consideration: Should we enforce specific dependency directions?

Examples:

  • Commands → Services → AST (never reverse)
  • Core → CLI (never CLI → Core)
  • Tests → Source (never Source → Tests)

Benefits: Clearer architecture, prevention of architectural drift
Drawbacks: May be overly restrictive, harder to implement

Recommendation: Start with cycle detection, consider direction enforcement later if needed.

Implementation Steps

  1. Build dependency graph analyzer
    • Parse import/export statements
    • Track file-to-file dependencies
    • Group files by directory
  2. Implement cycle detection algorithms
    • File-level cycle detection
    • Directory-level cycle detection
    • Class-level dependency analysis
  3. Create quality check integration
    • Integrate with existing quality check system
    • Generate actionable error messages
    • Suggest dependency inversion solutions
  4. Add configuration options
    • Enable/disable different levels of checking
    • Configure directory grouping rules
    • Set cycle detection depth limits

Testing Strategy

Test Cases Needed

  • Simple circular imports (A → B → A)
  • Complex circular chains (A → B → C → D → A)
  • Directory-level cycles with multiple files
  • Valid dependency hierarchies (should not trigger)
  • Dependency inversion examples (should not trigger)

Integration Points

  • Post-commit hooks - Detect cycles in changed files
  • CI/CD pipeline - Prevent merging cycle-introducing changes
  • Development workflow - Real-time feedback during development
  • Architecture reviews - Generate dependency reports

Priority

Medium - Architectural quality improvement that prevents technical debt accumulation.

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    DiscussionIssues where community input is encouraged to help refine the ideaQuality ChecksTasks that add to post-commit quality check system

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions