# 🔧 Modular Design Patterns

> **Plugin-based architecture** enabling scalable, maintainable, and extensible feature development with dependency injection, service abstractions, and clean modular boundaries.

## Table of Contents

- [[#Design Philosophy]]
- [[#Architecture Components]]
- [[#Service Abstractions]]
- [[#Module Development]]
- [[#Implementation Patterns]]
- [[#Benefits & Trade-offs]]

## Design Philosophy

### **Separation of Concerns**
Each module owns its complete domain logic, from data models to UI components, ensuring clear boundaries and reducing coupling between features.

### **Dependency Injection**
Services communicate through well-defined interfaces using a centralized DI container, enabling loose coupling and testability.

### **Plugin-Based Development**
Features are implemented as self-contained modules that can be independently developed, tested, and deployed.

### **Reactive Architecture**
Services integrate Vue's reactivity system to provide automatic UI updates and consistent state management.

---

## Architecture Components

### **Plugin Manager**
Orchestrates module loading, dependency resolution, and lifecycle management:

```typescript
class PluginManager {
  async loadModules(modules: ModulePlugin[]): Promise<void>
  getDependencyGraph(): Map<string, string[]>
  validateDependencies(modules: ModulePlugin[]): void
}
```

### **Dependency Injection Container**
Manages service registration, injection, and lifecycle:

```typescript
// Service registration
container.provide(SERVICE_TOKENS.RELAY_HUB, relayHub)

// Service consumption
const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB)
```

### **BaseService Architecture**
Abstract foundation providing common patterns for all services:

```typescript
abstract class BaseService {
  protected readonly metadata: ServiceMetadata
  protected dependencies = new Map<string, any>()
  
  abstract initialize(): Promise<void>
  abstract dispose(): Promise<void>
}
```

### **Module Plugin Interface**
Standardized contract for all feature modules:

```typescript
interface ModulePlugin {
  name: string
  version: string
  dependencies: string[]
  
  install(app: App, options?: ModuleConfig): Promise<void>
  routes?: RouteRecordRaw[]
  components?: Record<string, Component>
}
```

## Service Abstractions

### **Core Infrastructure Services**

#### **AuthService** - User Identity Management
- **Purpose**: Centralized authentication with Nostr key handling
- **Features**: Session management, profile updates, secure key storage
- **Pattern**: BaseService with reactive state management

#### **RelayHub** - Nostr Connection Management  
- **Purpose**: Centralized relay connections and event processing
- **Features**: Connection pooling, automatic reconnection, event deduplication
- **Pattern**: Service singleton with connection state management

#### **InvoiceService** - Lightning Payment Processing
- **Purpose**: Unified Lightning Network integration
- **Features**: Invoice creation, payment monitoring, QR code generation
- **Pattern**: BaseService with LNBits API integration

#### **ToastService** - User Notifications
- **Purpose**: Consistent notification system across modules
- **Features**: Context-specific messages, accessibility support
- **Pattern**: Service with method categorization by context

#### **StorageService** - User-Scoped Data Persistence
- **Purpose**: Secure, user-isolated local storage operations
- **Features**: Encryption, type safety, reactive storage
- **Pattern**: Service with automatic user prefixing

### **Shared Composables**

#### **useAuth()** - Authentication Access
```typescript
const auth = useAuth()
const { isAuthenticated, currentUser, login, logout } = auth
```

#### **useToast()** - Notification Access
```typescript
const toast = useToast()
toast.success('Operation completed!')
toast.error('Operation failed')
```

#### **useStorage()** - Storage Access
```typescript
const storage = useStorage()
const userData = storage.getUserData('preferences', defaultPrefs)
```

## Module Development

### **Module Structure Pattern**
Each module follows a consistent directory structure:

```
src/modules/[module-name]/
├── index.ts                 # Module plugin definition
├── components/              # Module-specific UI components
├── composables/             # Module composables and hooks
├── services/               # Business logic services
├── stores/                 # Module-specific Pinia stores
├── types/                  # TypeScript type definitions
└── views/                  # Page components and routes
```

### **Service Development Pattern**
Services extend BaseService for consistent lifecycle management:

```typescript
export class MyService extends BaseService {
  protected readonly metadata = {
    name: 'MyService',
    dependencies: ['AuthService', 'RelayHub']
  }
  
  constructor() {
    super()
  }
  
  async initialize(): Promise<void> {
    await super.initialize() // Initialize dependencies
    // Service-specific initialization
    this.isInitialized.value = true
  }
  
  async dispose(): Promise<void> {
    // Cleanup logic
    this.isDisposed.value = true
  }
}
```

### **Module Registration Pattern**
Standardized module plugin structure:

```typescript
export const myModule: ModulePlugin = {
  name: 'my-module',
  version: '1.0.0',
  dependencies: ['base'],
  
  async install(app: App, options?: MyModuleConfig) {
    // 1. Create and register services
    const myService = new MyService()
    container.provide(SERVICE_TOKENS.MY_SERVICE, myService)
    
    // 2. Register global components
    app.component('MyGlobalComponent', MyGlobalComponent)
    
    // 3. Initialize services
    await myService.initialize()
  },
  
  routes: [
    {
      path: '/my-feature',
      component: () => import('./views/MyFeatureView.vue')
    }
  ]
}
```

### **Dependency Declaration**
Services declare dependencies through metadata:

```typescript
protected readonly metadata = {
  name: 'ChatService',
  dependencies: ['AuthService', 'RelayHub', 'StorageService']
}

// Access injected dependencies
private get authService(): AuthService {
  return this.dependencies.get('AuthService') as AuthService
}
```

## Implementation Patterns

### **Cross-Module Communication**

#### **Service Dependencies**
For required functionality between modules:
```typescript
// ✅ Correct: Use dependency injection
const relayHub = injectService(SERVICE_TOKENS.RELAY_HUB)

// ❌ Wrong: Direct import breaks modularity
import { relayHub } from '../base/services/relay-hub'
```

#### **Event Bus Communication**
For optional cross-module notifications:
```typescript
// Publishing events
eventBus.emit('user:authenticated', { userId: user.pubkey })
eventBus.emit('payment:received', { amount: 1000, invoiceId: 'abc123' })

// Subscribing to events
eventBus.on('chat:message-received', (message) => {
  // Handle cross-module events
})
```

#### **Shared Components**
Modules can export components for reuse:
```typescript
// In module plugin definition
export const chatModule: ModulePlugin = {
  components: {
    'ChatAvatar': () => import('./components/ChatAvatar.vue'),
    'MessageBubble': () => import('./components/MessageBubble.vue')
  }
}

// Usage in other modules
<ChatAvatar :pubkey="user.pubkey" :size="32" />
```

### **State Management Patterns**

#### **Service-Based State**
Core state managed by services:
```typescript
// AuthService manages authentication state
export class AuthService extends BaseService {
  public isAuthenticated = ref(false)
  public user = ref<User | null>(null)
  
  // Computed properties for components
  public userDisplay = computed(() => this.user.value?.name || 'Anonymous')
}
```

#### **Module-Specific Stores**
Complex state handled by Pinia stores:
```typescript
// Market module store
export const useMarketStore = defineStore('market', () => {
  const products = ref<Product[]>([])
  const cartItems = ref<CartItem[]>([])
  
  // Access shared services
  const auth = useAuth()
  const toast = useToast()
  
  return { products, cartItems }
})
```

### **Error Handling Patterns**

#### **Service-Level Error Handling**
Centralized error handling in services:
```typescript
export class MyService extends BaseService {
  protected handleError(error: Error, context: string) {
    console.error(`[${this.metadata.name}] ${context}:`, error)
    
    // Use toast service for user notifications
    const toast = injectService(SERVICE_TOKENS.TOAST_SERVICE)
    toast.error(`${context} failed: ${error.message}`)
  }
}
```

#### **Component-Level Error Handling**
Consistent error display in components:
```vue
<script setup lang="ts">
const { error, isLoading, execute } = useAsyncOperation()

const handleAction = () => execute(async () => {
  await myService.performAction()
})
</script>

<template>
  <div>
    <button @click="handleAction" :disabled="isLoading">
      {{ isLoading ? 'Loading...' : 'Perform Action' }}
    </button>
    <div v-if="error" class="error">{{ error }}</div>
  </div>
</template>
```

## Benefits & Trade-offs

### **Achieved Benefits**

#### **Development Velocity**
- **Consistent Patterns** - Standardized development approaches across modules
- **Reusable Services** - Shared infrastructure reduces implementation time
- **Type Safety** - Dependency injection eliminates `as any` casting
- **Clear Boundaries** - Module separation simplifies feature development

#### **Maintainability**
- **Single Source of Truth** - Centralized services eliminate duplication
- **Dependency Visibility** - Clear service relationships and requirements
- **Testability** - Isolated modules and mockable dependencies
- **Extensibility** - Easy to add new modules without affecting existing ones

#### **User Experience**
- **Consistent Interface** - Unified patterns across all features
- **Reliable Performance** - Optimized shared services
- **Progressive Loading** - Lazy-loaded modules for faster initial load
- **Error Recovery** - Consistent error handling and user feedback

### **Architectural Trade-offs**

#### **Complexity vs. Flexibility**
- **Increased Initial Setup** - More boilerplate for dependency injection
- **Enhanced Flexibility** - Easy to swap implementations and add features
- **Learning Curve** - Developers need to understand DI patterns
- **Long-term Benefits** - Reduced complexity as application grows

#### **Performance Considerations**
- **Service Initialization** - Dependency resolution overhead at startup
- **Memory Efficiency** - Singleton services reduce memory usage
- **Bundle Optimization** - Module-based code splitting improves loading
- **Runtime Performance** - Optimized shared services benefit all modules

### **Best Practices Established**

1. **Always use dependency injection** for cross-module service access
2. **Extend BaseService** for all business logic services  
3. **Declare dependencies explicitly** in service metadata
4. **Use reactive state** for UI-affecting service properties
5. **Handle errors consistently** through standardized patterns
6. **Test modules in isolation** with mocked dependencies

## See Also

### Architecture Documentation
- **[[index|🏗️ Architecture Overview]]** - System design principles
- **[[dependency-injection|⚙️ Dependency Injection]]** - DI container system
- **[[authentication-architecture|🔐 Authentication Architecture]]** - Auth service patterns

### Development Guides
- **[[../04-development/index|💻 Development Guide]]** - Module development workflows
- **[[../02-modules/index|📦 Module System]]** - Individual module documentation
- **[[../03-core-services/index|⚙️ Core Services]]** - Infrastructure service details

---

**Tags:** #architecture #modular-design #dependency-injection #plugin-system  
**Last Updated:** 2025-09-07  
**Author:** Development Team