Files
storybook/docs/advanced/23-best-practices.md
Sienna Meridian Satterwhite 16deb5d237 release: Storybook v0.2.0 - Major syntax and features update
BREAKING CHANGES:
- Relationship syntax now requires blocks for all participants
- Removed self/other perspective blocks from relationships
- Replaced 'guard' keyword with 'if' for behavior tree decorators

Language Features:
- Add tree-sitter grammar with improved if/condition disambiguation
- Add comprehensive tutorial and reference documentation
- Add SBIR v0.2.0 binary format specification
- Add resource linking system for behaviors and schedules
- Add year-long schedule patterns (day, season, recurrence)
- Add behavior tree enhancements (named nodes, decorators)

Documentation:
- Complete tutorial series (9 chapters) with baker family examples
- Complete reference documentation for all language features
- SBIR v0.2.0 specification with binary format details
- Added locations and institutions documentation

Examples:
- Convert all examples to baker family scenario
- Add comprehensive working examples

Tooling:
- Zed extension with LSP integration
- Tree-sitter grammar for syntax highlighting
- Build scripts and development tools

Version Updates:
- Main package: 0.1.0 → 0.2.0
- Tree-sitter grammar: 0.1.0 → 0.2.0
- Zed extension: 0.1.0 → 0.2.0
- Storybook editor: 0.1.0 → 0.2.0
2026-02-13 21:52:03 +00:00

345 lines
7.6 KiB
Markdown

