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.dart to 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 a void 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 \n at 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 // Assertions comment

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.