refactor: Reduce ExecutionOrchestrator constructor dependencies (15 → 8)#1448
Conversation
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extract single-responsibility components from ExecutionOrchestrator to reduce constructor dependencies from 15 to 8, addressing issue #1425. New components: - IPipelineOutputCoordinator: Coordinates all output operations (printing, logging, exception flushing) - wraps 5 dependencies - IIgnoredModuleResultRegistrar: Handles registration of skipped results for ignored modules - wraps 4 dependencies - IPipelineSummaryFactory: Factory for creating PipelineSummary instances - wraps 3 dependencies Benefits: - Improved testability: Each component can be unit tested in isolation - Better maintainability: Smaller, focused classes are easier to understand - Enhanced extensibility: Components can be replaced or extended via DI - Clearer intent: Each dependency group has a meaningful name Closes #1425 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SummaryExtracts 3 single-responsibility components from ExecutionOrchestrator to reduce constructor dependencies from 15 to 8. Critical IssuesNone found ✅ Suggestions1. Potential resource leak in PipelineOutputScope (PipelineOutputCoordinator.cs:71-75)The nested Current code: private sealed class PipelineOutputScope : IPipelineOutputScope
{
private readonly IPrintModuleOutputExecutor _printModuleOutputExecutor;
private readonly IPrintProgressExecutor _printProgressExecutor;
public PipelineOutputScope(
IPrintModuleOutputExecutor printModuleOutputExecutor,
IPrintProgressExecutor printProgressExecutor)
{
_printModuleOutputExecutor = printModuleOutputExecutor;
_printProgressExecutor = printProgressExecutor;
}
public async ValueTask DisposeAsync()
{
_printModuleOutputExecutor.Dispose();
await _printProgressExecutor.DisposeAsync().ConfigureAwait(false);
}
}Concern: Looking at ExecutionOrchestrator.cs:171, the scope is properly used with
2. Type check using GetType() != typeof() (IgnoredModuleResultRegistrar.cs:47)if (_resultRepository.GetType() != typeof(NoOpModuleResultRepository))This is fragile - it breaks if someone creates a derived class. Consider: if (_resultRepository is not NoOpModuleResultRepository)This pattern would also work better with DI if you wanted to register a "null object" as a specific marker type. Verdict✅ APPROVE - Well-structured refactoring following established patterns from #1447. The dependency reduction is meaningful and the new abstractions have clear responsibilities. |
Summary
IPipelineOutputCoordinator: Coordinates all output operations (printing, logging, exception flushing) - wraps 5 dependenciesIIgnoredModuleResultRegistrar: Handles registration of skipped results for ignored modules - wraps 4 dependenciesIPipelineSummaryFactory: Factory for creating PipelineSummary instances - wraps 3 dependenciesBenefits
Dependency Reduction
Test plan
Closes #1425
🤖 Generated with Claude Code