Skip to content

Extract narrow interface for CWService radio dependency #87

@ny4i

Description

@ny4i

Problem

CWService depends on RadioController directly. To unit-test CWService, we had to make 3 methods virtual on RadioController (isConnected, setCWSpeed, getCWSpeedRange) and mock via inheritance. This works but:

  1. Performance: MockRadioForCW inherits RadioController which starts a worker thread on construction. Even with a shared fixture, the CW test takes 1.52s for 11 trivial tests — almost all of that is thread start/stop overhead.
  2. Coupling: CWService only needs 3 methods but inherits the entire RadioController surface area (connect, disconnect, frequency, band, mode, PTT, RIT, XIT, split, etc.).
  3. Fragility: Adding new RadioController constructor side effects will silently slow down or break CW tests.

Proposed Fix

Extract a narrow interface:

class ICWRadio {
public:
    virtual ~ICWRadio() = default;
    virtual bool isConnected() const = 0;
    virtual void setCWSpeed(int wpm) = 0;
    virtual void getCWSpeedRange(int& minWpm, int& maxWpm) const = 0;
};
  • RadioController implements ICWRadio
  • CWService depends on ICWRadio* instead of RadioController*
  • Test mock implements ICWRadio directly — no thread, no overhead
  • Remove virtual from the 3 RadioController methods (no longer needed)

Current Workaround

Comment in RadioController.h line 42-43 documents the technical debt:

// Note: isConnected, setCWSpeed, getCWSpeedRange are virtual to allow test mocking.
// Ideally CWService would depend on a narrow interface, not RadioController directly.

Shared test fixture in test_cw_service.cpp mitigates the performance issue (6.5s → 1.52s).

Acceptance Criteria

  • ICWRadio interface extracted
  • CWService depends on ICWRadio*
  • RadioController implements ICWRadio
  • Test mock implements ICWRadio directly (no thread overhead)
  • CW test runs in <0.5s
  • virtual removed from RadioController methods

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions