# Coding and Commenting Style

The rules this codebase is written to. The architecture page says which
way the dependencies point; this one says what the code looks like once it
is there. Both exist because the README promised them at the start of the
build, and because a rule that lives only in someone's head cannot be
reviewed against.

The mechanical half of this page is enforced by
[`.editorconfig`](https://github.com/SteveStout/TheYard/blob/main/.editorconfig)
and the compiler settings, not by review: indentation, line endings, using
order, `var` usage, unused locals and parameters. Review is for the half a
tool cannot check.

## In plain words

This page sets the rules the code here is written to, from naming to where each piece may live. A comment explains why the code is written as it is, because the code already shows what it does. A settings file the editor and compiler read (.editorconfig) checks the mechanical rules.

What that is worth: a developer can predict what a file is called and where it goes before opening it, and the organization gets code a reviewer can check against written rules instead of rules that live in someone's head.

## Naming

- C#: `PascalCase` for types, methods and properties, `camelCase` for
  locals and parameters, `_camelCase` for private fields. Interfaces that
  are ports read as the thing they provide (`IVehicleSource`), not as the
  implementation.
- TypeScript: `camelCase` for values and functions, `PascalCase` for types
  and components, `SCREAMING_SNAKE` for module constants
  (`FILTER_DEBOUNCE_MS`, `EMPTY_FILTERS`).
- The wire is snake_case end to end because the dataset is
  (`body_style`, `min_next_bid`). Nothing is renamed in transit.
- A test name is a sentence: `Increments_are_tiered`,
  `Live_auction_accepts_a_bid_at_the_minimum_and_rejects_below_it`. A
  failing run should read like a report.
- Files are named for what they hold, one main type each: `BidRules.cs`,
  `VehicleCard.tsx`, `VehicleCard.module.css` beside it.

## Layering

- Dependencies point inward. `TheYard.Data` references nothing;
  `TheYard.Domain` may reference Data; Application talks to
  Infrastructure only through ports. If a file needs a `using` that points
  outward, the code is in the wrong project, and `OnionTests` fails the
  gate (ADR: Onion and SOLID, how this codebase holds them).
- Domain code is pure: no `DateTime.Now`, no filesystem, no HTTP. Time
  arrives as an `AuctionClock` the caller built, which is why the tests
  can anchor it.
- The host binds and delegates. A handler in `api/TheYard.Api/Endpoints/`
  reads the request and asks Application for the answer; a rule in a
  handler or in `Composition/` is a bug in layering.
- The browser holds no business rules. If a calculation decides money or
  eligibility, it belongs in Domain and travels on the wire.
- `src/lib` is plain TypeScript with no React import; `src/hooks` is React
  state more than one component needs; `src/components` render.

## Comments

The rule is **what, how and why, with no history**. A comment says what the
code does where the name cannot, how where the way is not obvious, and why
this way or what breaks otherwise; it never leans on a date, a version or a
review to stand in for the reason, and a test holds that (ADR: The rules a
change has to pass).

```csharp
/// <summary>
/// Places one bid for one buyer. The rules run against the vehicle as
/// everybody's bids leave it, under the gate, and an accepted bid is
/// written to the store before it is recorded in memory.
/// </summary>
public async Task<BidOutcome> PlaceBidAsync(Vehicle vehicle, int amount, AuctionClock clock, string userId)
{
    await LoadAsync();
    await _gate.WaitAsync();
    try
    {
        var merged = Apply(vehicle);
        // Sold is read under the same gate as the write that makes it true,
        // so two buyers cannot both find it false.
        var outcome = BidRules.ResolveBid(merged, amount, clock, IsSold(vehicle.Id));
        if (outcome.Kind != BidOutcomeKind.Rejected)
        {
            var state = new BidState(
                outcome.Amount,
                merged.BidCount + 1,
                WonBuyNow: outcome.Kind == BidOutcomeKind.Won,
                AtMs: clock.NowMs);
            // The store first, then memory. The other order looks harmless
            // and is not: a store that throws would leave the dictionaries
            // holding a bid the caller was just told had failed, shown as
            // winning until the next restart deleted it. This way a failed
            // write means the bid did not happen anywhere, which is the
            // answer the caller already has.
            await _store.SaveAsync(userId, vehicle.Id, state);
            Record(userId, vehicle.Id, state);
        }
        return outcome;
    }
    finally
    {
        _gate.Release();
    }
}
```
*Live from [`api/TheYard.Application/BidService.Bidding.cs`](https://github.com/SteveStout/TheYard/blob/1d6b50b/api/TheYard.Application/BidService.Bidding.cs#L14-L51), region `place`, read from this build at 1d6b50b.*

The comment above the store write in that method is worth keeping: the two
lines could be swapped without a compiler noticing, and the reason they
cannot is a failure that would reach a visitor. A comment reading
`// save the bid` would not be. The method is read from this build, so the
page shows the comment as it stands today and not as it was pasted once.

Four more habits:

- A public C# member gets a `<summary>` when its name cannot carry the
  whole contract. `IVehicleSource.LoadAsync()` needs none; `LiveSamples.Expand`
  needs several lines.
- A file that implements a decision names the record: `(ADR-015)`,
  `(ADR: The palette)`. That is how a reader gets from a line to the
  reasoning behind it.
- A comment that explains a workaround says what would happen without it,
  because that is the part that decides whether it can be removed later.
- Code shown in a served record is documented by that record, and carries
  teaching comments for a reader meeting the pattern for the first time
  (ADR: Docs and testing). Code no record shows keeps its own comments.

## Quoting the owner

Records open with the instruction that produced them, in Steve's words, so a
reader can see what was asked before reading what was built. Those words were
typed fast, often from a phone, and they are quoted the way a newspaper quotes
speech: spelling, casing and punctuation regularized for print, product names
written in full, the meaning and the phrasing his. Never `[sic]`, never a typo
kept for authenticity, and never the back-and-forth around the instruction;
the record carries the ask and what it decided, not the exchange. A record
that names a correction he made frames it as the rule it produced.

## Tests

- The suite is chosen by what the code depends on: pure rules get xunit
  unit tests, anything needing the host gets an integration test through
  `WebApplicationFactory`, anything needing a browser gets Playwright.
- A test builds what it needs with the builders in `TestData`, overriding
  only the fields it cares about.
- Time is anchored, never `Now`. Shared state is reset in `beforeEach` or
  isolated in its own fixture class.
- Browser tests locate by role and accessible name, which keeps the suite
  honest about accessibility.
- ADR: The tests, explained walks all three suites for a newcomer.

## Formatting

- Four spaces in C#, two in TypeScript, CSS and JSON. UTF-8 everywhere;
  the files that carry a byte-order mark or CRLF keep them, because
  rewriting a file's encoding is a diff nobody asked for.
- Lines wrap around 120 characters in C# and 100 in TypeScript. Prose in
  the documents wraps at 100 (`max_line_length = 100` for Markdown in
  `.editorconfig`) so a diff of a paragraph is readable.
- One statement per line; no single-line `if` bodies without braces.
- Prose in this repository, including these documents and every commit
  message, uses no em dashes. That is the house voice, not a style
  preference, and the ship gate counts them.

## Files

- [`.editorconfig`](https://github.com/SteveStout/TheYard/blob/main/.editorconfig): the mechanical rules, applied by the editor and the compiler.
- [`docs/app-architecture/ARCHITECTURE.md`](https://github.com/SteveStout/TheYard/blob/main/docs/app-architecture/ARCHITECTURE.md): the layers these rules protect.
- [`api/TheYard.Api/TheYard.Api.csproj`](https://github.com/SteveStout/TheYard/blob/main/api/TheYard.Api/TheYard.Api.csproj): nullable reference types and implicit usings on.
- [`tsconfig.app.json`](https://github.com/SteveStout/TheYard/blob/main/tsconfig.app.json): `strict`, `noUnusedLocals`, `noUnusedParameters`, explained option by option in ADR: The React configuration, explained.
- [`docs/decisions/ADR-006-docs-and-testing.md`](https://github.com/SteveStout/TheYard/blob/main/docs/decisions/ADR-006-docs-and-testing.md): the documenting rule the comment section points at.
- [`docs/decisions/ADR-017-staff-review.md`](https://github.com/SteveStout/TheYard/blob/main/docs/decisions/ADR-017-staff-review.md): the review pass these rules are reviewed against.
