Engineering standards
เนื้อหานี้ยังไม่ได้แปลเป็นภาษาไทย แสดงเป็นภาษาอังกฤษแทน
These are the constraints we hold ourselves to when shipping engine changes. Every PR is reviewed against this list.
API design
Section titled “API design”- Additive over breaking. Within a minor, everything is additive. New parameters are optional with safe defaults. New interfaces have base implementations.
- Avoid leaking implementation types. Public API surfaces use abstractions. Implementation types live in non-public namespaces.
- Symmetric naming.
IXxxRegistry↔IXxxContributor.AddXxx(...)↔UseXxx(...). Pick a pattern and stay consistent within a domain. - No “Manager” classes. A class that’s named “Manager” is almost always two classes that haven’t been separated yet.
- Capability before transport. Define capability contracts first, then transport adapters. Modules should be transport-agnostic.
- All I/O is async. No
.Result, no.Wait(), noGetAwaiter().GetResult()in production code. Asyncsuffix on every async method that returnsTask/ValueTask.CancellationToken ctis the last parameter on every async method.ConfigureAwait(false)in non-host library code; not needed in app code that already runs in a context-freeWebApplication.
Exceptions
Section titled “Exceptions”- Don’t catch
Exception. Catch specific types or use exception filters. - Don’t swallow exceptions silently. If you must catch, log with structure and rethrow or escalate to the failure policy.
- Composition failures are fatal. Don’t paper over them.
Logging
Section titled “Logging”- Structured. Use named placeholders, never string concatenation.
- Level discipline:
Tracefor noisy diagnostics,Debugfor development,Informationfor state transitions,Warningfor recoverable issues,Errorfor caller-visible failures,Criticalfor service-wide failure. - Use
ILogger<T>typed loggers, not the staticLogclass.
Allocations
Section titled “Allocations”- Hot paths use pooled / stack-allocated buffers (
Span<T>,ArrayPool<T>). - Avoid LINQ in hot paths; manual loops +
foreachover arrays. - The benchmarks gate hot-path regressions of more than ~5%.
- Every change to a public API has a test that demonstrates the change.
- Composition smoke tests catch wiring failures.
- Behavior specs assert the externally observable behaviour.
- Integration tests against real backends (Postgres, Redis, Kafka, …) live behind
Category=Integration.
Documentation
Section titled “Documentation”- Public types have XML comments.
Cephalon.ReferenceDocsconsumes them. - Behaviour changes update the relevant hand-authored docs.
- New capabilities update the maturity audit and the conformance matrix.
Performance discipline
Section titled “Performance discipline”- The benchmarks suite is part of CI. PRs that regress hot paths get the regression noted in review.
- The latency budgets per public API are tracked in the benchmarks themselves.
- Avoid blocking calls in the request path. Avoid I/O in
OnRegister.
Compatibility metadata
Section titled “Compatibility metadata”- New packages carry the engine version, target frameworks, publisher metadata.
- Signed packages carry the signature chain. Trust-store entries land alongside the package.
Where things land
Section titled “Where things land”Cephalon.Abstractions: pure contracts. No reflection, no DI calls.Cephalon.Engine: composition. Holds the manifest schema.- Host adapters: glue the engine into a runtime. Never re-implement composition.
- Companion packages: capability providers. Always opt-in.
If a PR doesn’t fit one of these lanes, the design is probably wrong.