656 lines
20 KiB
Markdown
656 lines
20 KiB
Markdown
# Code of Conduct - Skelly Project
|
|
|
|
## Overview
|
|
|
|
Coding standards and development practices for the Skelly project. These guidelines help developers contribute effectively while maintaining code quality and project consistency.
|
|
|
|
## Core Principles
|
|
|
|
### 1. Code Clarity Over Cleverness
|
|
- Write code that is easy to read
|
|
- Use descriptive variable and function names
|
|
- Prefer explicit code over "clever" solutions
|
|
- Comment complex logic and business rules
|
|
|
|
### 2. Consistency First
|
|
- Follow existing code patterns
|
|
- Use same naming conventions throughout
|
|
- Maintain consistent indentation and formatting
|
|
- Follow Godot's GDScript style guide
|
|
|
|
### 3. Incremental Development
|
|
- Make small, focused commits
|
|
- Test changes before committing
|
|
- Don't break existing functionality
|
|
- Use debug system to verify changes
|
|
|
|
## GDScript Coding Standards
|
|
|
|
### Naming Conventions
|
|
|
|
> 📋 **Quick Reference**: For complete naming convention details, see the **[Naming Convention Quick Reference](#naming-convention-quick-reference)** section below.
|
|
|
|
```gdscript
|
|
# Variables and functions: snake_case
|
|
var player_health: int = 100
|
|
func calculate_damage() -> int:
|
|
|
|
# Constants: SCREAMING_SNAKE_CASE
|
|
const MAX_HEALTH := 100
|
|
const TILE_SPACING := 54
|
|
|
|
# Classes: PascalCase
|
|
class_name PlayerController
|
|
|
|
# Scene files (.tscn) and Script files (.gd): PascalCase
|
|
# MainMenu.tscn, MainMenu.gd
|
|
# Match3Gameplay.tscn, Match3Gameplay.gd
|
|
# TestAudioManager.gd (test files)
|
|
|
|
# Signals: past_tense
|
|
signal health_changed
|
|
signal game_started
|
|
|
|
# Private functions: prefix with underscore
|
|
func _ready():
|
|
func _initialize_grid():
|
|
```
|
|
|
|
### File Organization
|
|
```gdscript
|
|
# 1. extends statement
|
|
extends Node2D
|
|
|
|
# 2. class_name (if applicable)
|
|
class_name Match3Controller
|
|
|
|
# 3. Constants
|
|
const GRID_SIZE := Vector2i(8, 8)
|
|
|
|
# 4. Signals
|
|
signal match_found(tiles: Array)
|
|
|
|
# 5. Variables
|
|
var grid := []
|
|
@onready var debug_ui = $DebugUI
|
|
|
|
# 6. Functions (lifecycle first, then custom)
|
|
func _ready():
|
|
func _process(delta):
|
|
func custom_function():
|
|
```
|
|
|
|
### Documentation Requirements
|
|
```gdscript
|
|
# Required for all public functions
|
|
func set_gem_pool(gem_indices: Array) -> void:
|
|
"""Set specific gem types as the active pool"""
|
|
_update_all_tiles_gem_pool(gem_indices)
|
|
print("Set gem pool to: ", gem_indices)
|
|
|
|
# Document complex algorithms
|
|
func _get_match_line(start: Vector2i, dir: Vector2i) -> Array:
|
|
"""Find all matching tiles in a line from start position in given direction"""
|
|
var line = [grid[start.y][start.x]]
|
|
var type = grid[start.y][start.x].tile_type
|
|
# Implementation...
|
|
```
|
|
|
|
## Project-Specific Guidelines
|
|
|
|
### Scene Management
|
|
- All scene transitions go through `GameManager`
|
|
- Never use `get_tree().change_scene_to_file()` directly
|
|
- Define scene paths as constants in GameManager
|
|
|
|
```gdscript
|
|
# ✅ Correct
|
|
GameManager.start_match3_game()
|
|
|
|
# ❌ Wrong
|
|
get_tree().change_scene_to_file("res://scenes/game/Game.tscn")
|
|
```
|
|
|
|
### Autoload Usage
|
|
- Use autoloads for global state only
|
|
- Don't access autoloads from deeply nested components
|
|
- Pass data through signals or direct references when possible
|
|
|
|
```gdscript
|
|
# ✅ Correct - using signals
|
|
signal settings_changed
|
|
SettingsManager.volume_changed.connect(_on_volume_changed)
|
|
|
|
# ✅ Also correct - direct access for global state
|
|
var current_language = SettingsManager.get_setting("language")
|
|
|
|
# ❌ Wrong - tight coupling
|
|
func some_deep_function():
|
|
SettingsManager.set_setting("volume", 0.5) # Too deep in call stack
|
|
```
|
|
|
|
### Debug System Integration
|
|
- Always connect to DebugManager signals for debug UI
|
|
- Use structured logging instead of plain print statements
|
|
- Remove temporary debug logs before committing (unless permanently useful)
|
|
|
|
```gdscript
|
|
# ✅ Correct debug integration
|
|
func _connect_to_global_debug() -> void:
|
|
DebugManager.debug_ui_toggled.connect(_on_debug_ui_toggled)
|
|
debug_ui.visible = DebugManager.is_debug_ui_visible()
|
|
|
|
# ✅ Good structured logging
|
|
DebugManager.log_debug("Debug UI toggled to: " + str(visible), "Match3")
|
|
DebugManager.log_info("Initialized " + str(tiles.size()) + " tiles", "TileSystem")
|
|
|
|
# ❌ Bad logging practices
|
|
print("test") # Not descriptive, use structured logging
|
|
print(some_variable) # No context, use proper log level
|
|
```
|
|
|
|
### Logging Standards
|
|
- Use `DebugManager.log_*()` functions instead of `print()` or `push_error()`
|
|
- Choose log levels based on message importance and audience
|
|
- Include categories to organize log output by system/component
|
|
- Format messages with clear, descriptive text and relevant context
|
|
|
|
```gdscript
|
|
# ✅ Correct logging usage
|
|
DebugManager.log_info("Game scene loaded successfully", "SceneManager")
|
|
DebugManager.log_warn("Audio file not found, using default", "AudioManager")
|
|
DebugManager.log_error("Failed to save settings: " + error_message, "Settings")
|
|
|
|
# ❌ Wrong approaches
|
|
print("loaded") # Use DebugManager.log_info() with category
|
|
push_error("error") # Use DebugManager.log_error() with context
|
|
if debug_mode: print("debug info") # Use DebugManager.log_debug()
|
|
```
|
|
|
|
### Asset Management
|
|
- **Document every asset** in `assets/sources.yaml`
|
|
- Include source information, license details, and attribution
|
|
- Document modifications made to original assets
|
|
- Verify license compatibility before adding assets
|
|
- Update sources.yaml in same commit as adding asset
|
|
|
|
```gdscript
|
|
# ✅ Correct asset addition workflow
|
|
# 1. Add asset file to appropriate assets/ subdirectory
|
|
# 2. Update assets/sources.yaml with complete metadata
|
|
# 3. Commit both files together with descriptive message
|
|
|
|
# Example sources.yaml entry:
|
|
# audio:
|
|
# sfx:
|
|
# "button_click.wav":
|
|
# source: "https://freesound.org/people/user/sounds/12345/"
|
|
# license: "CC BY 3.0"
|
|
# attribution: "Button Click by SoundArtist"
|
|
# modifications: "Normalized volume, trimmed silence"
|
|
# usage: "UI button interactions"
|
|
```
|
|
|
|
### Error Handling
|
|
- Check if resources loaded successfully
|
|
- Use `DebugManager.log_error()` for critical failures
|
|
- Provide fallback behavior when possible
|
|
- Include meaningful context in error messages
|
|
|
|
```gdscript
|
|
# Good error handling with structured logging
|
|
func load_scene(path: String) -> void:
|
|
var packed_scene := load(path)
|
|
if not packed_scene or not packed_scene is PackedScene:
|
|
DebugManager.log_error("Failed to load scene at: %s" % path, "SceneLoader")
|
|
return
|
|
DebugManager.log_info("Successfully loaded scene: %s" % path, "SceneLoader")
|
|
get_tree().change_scene_to_packed(packed_scene)
|
|
```
|
|
|
|
### Memory Management Standards
|
|
|
|
**Critical Rules**:
|
|
1. **Always use `queue_free()`** instead of `free()` for node cleanup
|
|
2. **Wait for frame completion** after queueing nodes for removal
|
|
3. **Clear references before cleanup** to prevent access to freed memory
|
|
4. **Connect signals properly** for dynamically created nodes
|
|
|
|
```gdscript
|
|
# ✅ Correct memory management
|
|
for child in children_to_remove:
|
|
child.queue_free()
|
|
await get_tree().process_frame # Wait for cleanup
|
|
|
|
# ❌ Dangerous pattern (causes crashes)
|
|
for child in children_to_remove:
|
|
child.free() # Immediate deletion can crash
|
|
```
|
|
|
|
**Why This Matters**: Using `free()` causes immediate deletion which can crash if the node is still referenced elsewhere. `queue_free()` waits until it's safe to delete.
|
|
|
|
**See Also**: [ARCHITECTURE.md](ARCHITECTURE.md#memory-management-queue_free-over-free) for architectural rationale.
|
|
|
|
### Input Validation Standards
|
|
|
|
All user inputs must be validated before processing.
|
|
|
|
**Validation Requirements**:
|
|
1. **Type checking**: Verify input types before processing
|
|
2. **Bounds checking**: Validate numeric ranges and array indices
|
|
3. **Null checking**: Handle null and empty inputs gracefully
|
|
4. **Whitelist validation**: Validate against known good values
|
|
|
|
```gdscript
|
|
# ✅ Proper input validation
|
|
func set_volume(value: float, setting_key: String) -> bool:
|
|
# Whitelist validation
|
|
if not setting_key in ["master_volume", "music_volume", "sfx_volume"]:
|
|
DebugManager.log_error("Invalid volume setting key: " + str(setting_key), "Settings")
|
|
return false
|
|
|
|
# Bounds checking
|
|
var clamped_value = clamp(value, 0.0, 1.0)
|
|
if clamped_value != value:
|
|
DebugManager.log_warn("Volume value clamped from %f to %f" % [value, clamped_value], "Settings")
|
|
|
|
SettingsManager.set_setting(setting_key, clamped_value)
|
|
return true
|
|
|
|
# ✅ Grid movement validation
|
|
func _move_cursor(direction: Vector2i) -> void:
|
|
# Bounds checking
|
|
if abs(direction.x) > 1 or abs(direction.y) > 1:
|
|
DebugManager.log_error("Invalid cursor direction: " + str(direction), "Match3")
|
|
return
|
|
|
|
# Null/empty checking
|
|
if not grid or grid.is_empty():
|
|
DebugManager.log_error("Grid not initialized", "Match3")
|
|
return
|
|
|
|
# Process validated input
|
|
var new_pos = cursor_pos + direction
|
|
# ... continue with validated data
|
|
```
|
|
|
|
**See Also**: [ARCHITECTURE.md](ARCHITECTURE.md#input-validation-whitelist-approach) for architectural decision rationale.
|
|
|
|
## Code Quality Checklist
|
|
|
|
Before committing code, verify:
|
|
|
|
- [ ] All user inputs validated (type, bounds, null checks)
|
|
- [ ] Error handling with fallback mechanisms implemented
|
|
- [ ] Memory cleanup uses `queue_free()` not `free()`
|
|
- [ ] No global static state introduced
|
|
- [ ] Proper logging with categories and appropriate levels
|
|
- [ ] Race condition protection for async operations
|
|
- [ ] Input actions defined in project input map
|
|
- [ ] Resources loaded with null/type checking
|
|
- [ ] Documentation updated for new public APIs
|
|
- [ ] Test coverage for new functionality
|
|
|
|
## Git Workflow
|
|
|
|
### Commit Guidelines
|
|
- Use clear, descriptive commit messages
|
|
- Start with a verb in imperative mood
|
|
- Keep first line under 50 characters
|
|
- Add body if needed for complex changes
|
|
|
|
```bash
|
|
# Good commit messages
|
|
Add gem pool management to match-3 system
|
|
Fix debug UI visibility toggle issue
|
|
Update documentation for new debug system
|
|
|
|
# Bad commit messages
|
|
fix bug
|
|
update
|
|
wip
|
|
```
|
|
|
|
### Branch Management
|
|
- Create feature branches for new functionality
|
|
- Use descriptive branch names: `feature/debug-ui`, `fix/tile-positioning`
|
|
- Keep branches focused on single features
|
|
- Delete branches after merging
|
|
|
|
### Before Committing
|
|
1. Test your changes in the Godot editor
|
|
2. Check that existing functionality still works
|
|
3. Use the debug system to verify your implementation
|
|
4. Run the project and navigate through affected areas
|
|
5. Remove temporary debug code
|
|
|
|
## Code Review Guidelines
|
|
|
|
### For Reviewers
|
|
- Focus on code clarity and maintainability
|
|
- Check for adherence to project patterns
|
|
- Verify that autoloads are used appropriately
|
|
- Ensure debug integration is properly implemented
|
|
- Test the changes yourself
|
|
|
|
### For Contributors
|
|
- Explain complex logic in commit messages or comments
|
|
- Provide context for why changes were made
|
|
- Test edge cases and error conditions
|
|
- Ask questions if project patterns are unclear
|
|
|
|
## Testing Approach
|
|
|
|
### Manual Testing Requirements
|
|
- Test in Godot editor with F5 run
|
|
- Verify debug UI works with F12 toggle
|
|
- Check scene transitions work
|
|
- Test on different screen sizes (mobile target)
|
|
- Verify audio and settings integration
|
|
|
|
### Debug System Testing
|
|
- Ensure debug panels appear/disappear correctly
|
|
- Test all debug buttons and controls
|
|
- Verify debug state persists across scene changes
|
|
- Check debug code doesn't affect release builds
|
|
|
|
## Naming Convention Quick Reference
|
|
|
|
> 🎯 **Single Source of Truth**: This section contains all naming conventions for the Skelly project. All other documentation files reference this section to avoid duplication and ensure consistency.
|
|
|
|
### 1. GDScript Code Elements
|
|
|
|
```gdscript
|
|
# Variables and functions: snake_case
|
|
var player_health: int = 100
|
|
func calculate_damage() -> int:
|
|
|
|
# Constants: SCREAMING_SNAKE_CASE
|
|
const MAX_HEALTH := 100
|
|
const TILE_SPACING := 54
|
|
|
|
# Classes: PascalCase
|
|
class_name PlayerController
|
|
|
|
# Signals: past_tense_with_underscores
|
|
signal health_changed
|
|
signal game_started
|
|
signal match_found
|
|
|
|
# Private functions: prefix with underscore
|
|
func _ready():
|
|
func _initialize_grid():
|
|
```
|
|
|
|
### 2. File Naming Standards
|
|
|
|
#### Script and Scene Files
|
|
```gdscript
|
|
# ✅ Correct: All .gd and .tscn files use PascalCase
|
|
MainMenu.tscn / MainMenu.gd
|
|
Match3Gameplay.tscn / Match3Gameplay.gd
|
|
ClickomaniaGameplay.tscn / ClickomaniaGameplay.gd
|
|
ValueStepper.tscn / ValueStepper.gd
|
|
|
|
# Test files: PascalCase with "Test" prefix
|
|
TestAudioManager.gd
|
|
TestGameManager.gd
|
|
TestMatch3Gameplay.gd
|
|
|
|
# ❌ Wrong: Old snake_case style (being migrated)
|
|
main_menu.tscn / main_menu.gd
|
|
TestAudioManager.gd
|
|
```
|
|
|
|
**Rules:**
|
|
- Scene files (.tscn) must match their script file name exactly
|
|
- All new files must use PascalCase
|
|
- Test files use "Test" prefix + PascalCase
|
|
- Autoload scripts follow PascalCase (GameManager.gd, AudioManager.gd)
|
|
|
|
### 3. Directory Naming Conventions
|
|
|
|
#### Source Code Directories
|
|
```
|
|
# Source directories: snake_case
|
|
src/autoloads/
|
|
scenes/game/gameplays/
|
|
scenes/ui/components/
|
|
tests/helpers/
|
|
|
|
# Root directories: lowercase
|
|
docs/
|
|
tests/
|
|
tools/
|
|
data/
|
|
```
|
|
|
|
#### Asset Directories
|
|
```
|
|
# Asset directories: kebab-case
|
|
assets/audio-files/
|
|
assets/ui-sprites/
|
|
assets/game-textures/
|
|
assets/fonts/
|
|
localization/
|
|
```
|
|
|
|
### 4. Resource and Configuration Files
|
|
|
|
```bash
|
|
# Configuration files: lowercase with dots
|
|
project.godot
|
|
gdlintrc
|
|
.gdformatrc
|
|
.editorconfig
|
|
export_presets.cfg
|
|
|
|
# Godot resource files (.tres): PascalCase
|
|
data/DefaultBusLayout.tres
|
|
data/PlayerSaveData.tres
|
|
scenes/ui/DefaultTheme.tres
|
|
|
|
# Asset metadata: kebab-case
|
|
assets/asset-sources.yaml
|
|
assets/audio-files/audio-sources.yaml
|
|
assets/ui-sprites/sprite-sources.yaml
|
|
|
|
# Development files: kebab-case
|
|
requirements.txt
|
|
development-tools.md
|
|
```
|
|
|
|
### 5. Asset File Naming
|
|
|
|
```bash
|
|
# Audio files: kebab-case in kebab-case directories
|
|
assets/audio-files/background-music.ogg
|
|
assets/audio-files/ui-sounds/button-click.wav
|
|
assets/audio-files/game-sounds/match-sound.wav
|
|
|
|
# Visual assets: kebab-case
|
|
assets/ui-sprites/main-menu-background.png
|
|
assets/game-textures/gem-blue.png
|
|
assets/fonts/main-ui-font.ttf
|
|
|
|
# Import settings: match the original file
|
|
background-music.ogg.import
|
|
button-click.wav.import
|
|
```
|
|
|
|
**Asset Rules:**
|
|
- All asset files use kebab-case
|
|
- Organized in kebab-case directories
|
|
- Import files automatically match asset names
|
|
- Document all assets in `asset-sources.yaml`
|
|
|
|
### 6. Git Workflow Conventions
|
|
|
|
#### Branch Naming
|
|
```bash
|
|
# Feature branches: feature/description-with-hyphens
|
|
feature/new-gameplay-mode
|
|
feature/settings-ui-improvement
|
|
feature/audio-system-upgrade
|
|
|
|
# Bug fixes: fix/description-with-hyphens
|
|
fix/tile-positioning-bug
|
|
fix/save-data-corruption
|
|
fix/debug-menu-visibility
|
|
|
|
# Refactoring: refactor/component-name
|
|
refactor/match3-input-system
|
|
refactor/autoload-structure
|
|
|
|
# Documentation: docs/section-name
|
|
docs/code-of-conduct-update
|
|
docs/api-documentation
|
|
```
|
|
|
|
#### Commit Message Format
|
|
```bash
|
|
# Format: <type>: <description>
|
|
# Examples:
|
|
feat: add dark mode toggle to settings menu
|
|
fix: resolve tile swap animation timing issue
|
|
docs: update naming conventions in code of conduct
|
|
refactor: migrate print statements to DebugManager
|
|
test: add comprehensive match3 validation tests
|
|
```
|
|
|
|
### 7. Quick Reference Summary
|
|
|
|
| File Type | Convention | Example |
|
|
|-----------|------------|---------|
|
|
| **GDScript Files** | PascalCase | `MainMenu.gd`, `AudioManager.gd` |
|
|
| **Scene Files** | PascalCase | `MainMenu.tscn`, `Match3Gameplay.tscn` |
|
|
| **Test Files** | Test + PascalCase | `TestAudioManager.gd` |
|
|
| **Variables/Functions** | snake_case | `player_health`, `calculate_damage()` |
|
|
| **Constants** | SCREAMING_SNAKE_CASE | `MAX_HEALTH`, `TILE_SPACING` |
|
|
| **Classes** | PascalCase | `class_name PlayerController` |
|
|
| **Signals** | past_tense | `health_changed`, `game_started` |
|
|
| **Directories** | snake_case (src) / kebab-case (assets) | `src/autoloads/`, `assets/audio-files/` |
|
|
| **Assets** | kebab-case | `background-music.ogg`, `gem-blue.png` |
|
|
| **Config Files** | lowercase.extension | `project.godot`, `.gdformatrc` |
|
|
| **Branches** | type/kebab-case | `feature/new-gameplay`, `fix/tile-bug` |
|
|
|
|
> ✅ **Status**: All major file naming inconsistencies have been resolved. The project now follows consistent PascalCase naming for all .gd and .tscn files.
|
|
|
|
### 8. File Renaming Migration Guide
|
|
|
|
When renaming files to follow conventions:
|
|
|
|
**Step-by-step procedure:**
|
|
1. **Use Git rename**: `git mv old_file.gd NewFile.gd` (preserves history)
|
|
2. **Update .tscn references**: Modify script path in scene files
|
|
3. **Update code references**: Search and replace all `preload()` and `load()` statements
|
|
4. **Update project.godot**: If file is referenced in autoloads or project settings
|
|
5. **Update documentation**: Search all .md files for old references
|
|
6. **Update test files**: Modify any test files that reference the renamed file
|
|
7. **Run validation**: Execute `gdlint`, `gdformat`, and project tests
|
|
8. **Verify in editor**: Load scenes in Godot editor to confirm everything works
|
|
|
|
**Tools for validation:**
|
|
- `python tools/run_development.py --test` - Run all tests
|
|
- `python tools/run_development.py --lint` - Check code quality
|
|
- `python tools/run_development.py --format` - Ensure consistent formatting
|
|
|
|
## Common Mistakes to Avoid
|
|
|
|
### Architecture Violations
|
|
```gdscript
|
|
# Don't bypass GameManager
|
|
get_tree().change_scene_to_file("some_scene.tscn")
|
|
|
|
# Don't hardcode paths
|
|
var tile = load("res://scenes/game/gameplays/Tile.tscn")
|
|
|
|
# Don't ignore null checks
|
|
var node = get_node("SomeNode")
|
|
node.do_something() # Could crash if node doesn't exist
|
|
|
|
# Don't create global state in random scripts
|
|
# Use autoloads instead
|
|
```
|
|
|
|
### Asset Management Violations
|
|
```gdscript
|
|
# Don't add assets without documentation
|
|
# Adding audio/new_music.mp3 without updating sources.yaml
|
|
|
|
# Don't use assets without verifying licenses
|
|
# Using copyrighted music without permission
|
|
|
|
# Don't modify assets without documenting changes
|
|
# Editing sprites without noting modifications in sources.yaml
|
|
|
|
# Don't commit assets and documentation separately
|
|
git add assets/sprites/new_sprite.png
|
|
git commit -m "add sprite" # Missing sources.yaml update
|
|
|
|
# Correct approach
|
|
git add assets/sprites/new_sprite.png assets/sources.yaml
|
|
git commit -m "add new sprite with attribution"
|
|
```
|
|
|
|
### Performance Issues
|
|
```gdscript
|
|
# Don't search nodes repeatedly
|
|
func _process(delta):
|
|
var ui = get_node("UI") # Expensive every frame
|
|
|
|
# Cache node references
|
|
@onready var ui = $UI
|
|
func _process(delta):
|
|
ui.update_display() # Much better
|
|
```
|
|
|
|
### Debug System Misuse
|
|
```gdscript
|
|
# Don't create separate debug systems
|
|
var my_debug_enabled = false
|
|
print("debug: " + some_info) # Don't use plain print()
|
|
|
|
# Use the global debug and logging systems
|
|
if DebugManager.is_debug_enabled():
|
|
show_debug_info()
|
|
DebugManager.log_debug("Debug information: " + some_info, "MyComponent")
|
|
```
|
|
|
|
## Learning Resources
|
|
|
|
### Godot-Specific
|
|
- [GDScript Style Guide](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html)
|
|
- [Godot Best Practices](https://docs.godotengine.org/en/stable/tutorials/best_practices/index.html)
|
|
- Project documentation in `docs/map.md`
|
|
|
|
### General Programming
|
|
- Clean Code principles
|
|
- SOLID principles (adapted for game development)
|
|
- Git best practices
|
|
|
|
## Getting Help
|
|
|
|
### When Stuck
|
|
1. Check existing code for similar patterns
|
|
2. Review project documentation (`docs/`)
|
|
3. Use the debug system to understand current state
|
|
4. Ask specific questions about project architecture
|
|
5. Test your understanding with small experiments
|
|
|
|
### Code Review Process
|
|
- Submit pull requests early and often
|
|
- Ask for feedback on approach before implementing large features
|
|
- Be open to suggestions and alternative approaches
|
|
- Learn from review feedback for future contributions
|
|
|
|
## Summary
|
|
|
|
This code of conduct emphasizes:
|
|
- **Clarity**: Write code that others can understand
|
|
- **Consistency**: Follow established patterns
|
|
- **Integration**: Use the project's systems properly
|
|
- **Learning**: Continuously improve your skills
|
|
|
|
Remember: It's better to ask questions and write clear, simple code than to guess and create complex, hard-to-maintain solutions. The goal is to contribute effectively to a codebase that will grow and evolve over time.
|