# Best Practices
This chapter compiles best practices for writing clear, maintainable, and effective Storybook code. These guidelines apply across all declaration types and project sizes.
## Naming Conventions
### Declarations
Use **PascalCase** for all declaration names:
```storybook
character MasterBaker { } // Good
species DomesticCat { } // Good
behavior GuardPatrol { } // Good
character master_baker { } // Avoid
behavior guard-patrol { } // Invalid (no hyphens)
```
### Fields
Use **snake_case** for field names:
```storybook
character Martha {
skill_level: 0.95 // Good
emotional_state: focused // Good
years_experience: 22 // Good
skillLevel: 0.95 // Avoid (camelCase)
}
```
### Behavior Tree Labels
Use **snake_case** for node labels, with descriptive names:
```storybook
choose survival_instinct { // Good
then fight_response { } // Good
then flight_response { } // Good
}
choose s1 { // Avoid (meaningless)
then a { } // Avoid
}
```
### Enum Variants
Use **PascalCase** or **snake_case** consistently within an enum:
```storybook
// PascalCase (good for short names)
enum Size { Tiny, Small, Normal, Large, Huge }
// snake_case (good for compound names)
enum GovernmentStyle {
absolute_tyranny,
constitutional_monarchy,
direct_democracy
}
```
## File Organization
### Separate Schema from World
Keep reusable type definitions separate from instance data:
```
project/
schema/ # Reusable across stories
core_enums.sb # Enum definitions
templates.sb # Template definitions
beings.sb # Species definitions
world/ # Specific to this story
characters/ # Character instances
behaviors/ # Behavior trees
relationships/ # Relationship instances
locations/ # Location instances
```
### One Concern per File
Group related declarations, but avoid putting unrelated things together:
```storybook
// characters/bakery_staff.sb - Good: related characters together
character Martha { }
character Jane { }
character Elena { }
// everything.sb - Avoid: everything in one file
character Martha { }
behavior BakeRoutine { }
schedule DailyRoutine { }
relationship Partnership { }
```
### Explicit Imports
Prefer explicit imports over wildcards:
```storybook
// Good: clear what is being used
use schema::core_enums::{SkillLevel, Specialty};
use schema::beings::Human;
// Avoid: unclear dependencies
use schema::core_enums::*;
use schema::beings::*;
```
## Character Design
### Use Species for Identity, Templates for Traits
```storybook
// Species: ontological identity
species Human { lifespan: 70 }
// Templates: compositional traits
template Warrior { strength: 10..20 }
template Scholar { intelligence: 15..20 }
// Character: combines identity and traits
character Aragorn: Human from Warrior {
strength: 18
}
```
### Document with Prose Blocks
```storybook
character Martha: Human {
age: 34
---backstory
Martha learned to bake from her grandmother, starting at
age twelve. She now runs the most popular bakery in town.
---
---personality
Meticulous and patient, with an unwavering commitment to
quality. Tough but fair with her staff.
---
}
```
### Prefer Flat Inheritance
Avoid deep species hierarchies. Two or three levels is usually enough:
```storybook
// Good: shallow
species Mammal { warm_blooded: true }
species Human includes Mammal { sapient: true }
// Avoid: too deep
species Being { }
species LivingBeing includes Being { }
species Animal includes LivingBeing { }
species Vertebrate includes Animal { }
species Mammal includes Vertebrate { }
species Human includes Mammal { }
```
## Behavior Tree Design
### Name Every Composite Node
```storybook
// Good: self-documenting
choose daily_priority {
then handle_emergency { }
then do_work { }
then relax { }
}
// Avoid: anonymous nodes
choose {
then { }
then { }
}
```
### Keep Trees Shallow
Extract deep subtrees into separate behaviors:
```storybook
// Good: flat with includes
behavior Main {
choose mode {
include CombatBehavior
include ExplorationBehavior
include SocialBehavior
}
}
// Avoid: deeply nested
behavior Main {
choose {
then { choose { then { choose { then { Action } } } } }
}
}
```
### Use Decorators for Control Flow
```storybook
// Good: decorator handles timing
cooldown(30s) { CastSpell }
timeout(10s) { SolvePuzzle }
retry(3) { PickLock }
// Avoid: manual timing in actions
CheckCooldownTimer
IfCooldownReady { CastSpell }
```
## Expression Writing
### Use Parentheses for Clarity
```storybook
// Good: explicit grouping
on (health < 50 or is_poisoned) and has_antidote -> healing
// Risky: relies on precedence knowledge
on health < 50 or is_poisoned and has_antidote -> healing
```
### Break Complex Conditions into Multiple Transitions
```storybook
// Good: separate transitions, easy to read
state combat {
on health < 20 and not has_potion -> desperate
on surrounded and not has_escape -> desperate
on enemy_count > 10 -> desperate
}
// Avoid: one massive condition
state combat {
on (health < 20 and not has_potion) or (surrounded and not has_escape) or enemy_count > 10 -> desperate
}
```
### Use `is` for Enum Comparisons
```storybook
// Good: reads naturally
on status is active -> active_state
on skill_level is master -> teach_others
// Works but less readable
on status == active -> active_state
```
## Schedule Design
### Use Named Blocks for Override Support
```storybook
// Good: named blocks can be overridden
schedule Base {
block work { 09:00 - 17:00, action: standard_work }
}
schedule Variant extends Base {
block work { 05:00 - 13:00, action: early_work }
}
```
### Group Related Blocks
```storybook
schedule DailyRoutine {
// Morning
block wake { 06:00 - 07:00, action: morning_routine }
block breakfast { 07:00 - 08:00, action: eat }
// Work
block commute { 08:00 - 09:00, action: travel }
block work { 09:00 - 17:00, action: work }
// Evening
block leisure { 18:00 - 22:00, action: relax }
block sleep { 22:00 - 06:00, action: sleep }
}
```
## Relationship Design
### Use Roles for Clarity
```storybook
// Good: roles clarify the relationship
relationship Marriage {
Martha as spouse
David as spouse
bond: 0.9
}
// Less clear without roles
relationship Marriage {
Martha
David
bond: 0.9
}
```
### Use Perspectives for Asymmetry
```storybook
// Good: captures different viewpoints
relationship TeacherStudent {
Gandalf as teacher self { patience: 0.8 } other { potential: 0.9 }
Frodo as student self { motivation: 0.7 } other { admiration: 0.95 }
bond: 0.85
}
```
## General Principles
1. **Readability over brevity**: Storybook code should read like a narrative, not a puzzle.
2. **Explicit over implicit**: Say what you mean. Use named nodes, explicit imports, and clear field names.
3. **Flat over deep**: Shallow hierarchies, short behavior trees, and focused files are easier to maintain.
4. **Composition over inheritance**: Prefer combining templates over building deep species hierarchies.
5. **Document with prose**: Prose blocks are a feature, not clutter. Use them to explain intent alongside data.
6. **One concept per declaration**: Each behavior tree, life arc, or schedule should have a single clear purpose.
## Cross-References
- [Design Patterns](./20-patterns.md) - Common structural patterns
- [Validation Rules](../reference/19-validation.md) - What the compiler checks
- [Language Overview](../reference/09-overview.md) - Language philosophy