Files
lmxopcua/code-reviews/Driver.FOCAS.Contracts/findings.md
T
Joseph Doherty 97020d0527 review(Driver.FOCAS.Contracts): first review; keep Writable=true default (re-triaged)
First review at 7286d320. -001 re-triaged Won't-Fix: the 'FOCAS is read-only' premise was
WRONG (FOCAS supports PMC/data writes); flipping Writable default to false broke 6 consuming
write tests -> reverted to true, doc corrected. -003/-004 doc fixes resolved. -002
(WriteIdempotent not threaded, Driver.FOCAS) Open.
2026-06-19 12:22:53 -04:00

6.3 KiB

Code Review — Driver.FOCAS.Contracts

Field Value
Module src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts
Reviewer Claude Code
Review date 2026-06-19
Commit reviewed 7286d320
Status Reviewed
Open findings 1

Checklist coverage

A comprehensive review completes every category, recording "No issues found" where a category produced nothing rather than leaving it blank.

# Category Result
1 Correctness & logic bugs 1 finding (Driver.FOCAS.Contracts-001)
2 OtOpcUa conventions No issues found
3 Concurrency & thread safety No issues found
4 Error handling & resilience No issues found
5 Security No issues found
6 Performance & resource management No issues found
7 Design-document adherence 1 finding (Driver.FOCAS.Contracts-002)
8 Code organization & conventions No issues found
9 Testing coverage No test project — findings recorded, deferred by task scope
10 Documentation & comments 2 findings (Driver.FOCAS.Contracts-003, Driver.FOCAS.Contracts-004)

Findings

Driver.FOCAS.Contracts-001

Field Value
Severity Low
Category Correctness & logic bugs
Location src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts/FocasDriverOptions.cs:144
Status Won't Fix

Description: FocasTagDefinition's positional parameter Writable defaults to true. The original review hypothesised that FOCAS is read-only by design (claiming WireFocasClient.WriteAsync always returns BadNotWritable and the def.Writable gate is dead code) and that the default should therefore be false. That premise was wrong — FOCAS supports PMC/data writes, the def.Writable gate is live, and six Driver.FOCAS.Tests write tests (FocasPmcBitRmwTests, FocasReadWriteTests) rely on Writable defaulting to true.

Recommendation: Leave the default at true. (The original recommendation to flip it to false is withdrawn.)

Resolution: Won't Fix (re-triaged 2026-06-19). The "FOCAS is read-only" premise was incorrect — the consuming Driver.FOCAS.Tests write suites failed when the default was flipped to false. The default Writable = true is intentional and correct; the change was reverted. The accompanying <param> doc was kept but corrected to describe the live write path. (Caught by the orchestrator's consuming-driver-test safety net, which the no-test-project Contracts build could not exercise.)


Driver.FOCAS.Contracts-002

Field Value
Severity Low
Category Design-document adherence
Location src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts/FocasDriverOptions.cs:139-145
Status Open

Description: FocasTagDefinition carries a WriteIdempotent field (default false) that the FOCAS driver never reads anywhere — neither in DiscoverAsync, ReadAsync, nor WriteAsync. DiscoverAsync always passes WriteIdempotent: false to DriverAttributeInfo (hardcoded), so the field has no runtime effect. docs/drivers/FOCAS.md does not mention WriteIdempotent in its configuration tables, making its purpose undiscoverable to operators.

Recommendation: Either (a) thread FocasTagDefinition.WriteIdempotent through to DriverAttributeInfo in DiscoverAsync so the field has runtime effect and matches the pattern of other drivers, or (b) remove it from the record and the FocasDriverConfigDto wire DTO. Option (a) is the safer fix and matches the design of Modbus and other drivers. This is deferred because the fix touches FocasDriver.DiscoverAsync outside this module and requires a driver-level test change.

Resolution: (empty until closed)


Driver.FOCAS.Contracts-003

Field Value
Severity Low
Category Documentation & comments
Location src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts/FocasDriverOptions.cs:147-155
Status Resolved

Description: FocasProbeOptions is the only class in this module without a class-level XML <summary> comment. All other options classes (FocasDriverOptions, FocasFixedTreeOptions, FocasHandleRecycleOptions, FocasAlarmProjectionOptions) have class-level summaries. This inconsistency causes IDE tooltips and XML-doc generators to produce a blank description for FocasProbeOptions.

Recommendation: Add a class-level <summary> consistent with the pattern of the other options types: Controls periodic connectivity probing. One <c>cnc_rdcncstat</c> call per configured device per tick; transitions fire <c>OnHostStatusChanged</c>.

Resolution: Fixed in the same commit as this review. Added XML <summary> to FocasProbeOptions. Verified by build (no test project).


Driver.FOCAS.Contracts-004

Field Value
Severity Low
Category Documentation & comments
Location src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Contracts/FocasDriverOptions.cs:107-131
Status Resolved

Description: FocasDeviceOptions's class-level <summary> references <paramref name="Series"/> but there is no corresponding <param name="Series"> documentation block. Only PositionDecimalPlaces has a <param> entry; HostAddress, DeviceName, and Series are all undocumented at the parameter level. This leaves the expected URI form of HostAddress (focas://{ip}[:{port}]) and the valid values of Series undiscoverable from the XML doc.

Recommendation: Add <param> entries for HostAddress, DeviceName, and Series documenting the expected URI form for HostAddress and referring to FocasCncSeries.Unknown as the permissive default for Series.

Resolution: Fixed in the same commit as this review. Added <param> doc entries for HostAddress, DeviceName, and Series to FocasDeviceOptions. Verified by build (no test project).