Extract functionality from handlers.py into focused modules: New Modules: - bot/message_utils.py (120 lines) - Telegram message handling * send_or_edit_with_image() - Smart message/image transitions * Image caching and upload logic - bot/commands.py (110 lines) - Slash command handlers * start() - Player initialization * export_map() - Admin map export * spawn_stats() - Admin spawn statistics Refactored: - bot/handlers.py: 365 → 177 lines (-51% reduction) * Now contains only routing logic * Re-exports commands for backward compatibility * Cleaner, more focused responsibility Benefits: - Single Responsibility Principle achieved - Better testability (can test modules independently) - Improved organization and discoverability - Easier maintenance (changes isolated to specific files) - Full backward compatibility maintained Documented in MODULE_SEPARATION.md
5.9 KiB
Module Separation - Clean Architecture
Date: October 20, 2025
Status: ✅ Complete
Overview
Extracted utility functions and command handlers from handlers.py into separate, focused modules, achieving true single-responsibility principle.
Changes
New Modules Created
1. bot/message_utils.py (120 lines)
Purpose: Message sending and editing utilities
Contains:
send_or_edit_with_image()- Smart message/image handling- Image caching and upload
- Smooth transitions between images
- Text-only message handling
- Edit vs send logic
Responsibilities:
- Telegram message manipulation
- Image file I/O and caching
- Error handling for message edits
2. bot/commands.py (110 lines)
Purpose: Slash command handlers
Contains:
start()- Initialize player and show statusexport_map()- Export map data as JSON (admin only)spawn_stats()- Show enemy spawn statistics (admin only)
Responsibilities:
- Command implementation
- Player initialization
- Admin commands
Refactored Module
bot/handlers.py
Before: 365 lines (routing + utilities + commands)
After: 177 lines (pure routing only)
Reduction: -188 lines (-51%)
Now Contains Only:
- Handler imports
HANDLER_MAPregistrybutton_handler()router- Re-exports of commands for main.py
Removed:
120 lines of utility functions110 lines of command handlers
Architecture
Before
handlers.py (365 lines)
├── Imports (60 lines)
├── Handler Registry (50 lines)
├── Utility Functions (120 lines) ❌ Mixed concerns
├── Command Handlers (110 lines) ❌ Mixed concerns
└── Button Router (25 lines)
After
handlers.py (177 lines) - Pure routing
├── Imports
├── Handler Registry
└── Button Router
message_utils.py (120 lines) - Message handling
└── send_or_edit_with_image()
commands.py (110 lines) - Command handlers
├── start()
├── export_map()
└── spawn_stats()
Benefits
1. Single Responsibility Principle
Each module has one clear purpose:
handlers.py→ Route button callbacksmessage_utils.py→ Handle Telegram messagescommands.py→ Implement slash commands
2. Improved Testability
Can test each module independently:
# Test message utils without routing
from bot.message_utils import send_or_edit_with_image
# Test commands without button handlers
from bot.commands import start, export_map
# Test routing without utility logic
from bot.handlers import button_handler
3. Better Organization
Clear separation of concerns:
- Routing logic → handlers.py
- Message I/O → message_utils.py
- User commands → commands.py
- Game actions → action_handlers.py, combat_handlers.py, etc.
4. Easier Maintenance
- Find code faster (know which file to open)
- Modify one concern without affecting others
- Less merge conflicts (changes in different files)
5. Cleaner Imports
# Before (everything from handlers)
from bot.handlers import start, button_handler, send_or_edit_with_image
# After (clear module boundaries)
from bot.handlers import button_handler
from bot.commands import start
from bot.message_utils import send_or_edit_with_image
File Structure
bot/
├── __init__.py
├── handlers.py (177 lines) - Router only
├── message_utils.py (120 lines) - Message utilities
├── commands.py (110 lines) - Slash commands
├── action_handlers.py (372 lines) - World actions
├── inventory_handlers.py(355 lines) - Inventory
├── combat_handlers.py (172 lines) - Combat
├── profile_handlers.py (147 lines) - Stats
├── corpse_handlers.py (234 lines) - Looting
├── pickup_handlers.py (135 lines) - Pickups
├── utils.py (120 lines) - General utilities
├── database.py - Data layer
├── keyboards.py - UI layer
├── logic.py - Game logic
└── combat.py - Combat system
Code Metrics
| Metric | Before | After | Change |
|---|---|---|---|
| handlers.py size | 365 lines | 177 lines | -188 (-51%) |
| Modules | 10 | 12 | +2 |
| Max module size | 372 lines | 372 lines | Unchanged |
| Avg module size | ~250 lines | ~200 lines | -50 lines |
| Separation of Concerns | ⚠️ Mixed | ✅ Clean | Improved |
Backward Compatibility
✅ Fully backward compatible
The refactoring maintains all existing interfaces:
# main.py continues to work unchanged
from bot import handlers
application.add_handler(CommandHandler("start", handlers.start))
application.add_handler(CallbackQueryHandler(handlers.button_handler))
handlers.py re-exports commands for compatibility:
# handlers.py
from .commands import start, export_map, spawn_stats # Re-export
# Allows: handlers.start (from main.py)
Testing
All modules tested and working:
- ✅
bot/handlers.py- Router works correctly - ✅
bot/message_utils.py- Image handling works - ✅
bot/commands.py- Commands execute properly - ✅ No import errors
- ✅ No runtime errors
- ✅ All handler calls work identically
Migration Path
If you want to update imports in the future:
Option 1: Keep Current (Recommended)
# main.py
from bot import handlers
handlers.start # Works via re-export
Option 2: Direct Imports
# main.py
from bot.commands import start, export_map, spawn_stats
from bot.handlers import button_handler
Both work identically!
Conclusion
This refactoring achieves:
- ✅ 51% reduction in handlers.py size
- ✅ Clear separation of concerns
- ✅ Better organization and discoverability
- ✅ Improved testability and maintainability
- ✅ Full backward compatibility
- ✅ No behavior changes
The codebase is now cleaner, more modular, and follows best practices for Python project structure!