5.0 KiB
Conventions
Naming
- Prefix: All framework types use
Acprefix (e.g.,AcDalBase,AcBinarySerializer,AcLoggerBase). - Interfaces: Standard
Iprefix +Ac(e.g.,IAcDbContextBase,IAcUserDbSetBase). - Extensions:
{Domain}Extensions.cs(e.g.,StringExtensions,CollectionExtensions,AcDbSessionExtension). - Test bases:
Ac{Domain}TestBaseorAcBase_{TestName}for inherited test methods. - Folder names — plural (workspace-wide): source folder names plural to avoid type-vs-folder namespace collisions (
Serializers/AcBinarySerializer.cs, NOTSerializer/). Namespace gets its own identity, separate from any single type. - English-only identifiers (workspace-wide): all identifiers (types, members, namespaces, files, folders) use English. Native-language names (Hungarian or otherwise) forbidden even in product/consumer code — readability for LLM/human collaborators.
Workspace-wide note: the framework-only class prefix mandate (
Acfor AyCode.,Mgfor Mango.Nop.; product/consumer repos un-prefixed) is an architectural rule — seeARCHITECTURE.md#class-prefix--framework-only-mandate. The first bullet above is the AyCode.Core-specific instance of that rule.
XML Documentation
<summary> — brief, developer-facing, readable in VS IntelliSense tooltip. NO implementation details, NO wire-format / byte-level / perf specifics — those live in docs/TOPIC/*.md. Add <example> only when usage is non-obvious; otherwise omit.
Patterns
- Extension methods over instance methods for CRUD — clean interfaces, composable impls.
- Session/Transaction pattern in DataLayers:
Session()for reads,Transaction()for writes. Both are mutex-protected. - Generic interface hierarchy for entities: Interface → Abstract Entity → Concrete (in consuming project).
- Partial classes for large serializers (AcBinarySerializer, AcToonSerializer split across 10+ files).
- Source generation for hot-path serialization. Runtime reflection only as fallback.
Serialization Conventions
- Binary serializer properties are written in alphabetical order (matches source generator output).
- String interning is opt-in via
[AcStringIntern]attribute orenableInternStringflag. - Chain API for multi-type deserialization with cross-reference resolution.
- Feature flags on
[AcBinarySerializable]eliminate dead code from generated output.
SignalR Conventions
See AyCode.Services/docs/SIGNALR/README.md for full architecture documentation.
- Single dispatch method — all communication goes through
OnReceiveMessage(int messageTag, int? requestId, SignalParams signalParams, object data). Do not add new hub methods. - Tag-based routing — associate methods with integer tags via
[SignalR(tag)](server) or[SignalRSendToClient(tag)](client). Tags must be unique across the entire system. - CRUD bundles — entities use
SignalRCrudTags(getAllTag, getItemTag, addTag, updateTag, removeTag)with 5 independent tag integers. Tags must be unique across the system. SeeAyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md. - Binary protocol —
AyCodeBinaryHubProtocol(derived fromAcBinaryHubProtocol) is the transport protocol. Zero-copy write:AcBinarySerializer.Serialize(value, output)directly to pipe. Zero-copy read:SequenceReader<byte>+ type-aware deserialization viaSignalParams.SignalDataType. Three read paths: byte[] fast-path (0x44 tag), IsRawBytesData (raw byte[]), typed deserialization.
⚠️ Temporary: JSON-in-Binary Request Parameters
Client→server request parameters use a JSON-inside-Binary envelope — cross-cutting tech debt, migration to pure Binary planned. Canonical: AyCode.Core/AyCode.Core/docs/XCUT/XCUT_ISSUES.md#accore-xcut-i-x8q1. Cross-refs: BINARY_ISSUES.md + SIGNALR_ISSUES.md (same ID). Migration: BINARY_TODO.md#accore-bin-t-s8p4. Do NOT attempt as a side-effect — requires coordinated client+server+consuming-project changes.
Testing
- MSTest framework across all test projects.
- Abstract test bases with
AcBase_prefixed methods for reusable test logic. - TestDataFactory for centralized test data creation with ID sequencing.
- Testable infrastructure for SignalR:
TestableSignalRClient2,TestableSignalRHub2bypass real connections.
Framework-First Placement
Every new type — generic or consumer-specific?
| Trait | Verdict |
|---|---|
| Contains a consumer's product name, tenant, or URL | REJECT from framework |
| Same pattern appears in 2+ consumers | PROMOTE to framework |
| Abstract/virtual hooks for consumer customization | ACCEPT in framework |
| Requires a specific concrete type from a consumer | REDESIGN — use generic/options/extension pattern |
Pre-commit check:
- No consumer-name string in any identifier, namespace, docstring, or doc
- No hardcoded consumer-specific values
- Extension methods / base classes / options classes cover the N-consumer use case
Full doctrine: ARCHITECTURE.md#framework-vs-consumer-boundary