Rules for Example File Creation
Core Principle
CRITICAL: Examples must contain executable code that actually runs, not code printed as strings to the console. Each example should: - Create real objects and call real methods - Capture results in variables - Print the actual runtime results - Assert against the computed values
BAD (printing code as text):
print(' @tomReflector');
print(' @TomComponent(OrderService)');
print(' class OrderServiceImpl implements OrderService {');
GOOD (executing real code):
final service = OrderServiceImpl();
final result = service.createOrder(userId: 1, item: 'Widget');
print(' - Order created: ${result.id}');
assert(result.id.isNotEmpty);
Which packages carry example/
A package with an importable surface — a library, or a server whose most useful seam runs without infrastructure — carries an
example/ directory that imports it. An application package with no importable surface (a Flutter app, a demo harness) does not: there is nothing for an example to import, and the app is itself what a reader runs. Its README says so in one sentence and names what to run instead, so the absence reads as a decision rather than a gap. When the app ships in-app samples — an Examples tab, a demo gallery — that sentence points at them.
File Naming
-
Numbered prefix: Use
NN_prefix for ordering (e.g.,01_,02_,03_) -
Descriptive suffix: Name describes the topic followed by
_example.dart(e.g.,01_timezone_basics_example.dart) -
Runner file: Create
00_run_all_examples.dartto run all examples in sequence
File Structure
Header Documentation
-
Library doc comment: Start with
///doc comment describing what the example demonstrates - Library directive: Include
library;after the doc comment -
Imports: Import the main package (e.g.,
import 'package:tom_core/tom_core.dart';)
Section Comments
- Major sections: Use
// ====...====style for major section headers -
Sub-sections: Use
// ----...----style for individual examples within the file -
Numbered examples: Label each example with a number (e.g.,
// Example 1:,// Example 2:)
Function Structure
-
Single
run()function: Each example file exports avoid run()function -
Example title print: Start with a header print like
print('=== 01: Timezone Basics Example ===\n'); - Print statements: Include print statements showing what's happening and the output
Example Code
Executable Code Requirement
- Execute real code: All examples MUST execute actual code, not print code samples as strings
- Create real instances: Instantiate real objects, call real methods, capture real results
- No code-as-text: Never use print() to display code samples - the code should run and produce output
Deterministic Values
- Avoid DateTime.now(): Use fixed dates for deterministic, reproducible results
- Named variables: Store results in descriptive named variables (not inline in prints)
- Show intermediate values: Capture intermediate results in variables for both printing and assertions
Print Format
-
Numbered output: Print example number and description (e.g.,
print('1. Creating timezones by IANA name:');) -
Indented results: Indent result lines with spaces (e.g.,
print(' - Tokyo: ${tokyo?.timezone}');) - Blank lines: Add
\nat end of each example section for readability
Assertions
Placement
- Group at bottom: All assertions go at the end of the
run()function -
Section header: Precede with comment
// ========================================================================= - Section label: Add
// Assertionscomment
Organization
-
Grouped by example: Add comment for each example's assertions (e.g.,
// Example 1: Timezone creation) - One assert per line: Each assertion on its own line
- Descriptive comments: Add inline comments explaining expected values when helpful
Content
- Verify all key values: Assert all important computed values from the example
- Use named variables: Assert against the named variables captured during the example, not new computations
Runner File (00_run_all_examples.dart)
-
Aliased imports: Import each example file with an alias (e.g.,
import '01_...' as timezone_basics;) - Decorative header/footer: Use box-drawing characters for visual header/footer
- Sequential execution: Call each example's
run()function in order - Run instructions: Include bash command to run in doc comment
File structure
- Static Method for Each Test: Make one "[ExampleGroup]Test" class per example file that groups the example code into static methods for each part of the example
- Static Fields for Variables and Results: Use static variable in the example class for data that flows from one example to the next and the results
- Assertions at the end of each example method: Pleace the assertions at the end of each example method
- Static run() method: add a static run() method the example class (or classes). Call this method from the runner file
Reflectable
- Add Runner File to Reflectable: insert the runner file into the reflectable_builder configuration in build.yaml if example need reflection
- Don't Hesitate Regarding Reflectable: Use reflectable as needed to provide good examples. Example quality has priority. Don't make too simple examples.
Error Handling
- Add try-catch blocks for operations that are supposed to fail: Catch the exceptions and the print the information about the exception.