Assist_Design/docs/SERVICE-REFACTOR-GUIDE.md
2025-08-27 20:01:46 +09:00

274 lines
8.8 KiB
Markdown

# Service Refactoring Guide: Modular Architecture
## 🎯 **Problem Solved: Monolithic Services**
### ❌ **Before: Monolithic Structure**
```typescript
// CatalogService.ts (700+ lines)
class CatalogService {
// Internet logic mixed with SIM logic mixed with VPN logic
// Caching logic mixed with business logic
// Hard to test, maintain, and extend
}
// OrdersService.ts (400+ lines)
class OrdersService {
// Validation, building, item creation, provisioning all mixed
// Difficult to isolate specific functionality
}
```
**Problems:**
- ❌ Single Responsibility Principle violated
- ❌ Hard to test individual components
- ❌ Difficult to maintain and debug
- ❌ High coupling between unrelated logic
- ❌ Large classes with mixed concerns
## ✅ **After: Modular Architecture**
### **🏗️ Catalog Services Structure**
```
📁 catalog/
├── 📁 services/
│ ├── base-catalog.service.ts # 🔧 Common Salesforce operations
│ ├── internet-catalog.service.ts # 🌐 Internet-specific logic
│ ├── sim-catalog.service.ts # 📱 SIM-specific logic
│ ├── vpn-catalog.service.ts # 🔒 VPN-specific logic
│ └── catalog-orchestrator.service.ts # 🎯 Coordinates everything + caching
├── catalog.controller.ts # 🚀 Routes to orchestrator
├── catalog.service.ts # ⚡ Legacy (backward compatible)
└── structured-catalog.service.ts # ⚡ Legacy (backward compatible)
```
### **🏗️ Orders Services Structure**
```
📁 orders/
├── 📁 services/
│ ├── order-validator.service.ts # ✅ Validation logic only
│ ├── order-builder.service.ts # 🔨 Order header building
│ ├── order-item-builder.service.ts # 📦 OrderItem creation
│ └── order-orchestrator.service.ts # 🎯 Coordinates order flow
├── orders.controller.ts # 🚀 Routes to orchestrator
└── orders.service.ts # ⚡ Legacy (backward compatible)
```
## 🧩 **Service Responsibilities**
### **Catalog Services**
| Service | Responsibility | Lines | Dependencies |
|---------|---------------|-------|-------------|
| `BaseCatalogService` | Common Salesforce queries, field mapping, error handling | ~120 | SF, Logger |
| `InternetCatalogService` | Internet plans, installations, add-ons logic | ~180 | BaseCatalog |
| `SimCatalogService` | SIM plans, activation fees, add-ons logic | ~140 | BaseCatalog |
| `VpnCatalogService` | VPN plans, activation fees logic | ~100 | BaseCatalog |
| `CatalogOrchestrator` | Coordinates services, handles caching | ~120 | All catalog services |
### **Order Services**
| Service | Responsibility | Lines | Dependencies |
|---------|---------------|-------|-------------|
| `OrderValidator` | Business rule validation, user mapping | ~180 | Mappings, WHMCS, SF |
| `OrderBuilder` | Order header field building | ~90 | None |
| `OrderItemBuilder` | SKU parsing, OrderItem creation | ~160 | SF |
| `OrderOrchestrator` | Coordinates order creation flow | ~120 | All order services |
## 🎯 **Usage Examples**
### **Using New Catalog Architecture**
```typescript
// In your service/controller
constructor(
private catalogOrchestrator: CatalogOrchestrator,
private internetCatalog: InternetCatalogService
) {}
// Get complete structured catalog (cached)
const catalog = await this.catalogOrchestrator.getStructuredCatalog();
// Get only Internet data (cached)
const internetData = await this.catalogOrchestrator.getInternetCatalog();
// Get specific Internet plans directly
const plans = await this.internetCatalog.getPlans();
```
### **Using New Order Architecture**
```typescript
// In your controller
constructor(private orderOrchestrator: OrderOrchestrator) {}
// Create order using orchestrated flow
const result = await this.orderOrchestrator.createOrder(userId, orderData);
// Get user orders
const orders = await this.orderOrchestrator.getOrdersForUser(userId);
```
### **Testing Individual Components**
```typescript
// Test only Internet catalog logic
describe('InternetCatalogService', () => {
let service: InternetCatalogService;
let mockBaseCatalog: jest.Mocked<BaseCatalogService>;
beforeEach(() => {
const module = Test.createTestingModule({
providers: [
InternetCatalogService,
{ provide: BaseCatalogService, useValue: mockBaseCatalog }
]
});
service = module.get(InternetCatalogService);
});
it('should parse internet plans correctly', async () => {
// Test only internet-specific logic, isolated
});
});
```
## 🔄 **Backward Compatibility**
### **Clean API Endpoints**
```typescript
// ✅ Clean architecture endpoints
GET /api/catalog // Uses CatalogOrchestrator (legacy format)
GET /api/catalog/structured // Uses CatalogOrchestrator (recommended)
GET /api/catalog/internet/addons // Uses CatalogOrchestrator
// ✅ Clean order endpoints
POST /api/orders // Uses OrderOrchestrator
GET /api/orders/user // Uses OrderOrchestrator
GET /api/orders/:id // Uses OrderOrchestrator
```
### **Clean Architecture Implementation**
```typescript
// ✅ Final clean implementation - no legacy code
@Module({
providers: [
BaseCatalogService, // Common operations
CatalogOrchestrator, // Main coordinator
InternetCatalogService, // Focused responsibility
SimCatalogService, // Focused responsibility
VpnCatalogService, // Focused responsibility
]
})
// ✅ Controller uses only orchestrator
@Controller()
class CatalogController {
constructor(
private catalogOrchestrator: CatalogOrchestrator // Single clean interface
) {}
@Get() getCatalog() { return this.catalogOrchestrator.getLegacyCatalog(); }
@Get('structured') getStructured() { return this.catalogOrchestrator.getStructuredCatalog(); }
}
```
## 📊 **Benefits Achieved**
| Aspect | Before | After |
|--------|---------|--------|
| **Service Size** | 700+ lines | ~120 lines per service |
| **Testability** | Hard (monolithic) | Easy (focused) |
| **Maintainability** | Difficult (mixed concerns) | Simple (single responsibility) |
| **Performance** | No specialized caching | Service-specific caching |
| **Extensibility** | Break existing code | Add new services cleanly |
| **Debugging** | Search through 700+ lines | Check specific 120-line service |
| **Code Coupling** | High (everything connected) | Low (focused dependencies) |
## 🚀 **Extension Examples**
### **Adding New Product Type**
```typescript
// 1. Create focused service
@Injectable()
export class IotCatalogService extends BaseCatalogService {
async getDevices(): Promise<IotDevice[]> {
const soql = this.buildCatalogServiceQuery('IoT');
// IoT-specific logic only, ~100 lines
}
}
// 2. Add to orchestrator
@Injectable()
export class CatalogOrchestrator {
constructor(
// ... existing services
private iotCatalog: IotCatalogService // Add new service
) {}
async getStructuredCatalog() {
const [internet, sim, vpn, iot] = await Promise.all([
this.internetCatalog.getCatalogData(),
this.simCatalog.getCatalogData(),
this.vpnCatalog.getCatalogData(),
this.iotCatalog.getCatalogData() // Add new data
]);
return { internet, sim, vpn, iot };
}
}
// 3. Zero changes to existing services! 🎉
```
### **Adding New Order Validation**
```typescript
// Add to OrderValidator - single responsibility
@Injectable()
export class OrderValidator {
validateCreditCheck(orderData: any): void {
// Add new validation logic without touching other services
}
}
// OrderOrchestrator automatically uses new validation
// No changes needed elsewhere! 🎉
```
## 🔧 **Development Benefits**
### **Focused Development**
```typescript
// Working on Internet features? Only touch InternetCatalogService
// Working on order validation? Only touch OrderValidator
// Working on caching? Only touch CatalogOrchestrator
```
### **Easy Testing**
```typescript
// Test only what you're working on
describe('InternetCatalogService', () => {
// Mock only BaseCatalogService
// Test only Internet logic
// ~50 test lines vs 200+ before
});
```
### **Clear Code Ownership**
```typescript
// 🌐 Internet features → InternetCatalogService
// 📱 SIM features → SimCatalogService
// 🔒 VPN features → VpnCatalogService
// ✅ Order validation → OrderValidator
// 📦 Order items → OrderItemBuilder
```
## 🎯 **Implementation Complete**
**Clean Architecture Achieved:**
1. **Modular services** with single responsibilities
2. **Shared types** eliminating duplication
3. **Reusable utilities** for business logic
4. **Clean API endpoints** using orchestrators
5. **Easy testing** with focused components
The clean architecture provides excellent maintainability, testability, and extensibility! 🎉