Skip to content

Spec review: add per-module contracts, quantified NFRs, and a validation strategy to the d4np-cpp spec #32

Description

@danielPoloWork

Summary

The spec defines a C++20 high-performance systems library through a design philosophy (§1), a catalog of 25 modules spanning allocation, concurrency, strings, containers, I/O, diagnostics, and parsing (§2), and one API example (§3). It currently reads as a feature list: there are no quantified performance targets, no per-module semantic contracts (thread-safety, exception-safety, allocation behavior), no security/testing/CI strategy, and several technical claims that are contradictory or imprecise. The highest-impact improvement is a per-module contract table plus measurable NFRs backed by a defined benchmark methodology.

Strengths

  • Clear, coherent design philosophy in §1 (strict RAII, string_view/span-based zero-copy APIs, compile-time optimization via Concepts/SFINAE) that fits the stated domain.
  • Well-organized module catalog in §2 with realistic scope for a systems toolkit: allocation, concurrency, zero-copy strings, flat containers, I/O, diagnostics, parsing.
  • Sensible modern-C++ choices: non-allocating view-based parsing (§2.11, §2.23), cache-friendly flat containers (§2.14–15), constexpr hashing (§2.24).
  • A concrete API example (§3) that makes the intended ergonomics inspectable rather than abstract.

Gaps

  • §1 describes the library as "Header-Only e a compilazione parziale" — as written, these are mutually exclusive distribution models. The choice drives build integration, ABI stability, and packaging; the spec must pick one or explicitly define a hybrid (header-only core with optional compiled translation units).
  • §1 groups move semantics under "Zero-Copy Design": moves avoid copies at ownership-transfer boundaries, but that is a distinct mechanism from view-based zero-copy (string_view/span), and the spec never states which APIs guarantee which. Related over-claim in §2.23: a "non-allocating" JSON parser returning string views cannot produce unescaped string values (e.g., \uXXXX, \n) without in-situ mutation or allocation — the constraint is unstated.
  • §2.2 UniqueRef<T> "non può essere NULL" ignores the moved-from state: a movable, non-nullable owning type is contradictory unless the type is non-movable or the invariant is relaxed after move; the spec defines neither.
  • §2.3 StackAllocator<Size> promises "allocazione temporanea di array dinamici", but capacity is a compile-time constant — "dynamic arrays" is misleading. The buffer lives on the stack only when the allocator instance does, and alignment guarantees and overflow-fallback policy (fail vs heap fallback) are unspecified.
  • §2.7 LockFreeQueue (MPMC) omits the hard parts of the design: progress guarantee (lock-free vs obstruction-free), bounded vs unbounded capacity, and memory reclamation (ABA hazard; hazard pointers or epoch-based reclamation) are all unaddressed.
  • §2.17 names select/poll/epoll as the async backends — epoll is Linux-only, and there is no kqueue (macOS/BSD) or IOCP (Windows) path, nor a defined async model (readiness vs completion, callback vs future). This sits oddly beside §2.9, which explicitly promises a "portabile" semaphore wrapper.
  • §2.18 and §2.22–23 define components that consume untrusted input (BinarySerializer, CliParser, JsonParser) with no threat model or fuzzing plan; the constexpr SHA-256 in §2.24 has no test-vector validation requirement and no explicit statement of whether it is in cryptographic scope, nor whether a runtime (non-constexpr) path exists.
  • §3 is titled "Uso del FlatMap constexpr" but the code performs only runtime insert/find in main(). Cross-cutting: the spec has zero quantified NFRs — "ultra-veloce" (§2.18) and "ricerche ultra-rapide" (§2.14) carry no numbers — and there is no benchmark methodology, compiler/platform matrix, sanitizer/CI plan, or error-handling policy (exceptions vs std::expected).

Proposed improvements

  • Resolve the header-only vs partially-compiled contradiction in §1 and record it as an ADR (per sources/09_architecture_decision_records.md), including ABI/API stability policy and SemVer rules.
  • Add a per-module contract table for all 25 items in §2: thread-safety guarantee, exception-safety level (basic/strong/noexcept), allocation behavior, and algorithmic complexity.
  • Specify ownership and allocator semantics: UniqueRef moved-from policy (non-movable type vs relaxed invariant), and StackAllocator fixed-capacity buffer behavior (alignment guarantees, overflow-fallback policy, placement dependence).
  • Replace qualitative performance claims with numeric targets (e.g., LockFreeQueue throughput at N producers/consumers, FlatMap lookup vs std::map/std::unordered_map baselines, Logger enqueue latency p99) and define the benchmark methodology: Google Benchmark, CPU pinning, warmup, iteration counts, statistical treatment.
  • Specify zero-allocation constraints precisely: JsonParser escape-sequence strategy (in-situ mutation vs allocating fallback) and StringSplitter/JsonParser lifetime rules for returned string_views.
  • Define LockFreeQueue semantics: progress guarantee, bounded/unbounded capacity, ABA mitigation, and the memory reclamation scheme.
  • Define the cross-platform I/O strategy for §2.17 (epoll/kqueue/IOCP abstraction, or an explicitly Linux-scoped readiness model) and the async completion model exposed to callers.
  • Add a security section: threat model for untrusted-input components (§2.18, §2.22–23), fuzzing plan (libFuzzer/AFL++ targets), and SHA-256 validation against NIST test vectors with an explicit cryptographic or non-cryptographic scoping statement.
  • Document the CI matrix: GCC/Clang/MSVC versions, C++20 feature baseline, ASan/TSan/UBSan runs, and packaging targets (CMake install, vcpkg/Conan).
  • Fix the §3 example to actually demonstrate constexpr FlatMap construction (or retitle it), and add a C4 component diagram (per sources/06_c4_model_diagrams.md) grouping the 25 modules into layers with explicit dependency directions.

Acceptance criteria

  • §1 states a single ADR-backed distribution model with an ABI/versioning policy; no contradictory wording remains.
  • Every §2 module documents thread-safety, exception-safety, and allocation behavior; at least five performance-critical modules have numeric targets with a reproducible benchmark procedure.
  • A security section covers untrusted-input parsing and hash-function scoping, with enumerated fuzzing targets and SHA-256 test-vector validation.
  • The CI matrix (compilers, platforms, sanitizers) is documented, and the §3 example compiles and matches its title.
  • One C4 component diagram and at least three ADRs (distribution model, error-handling policy, lock-free queue design) are committed alongside the spec.

Rationale

The spec's credibility rests on claims — "lock-free", "zero-copy", "non-allocating", "ultra-veloce" — that are currently unverifiable and in several places over-stated or internally contradictory. Pinning each module to explicit contracts, measurable targets, and a defined validation pipeline turns the document from a feature wishlist into a reviewable engineering design, and resolving the §1 distribution contradiction unblocks every downstream build and packaging decision.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions