AyCode.Core/docs/CONVENTIONS.md

5.0 KiB

Conventions

Naming

  • Prefix: All framework types use Ac prefix (e.g., AcDalBase, AcBinarySerializer, AcLoggerBase).
  • Interfaces: Standard I prefix + Ac (e.g., IAcDbContextBase, IAcUserDbSetBase).
  • Extensions: {Domain}Extensions.cs (e.g., StringExtensions, CollectionExtensions, AcDbSessionExtension).
  • Test bases: Ac{Domain}TestBase or AcBase_{TestName} for inherited test methods.
  • Folder names — plural (workspace-wide): source folder names plural to avoid type-vs-folder namespace collisions (Serializers/AcBinarySerializer.cs, NOT Serializer/). 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 (Ac for AyCode., Mg for Mango.Nop.; product/consumer repos un-prefixed) is an architectural rule — see ARCHITECTURE.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 or enableInternString flag.
  • 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. See AyCode.Services.Server/docs/SIGNALR_DATASOURCE/README.md.
  • Binary protocolAyCodeBinaryHubProtocol (derived from AcBinaryHubProtocol) is the transport protocol. Zero-copy write: AcBinarySerializer.Serialize(value, output) directly to pipe. Zero-copy read: SequenceReader<byte> + type-aware deserialization via SignalParams.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, TestableSignalRHub2 bypass 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