Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 4, 2025

Refactors UserOutput to use trait dispatch instead of direct formatting, enabling new message types without modifying core code (Open/Closed Principle).

Changes

Core abstractions

  • OutputMessage trait with format(), required_verbosity(), channel() methods
  • Channel enum (Stdout/Stderr) for routing logic
  • Generic write(&mut self, message: &dyn OutputMessage) method in UserOutput

Message implementations

  • Six concrete types: ProgressMessage, SuccessMessage, WarningMessage, ErrorMessage, ResultMessage, StepsMessage
  • Each encapsulates formatting, verbosity requirements, and channel routing
  • All convenience methods (progress(), success(), etc.) now delegate to write()

Backward compatibility

  • API unchanged - all existing code works without modification
  • Verbosity filtering and theme support preserved

Example: Adding custom message types

struct DebugMessage { text: String }

impl OutputMessage for DebugMessage {
    fn format(&self, _theme: &Theme) -> String {
        format!("[DEBUG] {}\n", self.text)
    }
    fn required_verbosity(&self) -> VerbosityLevel { VerbosityLevel::Debug }
    fn channel(&self) -> Channel { Channel::Stderr }
}

// Use without modifying UserOutput
output.write(&DebugMessage { text: "info".to_string() });

External code can now define application-specific message types without touching UserOutput.

Testing

15 new tests including custom message type demonstrations. All 1107 tests pass.

Original prompt

This section details on the original issue you should resolve

<issue_title>Use Message Trait for Extensibility</issue_title>
<issue_description>## Overview

Implement a trait-based message system for the UserOutput module to achieve true extensibility following the Open/Closed Principle. This allows new message types to be added without modifying existing code by having each message type encapsulate its own formatting, verbosity requirements, and channel routing logic.

Current State: The codebase already has Theme support (Issue #124) and VerbosityFilter (Issue #103) implemented, providing the foundation for this refactoring.

Specification

See detailed specification: docs/issues/127-use-message-trait-for-extensibility.md

(Link will be updated after issue number assignment and file rename)

🏗️ Architecture Requirements

DDD Layer: Presentation
Module Path: src/presentation/user_output.rs
Pattern: Trait-based polymorphism with concrete message types

Key Changes

  • Define OutputMessage trait with methods: format(), required_verbosity(), channel()
  • Implement concrete message types: ProgressMessage, SuccessMessage, ErrorMessage, ResultMessage, StepsMessage, WarningMessage
  • Add write(&mut self, message: &dyn OutputMessage) method to UserOutput
  • Refactor convenience methods to use trait dispatch

Implementation Plan

Phase 1: Define Core Trait and Types (2 hours)

  • Define OutputMessage trait and Channel enum
  • Add comprehensive documentation
  • Write unit tests for trait definition

Phase 2: Implement Concrete Message Types (3 hours)

  • Implement all message types with trait implementations
  • Write unit tests for each message type

Phase 3: Refactor UserOutput (2.5 hours)

  • Add generic write() method
  • Update all convenience methods to use trait dispatch
  • Ensure backward compatibility

Phase 4: Testing and Validation (2 hours)

  • Run existing unit tests
  • Add new tests for trait-based dispatch
  • Add extensibility example (custom message type)
  • Run integration and E2E tests

Phase 5: Documentation and Cleanup (1 hour)

  • Update rustdoc comments
  • Add example of creating custom message type
  • Clean up unused code

Estimated Total Time: ~11 hours

Acceptance Criteria

Quality Checks:

  • Pre-commit checks pass: ./scripts/pre-commit.sh

Task-Specific Criteria:

  • OutputMessage trait is defined with all required methods
  • All existing message types implement the trait
  • UserOutput has a generic write() method that accepts trait objects
  • All existing convenience methods still work (backward compatibility)
  • Verbosity filtering works correctly for all message types
  • Channel routing (stdout vs stderr) works correctly
  • Adding a new message type requires ZERO changes to UserOutput struct
  • All existing tests pass without modification
  • New tests demonstrate extensibility with custom message type example
  • Code follows Open/Closed Principle

Related

Benefits

✅ True Open/Closed Principle - add new message types without touching existing code
✅ Encapsulation - each message knows how to format itself
✅ Single Responsibility - each message type has one clear purpose
✅ Testability - message types can be tested independently
✅ Extensibility - custom message types can be defined outside the module</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits November 4, 2025 08:29
- Define OutputMessage trait with format(), required_verbosity(), and channel() methods
- Define Channel enum for routing messages to stdout/stderr
- Implement concrete message types: ProgressMessage, SuccessMessage, WarningMessage, ErrorMessage, ResultMessage, StepsMessage
- Add generic write() method to UserOutput for trait-based dispatch
- Refactor all convenience methods to use trait dispatch
- Add comprehensive tests including custom message type examples
- All 1107 tests passing with 100% backward compatibility

Co-authored-by: josecelano <[email protected]>
Copilot AI changed the title [WIP] Implement trait-based message system for UserOutput module Implement trait-based message system for UserOutput extensibility Nov 4, 2025
Copilot AI requested a review from josecelano November 4, 2025 08:54
Copy link
Member

@josecelano josecelano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 15a8c1b

@josecelano josecelano marked this pull request as ready for review November 4, 2025 09:16
@josecelano josecelano merged commit 03875ec into main Nov 4, 2025
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use Message Trait for Extensibility

2 participants