Skip to content

Naming

Names are the primary documentation. These rules exist because the legacy codebase lost whole features to casing mistakes (D-03, D-04) and because _Misc, cider, rg_base and Exausted are all real identifiers a maintainer had to decode.


1. Casing

Element Convention Example
Namespace, type, method, property, event, constant PascalCase InventoryService
Interface PascalCase, I prefix IPersistenceBackend
Parameter, local camelCase itemDefinition
Private field _camelCase _registry
Static readonly / const PascalCase MaximumDoors
Type parameter T prefix TDefinition
Async method suffix Async LoadCharacterAsync

2. No abbreviations

Write the word.

inv inventory
cfg, conf configuration
plr, ply player
ent entity
amt amount
msg message
tmp (name what it holds)
mgr (see §4)
svc service
idx index
btn button

Permitted, because they are more readable than the expansion and are universally understood in this domain: Id, Ui, Rpc, Hp, Json, Http, Db, Npc, Ai, Fov.

Loop counters i, j, k and lambda parameter x are permitted in bodies of five lines or fewer. Beyond that, name them.


3. Say what it is

A name describes the concept, not the container.

Why
ItemDictionary ItemRegistry The container type can change
PlayerList Roster Same
DoorArray Doors Plurals are enough
DataManager CharacterStore See §4
StringHelper (delete it) See §4

4. Banned suffixes

Manager, Helper, Util, Utils, Utility, Handler, Processor, Data, Info, Base.

These are what you write when the class has no single responsibility. If you cannot name the type without one, the type is doing more than one thing — split it, and the names will appear.

Legitimate replacements: Registry, Store, Service, Factory, Provider, Policy, Resolver, Validator, Calculator, Serializer.

Base is permitted only on an abstract type genuinely designed for inheritance, and inheritance is limited to two levels (00_CODING_STANDARDS.md).


5. Booleans read as assertions

IsLocked, HasAccess, CanAfford, WasArrested, ShouldPersist.

Never negative: IsNotReady forces the reader to invert twice at every call site. Use IsReady and negate at the call.


6. Methods are verbs

Transfer, Purchase, Arrest, Resolve, Validate.

  • A method returning a value without side effects: Get…, Find…, Calculate…, or a property.
  • Get implies cheap and always succeeds. Find implies it may return null. Load implies I/O and is Async.
  • A method with side effects reads as a command: Purchase, not DoPurchase or HandlePurchase.

7. Events

Events are named for what happened, in the past tense, and carry a payload record:

public readonly record struct DoorPurchased(Character Buyer, Door Door, int Price);
public readonly record struct CharacterArrested(Character Character, TimeSpan Duration);

Cancellable events are named for what is about to happen, and expose cancellation explicitly — never by returning a truthy value (D-07):

public sealed class DoorPurchasing : CancellableEvent {  }

8. Namespaces

Applejack.Core.<Concern>          Logging, Events, Persistence, Configuration
Applejack.<Module>                Character, Items, Inventory, Economy, Crime, Jobs…
Applejack.<Module>.<Concern>      .Components, .Rules, .Persistence, .Ui

The namespace matches the folder path. One type per file, filename matching the type.

No cider prefix. The legacy internal name is historical; it appears in Documentation/Legacy/ and nowhere else.


9. Domain vocabulary

Use these consistently. Where the legacy name was misleading, the new name is given and the old one is recorded for translation.

Term Means Legacy name
Character A playable persona (none — was the Steam account)
Account The persistent Steam-level identity above characters ply.cider
Item definition The authored template ITEM / GM.Items[id]
Item instance A specific item with identity and state (did not exist)
Inventory A container of item instances _Inventory / entity._Inventory
Space The capacity unit (not weight) Size
Ownership Player / team / gang claim over an entity _Owner
Access Permission to use something you may not own _Owner.access
Permission A named capability held by a character _Access flag string
Group / Gang / Team The three-level job hierarchy same
Need An ambient depleting stat _Hunger, _Stamina
Interaction A timed, cancellable player action timer.Conditional
Module A unit of the framework "plugin"

"Plugin" now means a third-party extension. First-party units are modules. Keeping those distinct avoids the confusion that ADR-0002 resolves.


10. Files and assets

Kind Convention Example
Source file matches the type InventoryService.cs
Test file <TypeUnderTest>Tests.cs InventoryServiceTests.cs
Razor panel PascalCase.razor InventoryPanel.razor
Item asset snake_case.item small_pocket.item
Job asset snake_case.job police_officer.job
Prefab PascalCase.prefab WorldItem.prefab
Documentation NN_SCREAMING_SNAKE.md 06_PERSISTENCE.md

Asset IDs stay snake_case deliberately: it matches the original's item IDs, which keeps the legacy documentation directly usable as a content specification.