Code is read far more often than it is written. Clean code makes intent obvious, and a good review checks more than style.
π· Naming
Names say intent and domain: settlementDate, not d2. Booleans read as questions: isOverdrawn.
βοΈ Small functions
One level of abstraction per method. If you need "and" to describe it, split it.
πͺ Guard clauses
Return or throw early. Keep the happy path un-nested at the left margin.
π§ Immutability
record, init, required. C# 14's field keyword lets a property validate without a manual backing field.
β Nullability
Turn on nullable reference types. Treat warnings as errors in new projects.
π¬ Comments explain why
The code says what. Comments say why: a regulation, a workaround, a trade-off.
.NET 10 How to implement it
| Library / API | Package | Use it for |
| Nullable + warnings as errors | built-in <Nullable>, <TreatWarningsAsErrors> | Null safety enforced by the compiler |
| Formatting | built-in dotnet format + .editorconfig | Style checked in CI, not in review comments |
| Typed results | built-in TypedResults, Results<T1, T2> | Each endpoint outcome visible in the signature and OpenAPI |
| ProblemDetails | built-in AddProblemDetails(), IExceptionHandler | One error format; global handler for exceptions |
| Result pattern | ErrorOr or FluentResults | Return success or typed errors without exceptions |
public ErrorOr<Transfer> Create(Account from, decimal amount)
{
if (amount <= 0) return Error.Validation("amount", "Amount must be positive");
if (from.Balance < amount) return Error.Conflict("funds", "Insufficient funds");
return new Transfer(Guid.NewGuid(), from.Id, amount); // happy path last
}
app.MapPost("/transfers", (TransferRequest req, Accounts accounts, TransferService svc) =>
svc.Create(accounts.Get(req.FromId), req.Amount).Match<IResult>(
t => TypedResults.Created($"/transfers/{t.Id}", t),
errors => TypedResults.Problem(errors[0].Description,
statusCode: errors[0].Type == ErrorType.Validation ? 400 : 409)));
My 7-point code review checklist β
π― Correctness: edge cases like empty, zero, duplicates, time zones
π Security: authorisation on every endpoint, no PII in logs
β‘ Performance: no N+1 queries, no sync-over-async
π Readability: names that explain intent, small methods
π§ͺ Tests and π observability: would we know if it broke in prod?
Let formatters and analyzers argue about style, so humans can review design and risk. What's on your list?
#CodeReview #CleanCode #DotNet #SoftwareEngineering