# 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 modifies 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