Skip to content

Builder APIs disagree on setter naming, entry, and terminal method #434

Description

@ciaranra

Problem

PECOS has fifteen Python-facing builders and they disagree on all three parts of the
builder contract: how setters are named, how the builder is entered, and how it is
terminated. The split is close to even, so a reader cannot infer any of it.

Setter naming: 8 versus 7

with_* bare
general_noise() (47 methods) sim(...)
depolarizing_noise() (7) DetectorErrorModel.builder() (14)
biased_depolarizing_noise() (7) BpOsdBuilder (5)
DemBuilder (6) BpLsdBuilder (4)
DemSamplerBuilder (4) RelayBpBuilder (8)
InfluenceBuilder (4) MinSumBpBuilder (3)
SurfacePatchBuilder (3) UnionFindBuilder (1)
ColorCode488Builder (1)

Two plausible dividing lines both fail:

  • user-facing versus low-level — the noise builders are user-facing and use with_*,
    while sim() is user-facing and bare.
  • Rust-backed versus PythonBpOsdBuilder is Rust-backed and bare, DemBuilder is
    Rust-backed and with_*.

Terminal method

  • .build() — most builders
  • .run()sim(...)
  • none — the noise builders, which are passed directly into .noise(...)

Entry

  • free function: sim(...), general_noise(), depolarizing_noise()
  • classmethod: DetectorErrorModel.builder()
  • direct construction with required positional arguments: BpOsdBuilder(pcm, error_rate)

Why now

PR #420 added DetectorErrorModel.builder() and chose bare setters partly on the
strength of a "user-facing builders use bare setters" reading of the codebase. That
rule does not hold
— see the counterexamples above. The choice is defensible on other
grounds (it is scalar configuration on a Python surface, and the Rust API Guidelines
leave builder naming explicitly open, reserving with_ for constructors such as
Vec::with_capacity), but it was made against a pattern that turned out to be imaginary.
Rather than let that stand as an accidental precedent, the project should decide.

Proposal

  1. Pick one setter convention and write it down where it will be found — a short
    section in the contributing or API-conventions docs, not just an issue comment.
  2. Standardize the terminal. .build() everywhere, with sim(...).run() as a
    deliberate, documented exception because it also executes.
  3. Decide whether noise builders should have a terminal at all, or remain
    builder-shaped objects consumed directly by .noise(...).
  4. Converge entries on one shape, or state the rule that selects between them.
  5. Migrate with aliases and a deprecation ramp, as in Deprecation ramp: align pecos-engines GeneralNoiseModel idle-noise API with the structured vocabulary #424 — several of these are public
    and widely used.

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpythonPull requests that update python coderustPull requests that update rust code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions