Skip to content

refactor(#445): delete five "for tests" constructor seams no caller ever passes — production −41 lines - #446

Merged
tylerkron merged 1 commit into
mainfrom
issue-445-remove-test-seams
Oct 27, 2026
Merged

tylerkron merged 1 commit into
mainfrom
issue-445-remove-test-seams

Conversation

@tylerkron

@tylerkron tylerkron commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Closes #445. Not merging. This is for review.

What was wrong

Four production types took constructor parameters that were documented as existing "for tests". No test, no tool and no production code ever passed a value for them, so each one was a x ?? productionDefault that always used the right-hand side. Three of the doc comments described tests that do not exist:

  • FirmwareUpdateCoordinator: "tests inject a fake to assert WiFi sequencing"
  • HidBootloaderDiscovery: "tests inject a fake"
  • FirmwareDialogViewModel: "(tests pass mocks via the constructor args)"

A comment like that gives the next reader a reason to leave the code alone without checking whether anything still uses it. This PR deletes the seams and the false comments. It has the same shape as #420.

What changed

The change only removes code. There is no behaviour change and no test change.

type removed what the code does now
FirmwareUpdateCoordinator wifiFirmwareUpdateServiceFactory parameter, its field, its ?? line, 5 doc lines calls CreateWifiFirmwareUpdateService(...) directly. The local is still typed IFirmwareUpdateService, so the calls go through the same interface as before.
DaqifiViewModel the same parameter, its 3 doc lines, the forwarding argument none of the other parameters are affected.
HidBootloaderDiscovery pollInterval and finderFactory parameters, both fields, both ?? lines, 5 doc lines Start() builds new HidDeviceFinder() with DefaultPollInterval. It still creates a fresh finder on every Start, as the old factory did.
FirmwareDialogViewModel firmwareUpdateService and watcher parameters, their ?? legs and docs resolves both from DI, which was already the only path any caller used.
AppLoggerLoggerProvider the appLogger parameter and the constructor the field now initialises from AppLogger.Instance, at the same point in construction.

Two parameters are kept because callers pass real values to them:

  • FirmwareDialogViewModel's firmwareDownloadService. AvaloniaCapture passes an offline stub. Its doc now says that instead of "for tests".
  • targetDevicePath. The connection dialog passes it.

Diffstat (git diff --numstat origin/main...HEAD): raw +12 / −53 in 5 production files. Blank lines excluded and split by kind:

  • code: +8 / −27. All 8 added lines rewrite a line that was removed.
  • comments: +4 / −25

Proof that nothing passes these parameters (on origin/main @ 97be4df)

Verification

  • Build gate, run under a build.1 lock:
    • desktop head: dotnet build, green (0 errors)
    • iOS restore without -r
    • iOS Release -r iossimulator-arm64 --no-restore: green (exit 0)
  • dotnet test Daqifi.Avalonia.Tests: 1179 passed, 0 failed, 0 skipped (macOS, full suite)
  • Warnings: no change, read from CI's own logs on both ends (main Build run 35552132041 at 97be4df against this PR's run 35653845541). I compared the distinct first-party warnings, keyed on file + code + message (line numbers left out because the touched files shift). The sets are identical in all four jobs: Android 109/109, Desktop-on-macOS 107/107, Library+Desktop 108/108, iOS 107/107. Those are distinct counts, not the printed totals.
  • packages.lock.json is unchanged.
  • No device was needed. None of these paths is observable on the board without a flash, and flashing is on the denylist.

Coverage, stated plainly:

  • FirmwareUpdateCoordinator is covered by WifiFlashPlatformGateTests, FirmwareUpdateCancellationTests and FirmwareUploadAffordanceTests. None of them constructs it with the factory, so they run exactly the path this PR keeps.
  • HidBootloaderDiscovery and AppLoggerLoggerProvider have no covering tests. The change there only touches the constructor signature: each removed ?? always took its right-hand side, which is now written directly. The evidence is a green build plus the unchanged call sites in App.cs.

Qodo

  • R1 on 40bfef0 was graded ⚖️ Balanced and came back clean: 0 bugs, 0 rule violations, 0 requirement gaps.
  • R2 ran on the same head. It also came back clean, but its rationale reads "No changes from previous review". So only R1 actually reviewed the code, and R2 does not count as an independent second pass.
  • No inline threads were opened on either round. I re-checked both surfaces after a settle wait of at least 3 minutes each time.
  • CI is green on every job, including the Android head.

Out of scope

🤖 Generated with Claude Code

…ver passes

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tylerkron

Copy link
Copy Markdown
Contributor Author

/agentic_review

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Remove unused firmware, HID, and logging constructor seams

✨ Enhancement 🕐 10-20 Minutes

