-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Refactor user_output.rs Module to Folder Structure
Issue: #149
Parent Epic: #102 - User Output Architecture Improvements
Specification: docs/issues/149-refactor-user-output-module-to-folder-structure.md
Overview
The src/presentation/user_output.rs file has grown to 4,226 lines, making it difficult to navigate and maintain. This task refactors the monolithic file into a well-organized folder module structure with focused, cohesive submodules that follow project conventions.
This refactoring improves:
- Discoverability: Clear separation makes it easier to find specific functionality
- Maintainability: Smaller, focused files are easier to understand and modify
- Testability: Tests are co-located with their code using
#[cfg(test)]modules - Collaboration: Multiple developers can work on different aspects simultaneously
- Code Review: Smaller, focused changes are easier to review
Goals
- Convert
user_output.rstouser_output/folder module - Separate concerns into logical submodules
- Maintain backward compatibility (no public API changes)
- Ensure all tests pass without modification
- Follow project module organization conventions
- Improve code discoverability and navigation
Proposed Structure
src/presentation/user_output/
├── mod.rs # Public API, re-exports, module documentation
├── core.rs # UserOutput main struct and core impl
├── theme.rs # Theme struct and predefined themes
├── verbosity.rs # VerbosityLevel enum and VerbosityFilter
├── channel.rs # Channel enum
├── traits.rs # OutputMessage, FormatterOverride, OutputSink traits
├── messages/ # Message type implementations
│ ├── mod.rs
│ ├── progress.rs # ProgressMessage + tests
│ ├── success.rs # SuccessMessage + tests
│ ├── warning.rs # WarningMessage + tests
│ ├── error.rs # ErrorMessage + tests
│ ├── result.rs # ResultMessage + tests
│ ├── steps.rs # StepsMessage and builder + tests
│ └── info_block.rs # InfoBlockMessage and builder + tests
├── sinks/ # OutputSink implementations
│ ├── mod.rs
│ ├── standard.rs # StandardSink + tests
│ ├── composite.rs # CompositeSink + tests
│ ├── file.rs # FileSink + tests
│ ├── telemetry.rs # TelemetrySink + tests
│ └── writers.rs # StdoutWriter, StderrWriter wrappers + tests
├── formatters/ # FormatterOverride implementations
│ ├── mod.rs
│ └── json.rs # JsonFormatter + tests
└── test_support.rs # TestWriter, TestUserOutput (shared test utilities)
Note on Test Organization: All tests are unit tests that only depend on types within the user_output module. Following project conventions, they will be co-located with their code using #[cfg(test)] modules within each file. This improves discoverability and maintainability.
Implementation Plan
Phase 1: Create Folder Structure and Core Modules (1-2 hours)
- Create
src/presentation/user_output/directory - Create
mod.rswith module documentation and structure outline - Extract
Themetotheme.rswith tests in#[cfg(test)]module - Extract
VerbosityLevelandVerbosityFiltertoverbosity.rswith tests in#[cfg(test)]module - Extract
Channeltochannel.rswith tests in#[cfg(test)]module - Update
mod.rswith re-exports for backward compatibility - Verify existing code still compiles and all tests pass
Phase 2: Extract Traits and Core Logic (1-2 hours)
- Extract
OutputMessage,FormatterOverride,OutputSinktotraits.rs - Extract main
UserOutputstruct and methods tocore.rs - Update
mod.rswith re-exports - Verify all functionality works
Phase 3: Organize Message Types (2-3 hours)
- Create
messages/subdirectory - Extract each message type to its own file with tests in
#[cfg(test)]modules:-
progress.rs-ProgressMessagewith tests -
success.rs-SuccessMessagewith tests -
warning.rs-WarningMessagewith tests -
error.rs-ErrorMessagewith tests -
result.rs-ResultMessagewith tests -
steps.rs-StepsMessage,StepsMessageBuilder, and tests -
info_block.rs-InfoBlockMessage,InfoBlockMessageBuilder, and tests
-
- Create
messages/mod.rswith re-exports - Update parent
mod.rswith message re-exports - Verify all message tests pass
Phase 4: Organize Sink Implementations (1-2 hours)
- Create
sinks/subdirectory - Extract
StdoutWriterandStderrWritertowriters.rswith tests in#[cfg(test)]module - Extract sink implementations to individual files with tests:
-
standard.rs-StandardSinkwith tests -
composite.rs-CompositeSinkwith tests -
file.rs-FileSinkwith tests -
telemetry.rs-TelemetrySinkwith tests
-
- Create
sinks/mod.rswith re-exports - Update parent
mod.rswith sink re-exports - Verify all sink tests pass
Phase 5: Organize Formatters (30 minutes)
- Create
formatters/subdirectory - Extract
JsonFormattertojson.rswith tests in#[cfg(test)]module - Create
formatters/mod.rswith re-exports - Update parent
mod.rswith formatter re-exports - Verify formatter tests pass
Phase 6: Organize Test Infrastructure (30 minutes)
- Extract
test_supportmodule totest_support.rs - Verify
test_supportis accessible for testing in other modules - Verify all co-located unit tests still pass
- Check that test utilities (TestWriter, TestUserOutput) work correctly
Phase 7: Documentation and Cleanup (30 minutes)
- Update module-level documentation in
mod.rs - Add module documentation to each submodule
- Update imports in
mod.rsfor clarity - Remove old
user_output.rsfile - Verify documentation builds:
cargo doc --no-deps
Phase 8: Final Verification (30 minutes)
- Run pre-commit checks:
./scripts/pre-commit.sh - Verify no public API changes
- Verify all tests pass
- Verify no unused dependencies:
cargo machete - Check for any remaining TODO comments
- Manual smoke test of basic functionality
Acceptance Criteria
Note for Contributors: These criteria define what the PR reviewer will check. Use this as your pre-review checklist before submitting the PR to minimize back-and-forth iterations.
Quality Checks:
- Pre-commit checks pass:
./scripts/pre-commit.sh - All tests pass without modification:
cargo test - Documentation builds successfully:
cargo doc --no-deps - No unused dependencies:
cargo machete
Structural Criteria:
-
user_output.rsis converted touser_output/folder -
mod.rsserves as the public API entry point - All submodules are appropriately sized (< 500 lines each)
- Clear separation of concerns across submodules
- Tests are co-located with code using
#[cfg(test)]modules
Backward Compatibility:
- All existing public types remain accessible
- All existing import paths continue to work
- No changes required in code using
UserOutput - All existing tests pass without modification
- Public API surface is identical
Code Quality:
- Each module has clear, focused responsibility
- Module documentation explains purpose and usage
- Follows project module organization conventions
- No circular dependencies between submodules
- Private implementation details not leaked
Testing:
- Tests organized using
#[cfg(test)]modules per file - Test coverage maintained (no reduction)
- Test infrastructure (
test_support) easily accessible - All unit tests pass
Related Documentation
- Detailed Specification - Complete technical specification
- Module Organization Guide - Module organization conventions
- User Output Epic #102 - Parent epic
- Codebase Architecture - Overall architecture principles
Estimated Time
8-10 hours total for complete refactoring with testing and documentation