diff --git a/checklist.md b/checklist.md index 9912d1b..6d1e810 100644 --- a/checklist.md +++ b/checklist.md @@ -156,7 +156,7 @@ See: [`docs/02-aspnetcore.md`](./docs/02-aspnetcore.md) §§3, 4, 5, 8. - Keep `MapInboundClaims = false` so `scp` / `roles` / `azp` stay verbatim, and validate `iss`, `aud`, signing key, `exp`, `nbf`; pin tenant where applicable ([learn.microsoft.com/entra/identity-platform/access-token-claims-reference](https://learn.microsoft.com/entra/identity-platform/access-token-claims-reference), [RFC 9068](https://datatracker.ietf.org/doc/html/rfc9068)). - **Two separate named policies** per capability: a delegated policy that requires the `scp` scope (and rejects tokens carrying `roles` without `scp`); an app-only policy that requires `roles` **and** an `azp`/`appid` allow-list **and** the absence of `scp`. - For endpoints that legitimately accept both flows, list both policies on the endpoint (`RequireAuthorization("XDelegated", "XApp")`) so each policy still enforces its own invariants. -- Use `RequiredScope` / policy-based authorization, not ad-hoc claim sniffing in handlers; reference [`mghabin/entra-auth-patterns-dotnet`](https://github.com/mghabin/entra-auth-patterns-dotnet) for the runnable sample. +- Use `RequiredScope` / policy-based authorization, not ad-hoc claim sniffing in handlers. **Don't:** @@ -165,7 +165,7 @@ See: [`docs/02-aspnetcore.md`](./docs/02-aspnetcore.md) §§3, 4, 5, 8. - Accept tokens with `ver=1.0` when you expect `2.0` (or vice versa) without explicit handling. - Disable `ValidateIssuer`, `ValidateAudience`, or `ValidateLifetime`. Ever. -See: [`docs/02-aspnetcore.md#10-authnauthz`](./docs/02-aspnetcore.md#10-authnauthz), decision tree [12 — auth policy shape](./docs/decision-trees.md#12-auth-policy-shape-delegated-scp-vs-app-only-roles--azp). +See: [`docs/02-aspnetcore.md#10-authnauthz`](./docs/02-aspnetcore.md#10-authnauthz) (owner) and decision tree [12 — auth policy shape](./docs/decision-trees.md#12-auth-policy-shape-delegated-scp-vs-app-only-roles--azp). See also (non-normative, runnable sample): [`mghabin/entra-auth-patterns-dotnet`](https://github.com/mghabin/entra-auth-patterns-dotnet). ## 10. Caching diff --git a/coverage-map.md b/coverage-map.md index ee0ea73..952f377 100644 --- a/coverage-map.md +++ b/coverage-map.md @@ -200,7 +200,7 @@ Source: [`docs/06-cloud-native.md`](./docs/06-cloud-native.md). - `ServiceDefaults` shared project (§1): OTel wiring, default health checks, resilience handlers, service discovery defaults. - **Configuration in cluster** (§4): ConfigMap + CSI Key Vault driver as the configuration substrate; `appsettings.Production.json` rejected. Foundations §6 owns the in-process options pattern; this chapter owns where the bytes come from in the cluster. - **Resilience pipeline defaults at the platform layer** (§6): Polly v8 standard-pipeline composition for non-HTTP resources (queues, blobs, repositories) and the rationale for keeping HTTP resilience in [02 §7](#chapter-02--aspnetcore). HTTP retry verb policy is owned by ch02; this chapter does not re-decide it. -- **Health-check probe contract** (§10): `/health/live`, `/health/ready`, `/health/startup` endpoint names, semantics, what each probe may do, and the K8s probe wiring — matches the Aspire `ServiceDefaults` mapping. Chapter 02 §18 only owns the in-process `MapHealthChecks` plumbing and links here for the contract. +- **Health-check probe contract** (§10): `/health/live`, `/health/ready`, `/health/startup` endpoint names, semantics, what each probe may do, and the K8s probe wiring. Aspire `ServiceDefaults` ships **only** `/health` + `/alive` and **only in Development** — production code must explicitly `MapHealthChecks` for `/health/live`, `/health/ready`, `/health/startup` (see [ch06 §10](#chapter-06--cloud-native) and the [aspire.dev ServiceDefaults reference](https://aspire.dev/fundamentals/service-defaults/)). Chapter 02 §18 only owns the in-process `MapHealthChecks` plumbing and links here for the contract. - Kubernetes runtime contract: liveness / readiness / startup probes, QoS class, the CPU-limits-considered-harmful stance, requests sizing. - Service discovery via `Microsoft.Extensions.ServiceDiscovery` and `HttpClient` integration (§7). - **Networking** (§13): HTTP/2 + HTTP/3 enablement, forwarded headers in cluster, mTLS via service mesh, TLS termination boundary. diff --git a/docs/01-foundations.md b/docs/01-foundations.md index cca6a21..d316c42 100644 --- a/docs/01-foundations.md +++ b/docs/01-foundations.md @@ -96,6 +96,8 @@ libs; you will want it the first time prod stack-traces hit a NuGet'd package. - [`ContinuousIntegrationBuild`](https://learn.microsoft.com/dotnet/core/project-sdk/msbuild-props#continuousintegrationbuild) — what the CI flag strips from PDBs. - [reproducible-builds.org — Definition](https://reproducible-builds.org/docs/definition/) — vendor-neutral definition the .NET reproducible-build flags target. - [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) — the contract `Directory.Packages.props` versions are expected to honor. +- [`dotnet/sdk` — repository](https://github.com/dotnet/sdk) — primary source for SDK behaviour, MSBuild SDK targets, and `global.json` semantics. +- [ECMA-334 — C# Language Specification](https://ecma-international.org/publications-and-standards/standards/ecma-334/) — the standardized language spec the C# compiler targets. > **See also**: monorepo layout and CI fan-out live in [`patterns/monorepo.md`](../patterns/monorepo.md), and the test-project conventions assumed by the `tests/` sibling layout are owned by [chapter 04 §1–§2](./04-testing.md#1-the-pyramid-and-why-most-teams-get-it-wrong). @@ -250,6 +252,10 @@ method does. - [Pattern matching](https://learn.microsoft.com/dotnet/csharp/fundamentals/functional/pattern-matching) — switch expressions, property/list patterns. - [`ref readonly` parameters](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/ref#ref-readonly-parameters) — when to use over `in`. - [ECMA-335 — Common Language Infrastructure](https://ecma-international.org/publications-and-standards/standards/ecma-335/) — the standardized runtime/IL spec the language targets (vendor-neutral baseline behind the C# spec). +- [`dotnet/csharplang` — language design notes](https://github.com/dotnet/csharplang) — primary source for C# 13/14 design discussions, LDM notes, and proposal status (the spec ships from here). +- [`dotnet/csharplang` — C# 14 proposals](https://github.com/dotnet/csharplang/tree/main/proposals/csharp-14.0) — `field` keyword, extension members, partial constructors, first-class Span conversions: where the design is recorded. +- [`dotnet/csharplang` — C# 13 proposals](https://github.com/dotnet/csharplang/tree/main/proposals/csharp-13.0) — `params` collections, `ref readonly`, `Lock` type, `OverloadResolutionPriority`. +- [`dotnet/roslyn` — repository](https://github.com/dotnet/roslyn) — the C# compiler; primary source for analyzer/source-generator authoring and language-feature implementation status. --- @@ -302,6 +308,8 @@ amnesty. - [`ArgumentNullException.ThrowIfNull`](https://learn.microsoft.com/dotnet/api/system.argumentnullexception.throwifnull) — annotated guard; feeds flow analysis. - [`StringSyntaxAttribute`](https://learn.microsoft.com/dotnet/api/system.diagnostics.codeanalysis.stringsyntaxattribute) — string-literal hints for analyzers/IDEs. - [Andrew Lock — *Embracing nullable reference types*](https://andrewlock.net/series/embracing-nullable-reference-types/) — community-canonical migration playbook for incremental NRT adoption on existing codebases. +- [`dotnet/csharplang` — Nullable reference types specification](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-8.0/nullable-reference-types-specification.md) — primary spec for NRT flow analysis, suppressions, and attribute semantics. +- [Mads Torgersen — *Embracing nullable reference types* (devblogs)](https://devblogs.microsoft.com/dotnet/embracing-nullable-reference-types/) — language-team announcement and rationale. --- @@ -390,6 +398,8 @@ singleton — the captured state is the lifetime of the singleton. - [Stephen Cleary — *Async and Await*](https://blog.stephencleary.com/2012/02/async-and-await.html) — canonical primer; `async void` exception flow. - [Stephen Cleary — *Don't Block on Async Code*](https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html) — sync-over-async deadlock anatomy. - [David Fowler — *AspNetCoreDiagnosticScenarios — AsyncGuidance*](https://github.com/davidfowl/AspNetCoreDiagnosticScenarios/blob/main/AsyncGuidance.md) — community-maintained field guide to async + DI gotchas; cross-linked from `Further reading`. +- [Stephen Toub — *Async/await internals* (devblogs)](https://devblogs.microsoft.com/dotnet/how-async-await-really-works/) — primary-source walk-through of the state machine, `IValueTaskSource`, and async-method-builder lowering. +- [`dotnet/runtime` — Threading & Tasks design docs](https://github.com/dotnet/runtime/tree/main/docs/design/features) — primary source for `Task`, `ValueTask`, and synchronization-context internals. --- @@ -466,6 +476,7 @@ The cluster-level resilience story (Aspire `ServiceDefaults` wiring of the same - [`IHttpClientFactory`](https://learn.microsoft.com/dotnet/core/extensions/httpclient-factory) — named/typed clients, handler pooling. - [`Microsoft.Extensions.Http.Resilience`](https://learn.microsoft.com/dotnet/core/resilience/http-resilience) — Polly v8 standard handlers. - [Steve Gordon — *HttpClientFactory in ASP.NET Core* (series)](https://www.stevejgordon.co.uk/introduction-to-httpclientfactory-aspnetcore) — community-canonical internals walkthrough: handler pooling, lifetimes, the `LogicalHandler`/`PrimaryHandler` chain. +- [`dotnet/runtime` — `Microsoft.Extensions.DependencyInjection` source](https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.DependencyInjection) — primary source for DI lifetime semantics, scope validation, and keyed services. --- @@ -518,6 +529,7 @@ smell that defeats validation, defeats reload, and defeats testability. - [Configuration providers & precedence](https://learn.microsoft.com/dotnet/core/extensions/configuration) — layering rules. - [Safe storage of secrets in development](https://learn.microsoft.com/aspnet/core/security/app-secrets) — `dotnet user-secrets`. - [Andrew Lock — *Adding validation to strongly-typed configuration objects*](https://andrewlock.net/adding-validation-to-strongly-typed-configuration-objects-in-asp-net-core/) — community-canonical walk-through of `IValidateOptions`, `[OptionsValidator]`, and `ValidateOnStart` patterns. +- [`[OptionsValidator]` source generator — devblogs](https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-rc1/#optionsvalidator-source-generator) — the .NET team announcement and rationale for compile-time options validation. --- @@ -550,6 +562,7 @@ always `using`. - [Implement `IDisposable` / dispose pattern](https://learn.microsoft.com/dotnet/standard/garbage-collection/implementing-dispose) — when finalizers, when not. - [Implement `IAsyncDisposable`](https://learn.microsoft.com/dotnet/standard/garbage-collection/implementing-disposeasync) — `await using` rules. - [`CancellationTokenSource`](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtokensource) — disposal of linked sources. +- [Stephen Toub — *DisposeAsync* notes (devblogs)](https://devblogs.microsoft.com/dotnet/configureawait-faq/#what-about-asynchronous-disposal) — async disposal semantics and `await using` rules from the libraries lead. --- @@ -599,6 +612,8 @@ catch it specifically, it shouldn't exist as its own type — a built-in - [Best practices for exceptions](https://learn.microsoft.com/dotnet/standard/exceptions/best-practices-for-exceptions) — design rules. - [`ExceptionDispatchInfo`](https://learn.microsoft.com/dotnet/api/system.runtime.exceptionservices.exceptiondispatchinfo) — preserving stacks across boundaries. - [`ProblemDetails` (RFC 9457)](https://datatracker.ietf.org/doc/html/rfc9457) — current standard error envelope for HTTP APIs; obsoletes RFC 7807. +- [RFC 9110 — HTTP Semantics](https://datatracker.ietf.org/doc/html/rfc9110) — primary source for status-code semantics that shape the exception → ProblemDetails mapping. +- [`dotnet/runtime` — Exception design notes](https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/exceptions.md) — primary-source CLR exception model behind the BCL guidance. --- @@ -654,6 +669,8 @@ This is the canonical C# 14 replacement for the `private string _name; public st - [`System.Collections.Immutable`](https://learn.microsoft.com/dotnet/api/system.collections.immutable) — `ImmutableArray`, `ImmutableList`. - [Choosing between class and struct](https://learn.microsoft.com/dotnet/standard/design-guidelines/choosing-between-class-and-struct) — when value semantics fit. - [Eric Lippert — *Immutability in C#* (series)](https://learn.microsoft.com/archive/blogs/ericlippert/immutability-in-c-part-one-kinds-of-immutability) — taxonomy of write-once / shallow / deep / observational immutability; shapes the rule that `IReadOnlyList` is a view, not a guarantee. +- [`dotnet/csharplang` — Records proposal](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-9.0/records.md) — primary-source design notes for `record` value-equality semantics referenced throughout this section. +- [Mads Torgersen — *C# 9 Records* (devblogs)](https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/) — language-team announcement of records and `init` accessors. --- @@ -705,6 +722,8 @@ runs in the IDE — every dep becomes a load-order hazard). - [`System.Text.Json` source generation](https://learn.microsoft.com/dotnet/standard/serialization/system-text-json/source-generation) — AOT, perf, startup. - [`GeneratedRegex`](https://learn.microsoft.com/dotnet/standard/base-types/regular-expression-source-generators) — compile-time regex. - [Roslyn interceptors feature doc](https://github.com/dotnet/roslyn/blob/main/docs/features/interceptors.md) — current status, encoding, generator-only guidance. +- [`dotnet/runtime` — `LoggerMessage` source generator](https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen) — primary-source generator implementation behind the high-perf logging guidance. +- [Source generators cookbook (`dotnet/roslyn`)](https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.cookbook.md) — primary-source authoring guide. - [Source generators overview](https://learn.microsoft.com/dotnet/csharp/roslyn-sdk/source-generators-overview) — authoring guidance. --- @@ -758,7 +777,7 @@ server (or NuGet.org's). **`dotnet test` and Microsoft.Testing.Platform.** The .NET 10 SDK ships first-class Microsoft.Testing.Platform (MTP) support in `dotnet test` alongside the legacy VSTest pipeline. -The runner choice, opt-in, and CI integration rules are owned by [chapter 04 §2 Frameworks: xUnit v3, MSTest, NUnit](./04-testing.md#2-frameworks-xunit-v3-mstest-nunit); just don't bake VSTest-only assumptions into CI templates you author today. +The runner choice, opt-in, and CI integration rules are owned by [chapter 04 §2 Frameworks: xUnit v3, MSTest, NUnit](./04-testing.md#2-frameworks-xunit-v3-mstest-nunit-tunit); just don't bake VSTest-only assumptions into CI templates you author today. **Sources:** @@ -770,6 +789,7 @@ The runner choice, opt-in, and CI integration rules are owned by [chapter 04 §2 - [.NET 10 SDK — what's new](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-10/sdk) — `dotnet test` and Microsoft.Testing.Platform. - [OWASP — Software Component Verification Standard (SCVS)](https://owasp.org/www-project-software-component-verification-standard/) — vendor-neutral baseline that `NuGetAudit` + lock-file restore are meant to satisfy. - [NIST SP 800-218 — Secure Software Development Framework (SSDF)](https://csrc.nist.gov/publications/detail/sp/800-218/final) — primary-source reference for the supply-chain controls (PW.4, PS.3) the build pipeline implements. +- [Sigstore project](https://www.sigstore.dev/) — primary-source supply-chain signing infrastructure (`cosign`, transparency log) referenced from the CI baseline. --- @@ -860,6 +880,8 @@ next to the csproj; do not let ops set GC policy in the deploy pipeline. - [CET — Control-flow Enforcement Technology (.NET 9)](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-9/runtime#control-flow-enforcement-technology) — default-on shadow stack on Windows. - [Tiered compilation](https://learn.microsoft.com/dotnet/core/runtime-config/compilation) — how tiers and quick-JIT interact. - [Performance improvements in .NET 10 — Stephen Toub](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-10/) — current canonical perf post; supersedes the .NET 8 link for Dynamic PGO. +- [`dotnet/runtime` — GC documentation](https://github.com/dotnet/runtime/tree/main/docs/design/coreclr/botr) — primary-source GC design notes (Server vs Workstation, DATAS, write barriers). +- [`dotnet/runtime` — Tiered compilation / Dynamic PGO design](https://github.com/dotnet/runtime/blob/main/docs/design/features/TieredCompilation.md) — primary source for tier-0/tier-1 behaviour referenced in this section. - [PGO improvements: type checks and casts (.NET 9)](https://learn.microsoft.com/dotnet/core/whats-new/dotnet-9/runtime#pgo-improvements-type-checks-and-casts) — what Dynamic PGO learned in .NET 9. - [Thread-pool runtime config](https://learn.microsoft.com/dotnet/core/runtime-config/threading) — `MinThreads`, hill-climbing semantics. - [`RuntimeHostConfigurationOption` MSBuild item](https://learn.microsoft.com/dotnet/core/runtime-config/#specify-a-configuration-value) — how project switches reach `runtimeconfig.json`. diff --git a/docs/02-aspnetcore.md b/docs/02-aspnetcore.md index b3718a8..5356eb0 100644 --- a/docs/02-aspnetcore.md +++ b/docs/02-aspnetcore.md @@ -934,7 +934,6 @@ Sources: - [Andrew Lock — andrewlock.net](https://andrewlock.net/) — deep, careful dives on middleware, auth, configuration, source generators. The reference blog for ASP.NET Core internals. - [David Fowler — gists and talks](https://gist.github.com/davidfowl) — especially [davidfowl/AspNetCoreDiagnosticScenarios](https://github.com/davidfowl/AspNetCoreDiagnosticScenarios): async/await, `HttpClient`, and threading traps straight from the architect. - [Khalid Abuhakmeh — khalidabuhakmeh.com](https://khalidabuhakmeh.com/) — pragmatic tips, Minimal APIs, tooling. -- [Nick Chapsas — YouTube](https://www.youtube.com/@nickchapsas) — current .NET features explained quickly; good for "what changed in the latest preview". - [Steve Gordon — stevejgordon.co.uk](https://www.stevejgordon.co.uk/) and NDC talks — `HttpClientFactory` internals, performance, diagnostics. - [Jimmy Bogard — jimmybogard.com](https://www.jimmybogard.com/) — domain modeling, MediatR, vertical slice architecture, ProblemDetails patterns. - [Gérald Barré (Meziantou) — meziantou.net](https://www.meziantou.net/) — edge cases, analyzers, source generators, niche perf. diff --git a/docs/03-data.md b/docs/03-data.md index 374babf..134cf0a 100644 --- a/docs/03-data.md +++ b/docs/03-data.md @@ -671,7 +671,7 @@ Sources: - Andrew Lock — https://andrewlock.net/ (config, startup, DbContext lifetime, HybridCache) - Jimmy Bogard — https://www.jimmybogard.com/ (outbox, CQRS, repository critique) - Khalid Abuhakmeh — https://khalidabuhakmeh.com/ (EF + Dapper interop) -- Nick Chapsas — https://nickchapsas.com/ and YouTube (perf, Dapper vs EF benchmarks) +- Nick Chapsas — https://nickchapsas.com/ (perf, Dapper vs EF benchmarks) - Meziantou — https://www.meziantou.net/ (async, Data Protection, column encryption) - Steve Gordon — https://www.stevejgordon.co.uk/ (async, caching, HybridCache internals) - David Fowler — gists on `TransactionScope`, async pitfalls — https://gist.github.com/davidfowl diff --git a/docs/04-testing.md b/docs/04-testing.md index 79214fa..b233608 100644 --- a/docs/04-testing.md +++ b/docs/04-testing.md @@ -804,7 +804,6 @@ Sources: ### Community - Khalid Abuhakmeh — testing & ASP.NET Core posts — https://khalidabuhakmeh.com/ - Andrew Lock — *.NET Escapades* (integration tests, WebApplicationFactory, Testcontainers) — https://andrewlock.net/ -- Nick Chapsas — YouTube deep-dives on xUnit v3, NSubstitute, Verify — https://www.youtube.com/@nickchapsas - Jimmy Bogard — *Los Techies* / blog (integration testing, Respawn author) — https://www.jimmybogard.com/ - Steve Smith (Ardalis) — testing & clean architecture — https://ardalis.com/ - Bradley Wells — xUnit v3 / MTP migration guides — https://bradwells.com/ (and https://wellsb.com) diff --git a/docs/05-performance.md b/docs/05-performance.md index 07500af..d3d3977 100644 --- a/docs/05-performance.md +++ b/docs/05-performance.md @@ -277,7 +277,8 @@ Reflection is allocation, slow startup, and AOT-hostile. Most reasons to use it **Sources:** - Konrad Kokosa, *Pro .NET Memory Management* (Apress, 2018, ISBN 978-1-4842-4026-7) — https://prodotnetmemory.com/ — the definitive book on the runtime memory model, GC heap layout, and pause-time analysis. -- Maoni Stephens (.NET GC architect) on GC internals — https://maoni0.medium.com/ +- Maoni Stephens (.NET GC architect) on GC internals — https://devblogs.microsoft.com/dotnet/author/maoni/ +- dotnet/runtime — GC design docs — https://github.com/dotnet/runtime/tree/main/docs/design/coreclr/botr (see `garbage-collection.md`). - Stephen Toub, "Performance Improvements in .NET 9" (DATAS explainer) — https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-9/ - GC fundamentals: https://learn.microsoft.com/dotnet/standard/garbage-collection/fundamentals - Workstation vs Server GC (defaults, single-CPU rule): https://learn.microsoft.com/dotnet/standard/garbage-collection/workstation-server-gc @@ -407,7 +408,7 @@ ENV DOTNET_GCHeapHardLimitPercent=75 **Sources:** - `LoggerMessage` source generator: https://learn.microsoft.com/dotnet/core/extensions/logger-message-generator - High-performance logging: https://learn.microsoft.com/dotnet/core/extensions/high-performance-logging -- Logging primitives, `ILogger`, and source-generated loggers as the language baseline → [Chapter 01 — foundations](./01-foundations.md#chapter-01--foundations). +- Logging primitives, `ILogger`, and source-generated loggers as the language baseline → [Chapter 01 — foundations §10 Source generators](./01-foundations.md#10-source-generators) (chapter-level ownership in [`coverage-map.md`](../coverage-map.md#chapter-01--foundations)). --- @@ -544,16 +545,20 @@ BDN measures *steady-state*. Startup wins from R2R, NativeAOT, and source genera - **Diagnostic CLI tools** (`dotnet-counters`, `dotnet-trace`, `dotnet-dump`, `dotnet-gcdump`). https://learn.microsoft.com/dotnet/core/diagnostics/ - **PerfView**. https://github.com/microsoft/perfview -### Community / people to follow +--- + +## Further reading (non-normative) + +The list below is community/practitioner pointers, not part of the canonical `Sources:` block above. Use them for depth, war stories, and benchmarks; rules in the chapter body still come from the authoritative sources. + - **Stephen Toub** (.NET libraries lead) — devblogs posts above; the source of truth. - **Adam Sitnik** (BenchmarkDotNet maintainer, .NET perf team) — https://adamsitnik.com/ — pooling, BDN, micro-opt patterns. - **Andrey Akinshin** (BenchmarkDotNet lead maintainer) — https://aakinshin.net/ — author of *Pro .NET Benchmarking: The Art of Performance Measurement* (Apress, 2019, ISBN 978-1-4842-4940-6); the reference on BDN methodology, statistical analysis, and benchmark pitfalls. - **Ben Adams** (Illyriad Games / .NET community) — https://github.com/benaadams — real-world high-throughput .NET service perf, Kestrel/ASP.NET Core internals, allocation hunting. -- **Maoni Stephens** (.NET GC architect) — https://maoni0.medium.com/ — anything about GC internals. +- **Maoni Stephens** (.NET GC architect) — https://devblogs.microsoft.com/dotnet/author/maoni/ — anything about GC internals. - **Stephen Cleary** — https://blog.stephencleary.com/ — async / `Task` semantics, `ValueTask`, threading. Author of *Concurrency in C# Cookbook*. - **Andrew Lock** — https://andrewlock.net/ — ASP.NET Core internals, source generators, deployment. - **David Fowler** (.NET architect) — Twitter/X and dotnet/aspnetcore — Pipelines, channels, ASP.NET Core perf patterns. -- **Nick Chapsas** — YouTube *KeepCoding* — accessible perf walkthroughs and BenchmarkDotNet demos. - **Konrad Kokosa — *Pro .NET Memory Management*** (Apress, 2018, still the definitive book on the runtime memory model and GC). Companion site: https://prodotnetmemory.com/ - **Sasha Goldshtein**, **Ben Watson — *Writing High-Performance .NET Code*** (2nd ed.) — practical perf engineering reference. - **Marc Gravell** — protobuf-net, Pipelines, Dapper perf. diff --git a/docs/decision-trees.md b/docs/decision-trees.md index 61a108d..67bd29a 100644 --- a/docs/decision-trees.md +++ b/docs/decision-trees.md @@ -332,19 +332,20 @@ References: [`docs/02-aspnetcore.md#10-authnauthz`](./02-aspnetcore.md#10-authna - Cost of wrong call: caching whole HTTP responses when you needed a domain object; rolling your own L1+L2 with stampede protection that HybridCache ships out of the box. -- Default per `ch03`: `OutputCache` for HTTP responses; `HybridCache` for - app-data with L1+L2 and stampede protection; `IDistributedCache` only as - a plain distributed K/V. +- Owner split: **`OutputCache` is owned by [`ch02 §9`](./02-aspnetcore.md#9-output-caching)** + (HTTP-response middleware). **`HybridCache` and `IDistributedCache` are + owned by [`ch03 §14`](./03-data.md#14-caching)** (data-shaped caches — + the matrix in ch03 §14 is for app data, not HTTP responses). ```mermaid flowchart TD A[Need a cache] --> B{What is being cached?} - B -->|Whole HTTP response
by route + vary| C[OutputCache — ch03] - B -->|Domain object / query result
multi-instance app| D[HybridCache
L1 in-proc + L2 distributed
+ stampede protection — ch03] - B -->|Plain distributed K/V
session, idempotency keys| E[IDistributedCache — ch03] + B -->|Whole HTTP response
by route + vary| C[OutputCache — ch02 §9] + B -->|Domain object / query result
multi-instance app| D[HybridCache
L1 in-proc + L2 distributed
+ stampede protection — ch03 §14] + B -->|Plain distributed K/V
session, idempotency keys| E[IDistributedCache — ch03 §14] ``` -References: [`docs/03-data.md#14-caching`](./03-data.md#14-caching), [`docs/02-aspnetcore.md#9-output-caching`](./02-aspnetcore.md#9-output-caching). +References: [`docs/02-aspnetcore.md#9-output-caching`](./02-aspnetcore.md#9-output-caching) (OutputCache owner), [`docs/03-data.md#14-caching`](./03-data.md#14-caching) (HybridCache / `IDistributedCache` owner). --- diff --git a/patterns/patterns.md b/patterns/patterns.md index b0e87cc..e889f7f 100644 --- a/patterns/patterns.md +++ b/patterns/patterns.md @@ -77,32 +77,7 @@ Decision-bearing prose lives in the chapters; this page only points there. - **Graceful shutdown** — Set `HostOptions.ShutdownTimeout` larger than the longest in-flight request; drain on `ApplicationStopping`, not on `StopAsync`. See [docs/06-cloud-native.md §11 Graceful shutdown](../docs/06-cloud-native.md#11-graceful-shutdown--drain-dont-drop). - **Telemetry-by-construction** — Every cross-boundary type takes `ILogger`, owns an `ActivitySource`, emits a `Meter`; bake it in, do not retrofit after incidents. - See [docs/06-cloud-native.md §5 Observability](../docs/06-cloud-native.md#5-observability--opentelemetry-one-sdk-three-signals). - ---- - -## Cross-cutting (no single chapter owner) - -These do not map cleanly onto one chapter and stay here. - -### Vertical slice vs Clean Architecture - -- **Vertical slice** ([Jimmy Bogard](https://www.jimmybogard.com/vertical-slice-architecture/)): organise by feature folder; each slice owns its request, handler, validator, DTO. Best where features evolve independently. -- **Clean Architecture** ([Steve Smith template](https://github.com/ardalis/CleanArchitecture)): organise by layer (Domain / Application / Infrastructure / Web). Best for stable, complex domains with cross-cutting policies. -- Hybrid is fine: Clean at the assembly level, vertical-slice within `Application`. Pick a *primary* axis. -- **Don't** mix the two axes at the same level — it produces a folder tree nobody can navigate. - -### Bounded contexts & monorepo strategy - -- One bounded context per deployable; one solution per bounded context inside the monorepo. -- Cross-context calls go over the wire (HTTP / messaging) — never via a shared `Domain` project. -- See [`monorepo.md`](./monorepo.md) for the repository layout rules. - -### Domain events vs integration events - -- Domain events fire inside the aggregate boundary and dispatch in-process after `SaveChanges` (see [docs/03-data.md §6](../docs/03-data.md#6-transactions--unit-of-work)). -- Integration events leave the process via the outbox. -- **Don't** conflate the two — the failure modes differ and one becomes the other only by crossing the outbox. + See [docs/06-cloud-native.md §5 Observability](../docs/06-cloud-native.md#5-observability-opentelemetry-one-sdk-three-signals). ---