Open table of contents
Conclusion
Translate vendor state and failure into explicit types to reduce caller assumptions.
Context
Passing COM state, nulls and exceptions directly makes every caller depend on vendor behavior. Concentrate translation in the adapter.
Design and verification scope
Assess the following responsibilities and boundaries when designing and verifying a configuration.
- COM interop
- Nullable values
- Stateful APIs
- Discriminated unions
- Option and Result
- Domain types
- Resource lifetime
For a domain that requires non-negative prices, missing and invalid values can be represented explicitly. This minimal conversion example leaves COM creation, cleanup and threading to the surrounding adapter.
open System
type Price = private Price of decimal
type ConversionError =
| MissingValue
| InvalidPrice of decimal
let toPrice (value: Nullable<decimal>) =
if not value.HasValue then Error MissingValue
elif value.Value < 0m then Error (InvalidPrice value.Value)
else Ok (Price value.Value)
Decision rationale
Use the relationship between COM interop and Resource lifetime to compare the responsibilities of the selected approach and alternatives. Separate retained constraints from what the new boundary can change.
Trade-offs
Compare the implementation, maintenance and review work introduced by Nullable values with the control it provides. Include failure paths, operator effort and conditions in which the approach should not be adopted.
Limitations
Typed conversion does not remove COM threading constraints or resource lifetimes. Callers still need explicit thread ownership, cleanup and error classification. Reuse also depends on the original wrapper’s authorship and license terms.
Related case context
These cases provide attributed design context. They do not establish that the proposed experiments or configurations were delivered in those engagements.