Grey Divider

AI Description

• Remove unused constructor overrides across firmware, HID discovery, and logging components.
• Use established production defaults and DI paths directly without changing runtime behavior.
• Correct comments that falsely described nonexistent test overrides.
Diagram

graph TD
  C["Update coordinator"] -->|"constructs directly"| W["WiFi updater"]
  H["HID discovery"] -->|"creates on Start"| F["HID finder"]
  D["Firmware dialog"] -->|"resolves services"| DI["App service provider"]
  L["Logger provider"] -->|"uses directly"| A["AppLogger singleton"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Require explicit dependency injection
  • ➕ Keeps dependencies visible in constructor contracts
  • ➕ Preserves straightforward substitution for future unit tests
  • ➖ Requires composition-root and caller changes
  • ➖ Retains abstractions with no current test or production consumer
  • ➖ Expands scope without delivering current behavioral value

Recommendation: Keep the PR's direct-production-path approach. Required constructor injection would be preferable if substitution were actively needed, but repository-wide caller evidence shows these optional seams are unused; removing them reduces misleading API surface while preserving behavior.

Files changed (5) +12 / -53

Refactor (5) +12 / -53
FirmwareUpdateCoordinator.csConstruct the WiFi firmware updater directly +2/-10

Construct the WiFi firmware updater directly

• Removes the unused WiFi update service factory parameter and field. WiFi flashing now calls the existing production factory method directly while retaining the interface-typed local and existing update flow.

Daqifi.Avalonia/Daqifi.Desktop/Device/Firmware/FirmwareUpdateCoordinator.cs

HidBootloaderDiscovery.csUse fixed production HID discovery dependencies +3/-15

Use fixed production HID discovery dependencies

• Removes optional polling interval and finder factory overrides. Each Start call still creates a fresh HidDeviceFinder, now using DefaultPollInterval directly.

Daqifi.Avalonia/Daqifi.Desktop/Device/Firmware/HidBootloaderDiscovery.cs

AppLoggerLoggerProvider.csInitialize the logger provider from the singleton +1/-12

Initialize the logger provider from the singleton

• Removes the unused optional constructor and initializes the backing logger directly from AppLogger.Instance.

Daqifi.Avalonia/Daqifi.Desktop/Loggers/AppLoggerLoggerProvider.cs

DaqifiViewModel.csStop forwarding the unused WiFi updater factory +0/-5

Stop forwarding the unused WiFi updater factory

• Removes the optional WiFi service factory from the view-model constructor and its FirmwareUpdateCoordinator call. Other firmware dependencies and defaults remain unchanged.

Daqifi.Avalonia/Daqifi.Desktop/ViewModels/DaqifiViewModel.cs

FirmwareDialogViewModel.csResolve updater and watcher exclusively through DI +6/-11

Resolve updater and watcher exclusively through DI

• Removes unused constructor overrides for the firmware updater and bootloader watcher, resolving both through the application service provider. Retains the firmware download override used by the capture harness and clarifies its documentation.

Daqifi.Avalonia/Daqifi.Desktop/ViewModels/FirmwareDialogViewModel.cs

@qodo-code-review

qodo-code-review Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit 40bfef0 ⚖️ Balanced

Results up to commit 40bfef0 ⚖️ Balanced


No changes from previous review

Grey Divider

Qodo Logo

@tylerkron

Copy link
Copy Markdown
Contributor Author

/agentic_review

@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 40bfef0

@tylerkron

Copy link
Copy Markdown
Contributor Author

Qodo-clean, CI green — ready for review. R1 (⚖️ Balanced) is the only round that reviewed the code; R2 on the same head says "No changes from previous review". Not merging.

@tylerkron

Copy link
Copy Markdown
Contributor Author

Sweep: five-way merge of main + #435 + #436 + #437 + #443 + #446 is clean

I built all five PRs merged onto origin/main 97be4df, using the heads 2bacbf3, b36c347, d50ef98, 9e29bb4 and 40bfef0. Nothing was pushed and nothing was merged.

@tylerkron

Copy link
Copy Markdown
Contributor Author

Sweep update: the six-way merge of main 97be4df + #435 + #436 + #437 + #443 + #446 + #449 is clean. The tree is b5f3d4d7, and the five-way 27e0b21c reproduced exactly. The full gate, HeadlessBench --no-incremental, 1208/1208 tests and parity 39/39 all pass, and this PR's head is unchanged. Details are on #449.

@tylerkron
tylerkron added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit d355480 Oct 27, 2026
7 checks passed
@tylerkron
tylerkron deleted the issue-445-remove-test-seams branch October 27, 2026 02:52
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.

Five constructor seams documented as "for tests" that no test passes — three of the comments describe tests that do not exist

1 participant