Library
Every public principle, from every expert. A principle runs for you once its expert, or a collection that holds it, is on your advisory board. To find people instead, go to Explore.

Join conditions with && only when they form one question, and give each separate question its own nested if.
Tests must exercise code from lib; never reproduce the implementation or mock the production class under test.
Before creating a new test file or test helper class, check whether an existing one already covers that unit and extend it instead.
Extract a function only when it names a stable domain concept, is reused, hides real complexity or is worth testing on its own.
Give each method of a fake a nullable override function field placed right above it, so a test can change one behavior without a new fake.
Avoid the late keyword, because it turns a compile time check into a runtime LateInitializationError; initialize in the constructor or use a nullable type.
Keep model objects immutable and hold changing state, such as which items are checked, separately, because mutating a field may not trigger setState and leaves the UI stale.
Give a lambda that spans several lines a curly-brace body instead of =>, because it needs less indentation and you can set breakpoints inside it.
Prefer switch, polymorphism, collection functions or early returns over if-else, and keep if-else for two equally weighted branches.
Catch the stack trace together with the error and pass both along, because an error without its stack trace says what failed but not where.
Read the time through clock.now() from package:clock, so tests can control it with fakeAsync or withClock.
Log through package:chirp, or developer.log in a Flutter app without chirp, and never print(), because print loses the error and stack trace.
Parse JSON with package:deep_pick instead of code generation or casting the Map from jsonDecode by hand, because it is type safe, null aware and needs no build_runner.
Transform collections with .map(), .where() and .fold() instead of filling an empty list in a loop, because declarative code is shorter and easier to read.
Inject dependencies instead of reaching for a singleton, so tests can replace them with a fake or a mock.
Keep ternaries on one line; when a condition spans lines, use an immediately invoked function or if-else so each branch stays readable and debuggable.
Inspect local conventions before adding public API, state management, abstractions or configuration.
Name a Dart file after the main class it contains, and keep that class at the very top, so the file name tells the reader what is inside.
Do not use String or List<String> for statuses, roles, categories or options; use an enum, a class with static values or an extension type.
Put a guard clause's return or throw on its own line inside braces, so exits stay visible and can take a breakpoint.
Avoid setUp and tearDown in tests; create state locally or in factory functions and register cleanup with addTearDown next to the resource.
Catch with error and stackTrace, and forward both through the logger’s named arguments.
Back data models that wrap API maps with a Rekord and typed getters parsed lazily through deep_pick, so a missing or broken field only fails when it is read.
Keep reactive state in signals scoped to a controller, preferably state_beacon, instead of ChangeNotifier or ValueNotifier, so derived values cannot go stale.
Use braces and put every control-flow body on a separate line.
Avoid build_runner and code generation in Dart; write the code once instead, and do not suggest freezed unless the project already depends on it.
Name the parameter of a single-parameter lambda it or another name under 7 characters; lambdas with several parameters keep descriptive names.
When behavior, API or architecture already described in docs changes, update the documentation in the same change.
Put the class a file is named after at the very top of the file, above its helper classes, enums and extensions, so readers meet the main type first.
Configure Dart linting with package:lint and never suggest other lint packages such as very_good_analysis or flutter_lints.
Write a private helper that does not touch instance state as a top-level function in the file, not a static member, because library privacy already scopes it.
For async_return_with_no_await, add await and preserve the async method.
Use fakes with in-memory state instead of mockito or mocktail mocks, because their state is easy to inspect while debugging.
Avoid the if-case pattern matching syntax and write a plain type and length check instead, because many developers still find if-case hard to read.
Declare variables final or const unless they are reassigned, so a var signals real reassignment; this does not apply to for-loop headers or function parameters.
Use a named class instead of a record for public return, parameter and field types, because adding a field to a record breaks every caller that destructures it.
Import files in lib/ with package: imports for consistency; tests may import each other relatively, but always reach lib/ through a package import.
Write copyWith as a typed function getter backed by a sentinel default, so callers can set nullable fields back to null without losing type safety.
Export a package's public symbols with explicit show clauses, so the public API is a deliberate list and internals do not leak.
Two feature files must not import each other; move the shared concept into something both depend on, or inline it, so each can be read and deleted alone.
Copy collections into a result object and expose them unmodifiable, and keep the data that explains a failure on the typed reason itself, so callers cannot mutate or misread it.
Organize code by feature and call repositories directly, because UseCase and layer-first folders add indirection and boilerplate without value.
Avoid sealed classes and enums in a package's public API when cases may grow, because each new case breaks every caller's exhaustive switch.
Wrap only the one call you expect to throw FormatException, StateError, TimeoutException and similar generic types, because a wide try cannot tell which statement threw.
Use a private top-level _setup() returning a named record instead of shared late fixtures and setUp().
Write a plain for loop instead of forEach, because forEach allocates an unnecessary lambda; for transformations use map, flatMap or reduce.
Report a failed operation by throwing, not by returning false, so the error and its stack trace reach the caller and cannot be silently ignored.
Avoid mutable global state, because it leaks between tests and makes them depend on each other.
Treat a deleted, commented-out or skipped test as a red flag that needs a reason: fix it, delete it with a tracking issue, or skip it with an issue number.
Keep an enum in the same file as the class that primarily uses it instead of giving it a file of its own.
Keep a constant in the file that uses it, or the one it belongs to most, instead of collecting constants in a globals file; only cross-module constants go to main.dart.
Return Future<T> and let failures throw instead of returning Future<Either<T>>, because a Future can fail anyway and Either only adds complexity and false safety.
Do not use package:bloc or flutter_bloc for state management; streams are hard to test, and a synchronous ChangeNotifier is simpler for most code.
Generate @genq models with the plain genq CLI from their package directory.
Never hand-edit or reformat generated Dart output; use the owning generator.
Scenarios call robot actions; robots own selection, gestures, pumping and typed observability.
Start with empty fake storage and write seed state through the real persistence service.
Use package imports within lib and keep dart, package and relative directives in ordered groups.
Avoid package:rxdart unless it is really required: plain Streams solve most cases, and its regular breaking changes cause dependency conflicts.
Make a function public only when it is a documented internal API; a helper that one other file needs belongs next to that caller as a private function.
Become an expert
Turn the advice you keep giving in code reviews into a principle that runs inside other people's agents. The guide takes you from an idea to a released principle, in the browser or in your editor.