--- description: Modular design principles and architecture guidelines for scalable development globs: alwaysApply: false --- # Rule: Architecture and Modular Design ## Goal Maintain a clean, modular architecture that scales effectively and prevents the complexity issues that arise in AI-assisted development. ## Core Architecture Principles ### 1. Modular Design - **Single Responsibility**: Each module has one clear purpose - **Loose Coupling**: Modules depend on interfaces, not implementations - **High Cohesion**: Related functionality is grouped together - **Clear Boundaries**: Module interfaces are well-defined and stable ### 2. Size Constraints - **Files**: Maximum 250 lines per file - **Functions**: Maximum 50 lines per function - **Classes**: Maximum 300 lines per class - **Modules**: Maximum 10 public functions/classes per module ### 3. Dependency Management - **Layer Dependencies**: Higher layers depend on lower layers only - **No Circular Dependencies**: Modules cannot depend on each other cyclically - **Interface Segregation**: Depend on specific interfaces, not broad ones - **Dependency Injection**: Pass dependencies rather than creating them internally ## Modular Architecture Patterns ### Layer Structure ``` src/ ├── presentation/ # UI, API endpoints, CLI interfaces ├── application/ # Business logic, use cases, workflows ├── domain/ # Core business entities and rules ├── infrastructure/ # Database, external APIs, file systems └── shared/ # Common utilities, constants, types ``` ### Module Organization ``` module_name/ ├── __init__.py # Public interface exports ├── core.py # Main module logic ├── types.py # Type definitions and interfaces ├── utils.py # Module-specific utilities ├── tests/ # Module tests └── README.md # Module documentation ``` ## Design Patterns for AI Development ### 1. Repository Pattern Separate data access from business logic: ```python # Domain interface class UserRepository: def get_by_id(self, user_id: str) -> User: ... def save(self, user: User) -> None: ... # Infrastructure implementation class SqlUserRepository(UserRepository): def get_by_id(self, user_id: str) -> User: # Database-specific implementation pass ``` ### 2. Service Pattern Encapsulate business logic in focused services: ```python class UserService: def __init__(self, user_repo: UserRepository): self._user_repo = user_repo def create_user(self, data: UserData) -> User: # Validation and business logic # Single responsibility: user creation pass ``` ### 3. Factory Pattern Create complex objects with clear interfaces: ```python class DatabaseFactory: @staticmethod def create_connection(config: DatabaseConfig) -> Connection: # Handle different database types # Encapsulate connection complexity pass ``` ## Architecture Decision Guidelines ### When to Create New Modules Create a new module when: - **Functionality** exceeds size constraints (250 lines) - **Responsibility** is distinct from existing modules - **Dependencies** would create circular references - **Reusability** would benefit other parts of the system - **Testing** requires isolated test environments ### When to Split Existing Modules Split modules when: - **File size** exceeds 250 lines - **Multiple responsibilities** are evident - **Testing** becomes difficult due to complexity - **Dependencies** become too numerous - **Change frequency** differs significantly between parts ### Module Interface Design ```python # Good: Clear, focused interface class PaymentProcessor: def process_payment(self, amount: Money, method: PaymentMethod) -> PaymentResult: """Process a single payment transaction.""" pass # Bad: Unfocused, kitchen-sink interface class PaymentManager: def process_payment(self, ...): pass def validate_card(self, ...): pass def send_receipt(self, ...): pass def update_inventory(self, ...): pass # Wrong responsibility! ``` ## Architecture Validation ### Architecture Review Checklist - [ ] **Dependencies flow in one direction** (no cycles) - [ ] **Layers are respected** (presentation doesn't call infrastructure directly) - [ ] **Modules have single responsibility** - [ ] **Interfaces are stable** and well-defined - [ ] **Size constraints** are maintained - [ ] **Testing** is straightforward for each module ### Red Flags - **God Objects**: Classes/modules that do too many things - **Circular Dependencies**: Modules that depend on each other - **Deep Inheritance**: More than 3 levels of inheritance - **Large Interfaces**: Interfaces with more than 7 methods - **Tight Coupling**: Modules that know too much about each other's internals ## Refactoring Guidelines ### When to Refactor - Module exceeds size constraints - Code duplication across modules - Difficult to test individual components - New features require changing multiple unrelated modules - Performance bottlenecks due to poor separation ### Refactoring Process 1. **Identify** the specific architectural problem 2. **Design** the target architecture 3. **Create tests** to verify current behavior 4. **Implement changes** incrementally 5. **Validate** that tests still pass 6. **Update documentation** to reflect changes ### Safe Refactoring Practices - **One change at a time**: Don't mix refactoring with new features - **Tests first**: Ensure comprehensive test coverage before refactoring - **Incremental changes**: Small steps with verification at each stage - **Backward compatibility**: Maintain existing interfaces during transition - **Documentation updates**: Keep architecture documentation current ## Architecture Documentation ### Architecture Decision Records (ADRs) Document significant decisions in `./docs/decisions/`: ```markdown # ADR-003: Service Layer Architecture ## Status Accepted ## Context As the application grows, business logic is scattered across controllers and models. ## Decision Implement a service layer to encapsulate business logic. ## Consequences **Positive:** - Clear separation of concerns - Easier testing of business logic - Better reusability across different interfaces **Negative:** - Additional abstraction layer - More files to maintain ``` ### Module Documentation Template ```markdown # Module: [Name] ## Purpose What this module does and why it exists. ## Dependencies - **Imports from**: List of modules this depends on - **Used by**: List of modules that depend on this one - **External**: Third-party dependencies ## Public Interface ```python # Key functions and classes exposed by this module ``` ## Architecture Notes - Design patterns used - Important architectural decisions - Known limitations or constraints ``` ## Migration Strategies ### Legacy Code Integration - **Strangler Fig Pattern**: Gradually replace old code with new modules - **Adapter Pattern**: Create interfaces to integrate old and new code - **Facade Pattern**: Simplify complex legacy interfaces ### Gradual Modernization 1. **Identify boundaries** in existing code 2. **Extract modules** one at a time 3. **Create interfaces** for each extracted module 4. **Test thoroughly** at each step 5. **Update documentation** continuously