The onion cut into vertical slices

Pinch or Ctrl+scroll to zoom; the text is selectable. Source · TheYard

The onion cut into vertical slices: the five rings as bands with references pointing inward, four slices cut through every ring, each a folder in the host and in Application and its adapters and rules at the inner rings' roots, the Shared column beside them, the rules the gate holds, and one bid followed through one slice The onion cut into vertical slices: five rings, one folder name per feature in every ring Read top to bottom for the rings, which point inward as they always did; read a dashed column for one feature, which now lives in one place in each ring and nowhere else. TheYard.Api, the host Features/<Slice>/Module.cs: Register and Map; Program.cs alone at the root; everything shared in Shared/<Concern>/ TheYard.Infrastructure and .Cosmos, the adapters the same ports answered twice, relational and document, in Features/<Slice>/ or Shared/<Concern>/; only the mapped rows stay at the root TheYard.Application, the use cases Features/<Slice>/: one handler per request, one HandleAsync; the auction, the stores and the kept history in Shared/<Concern>/ TheYard.Domain, the rules pure functions and records, in Shared/Auction or the slice that owns the rule; no clock, no disk, no network TheYard.Data, the records zero dependencies, zero behaviour Shared/, the same in every ring Activity, Auth, CostReadings Documentation, Edge, Grades, Hosted Instance, MachineReadings Observability, PlanReadings, Proof Resources, Sites, Stores, Usage, Wire Wiring ContextFactory.cs, CosmosStore.cs OutboundHttp.cs, one pool AzureMetrics.cs, the host's StandingReader.cs, the reads Ports.cs, IStoreDiagnostics CardFrame.cs, CloudWire.cs Fnv1a.cs, AuctionSchedule.cs CardTone.cs, the one tone rule Features/Bids Module.cs BidEndpoints.cs, the wire too EfBidStore.Standing.cs CosmosBidStore.Standing.cs PlaceBidHandler.cs BidReadHandlers.cs IBidStore in Ports.cs BidRules.cs, StandingRules.cs in Shared/Auction Features/Vehicles Module.cs VehicleEndpoints.cs VehicleWire.cs, in Shared/Wire EfVehicleCatalogue.cs CosmosVehicleCatalogue.cs VehicleHandlers.cs IVehicleCatalogue in Ports.cs VehicleFilter.cs and VehicleOrdering.cs Features/Accounts Module.cs AccountEndpoints.cs AccountEndpoints.SignIn.cs Features/Accounts/ IdentityAccountStore.cs CosmosUserStore.cs SessionHandlers.cs ResetHandlers.cs AccountPorts.cs (no rule of its own; the session is Application's) Features/Admin/Cloud Module.cs CloudEndpoints.cs SqlCard.cs and every reader YardModelFacts.cs the readers' requests go out through OutboundHttp ReadCloudCardHandler.cs ICloudCards, beside it CardTone.cs, in Shared/Cards and Admin/Plan, Admin/Operations, Docs, Health, Visitors, each a column like these inward only Held by the gate the ten ring rules a slice depends on its own folders and Shared/ every slice has a Module; Program.cs maps nothing one handler, one HandleAsync, ports by constructor no RequestServices, Environment or Configuration outside Program and *Module sites and stores are lists; no host or store literal in the host only Infrastructure opens a socket no typed resource name, SKU, price or date One request, through one slice POST /api/vehicles/{id}/bids. Nothing on this path reads RequestServices, Environment or configuration; the store was chosen once, in Shared, and handed in. The edge, the host X-Yard-Host, X-Yard-Store The name and the store the request carries. Shared pipeline Shared/RequestPipeline.cs Timing, forwarded headers, problems, the warm store. Bids/Module.Map Features/Bids/Module.cs The one place this route is mapped. BidEndpoints.PlaceBid Features/Bids/BidEndpoints.cs Binds the wire, calls the handler, writes the answer. PlaceBidHandler.HandleAsync Features/Bids/PlaceBidHandler.cs Ports by constructor: the store, the clock. One method. BidRules, then IBidStore Domain/BidRules.cs, EfBidStore The rule decides, pure; the adapter writes, Ef or Cosmos. The slice's tests: BidHandlerTests gives the handler a fake IBidStore and a fixed clock and asserts every outcome BidRules can reach; BidEndpointStatusTests is one integration case per status code. Adding a slice is one folder in the host and one in Application, and one Module; nothing in Program.cs changes. Removing one is deleting those folders; the gate says what else referred to it. Until 1.0.4.0 the host was sliced by kind instead: Endpoints/, Composition/, Cloud/ and ninety files at the root. The rings were held; the slices were not, and a feature was spread across all four folders. Source: docs/images/vertical-slices.svg, drawn by docs/images/vertical-slices.mjs from the Features/ folders, OnionTests.cs and SliceTests.cs. The gate holds every claim on it.