AgentSkillsCN

System Boundaries

明确界定各系统、服务与模块之间的边界,有效管控复杂性,助力各组件独立演进。

SKILL.md
--- frontmatter
name: System Boundaries
description: Defining clear boundaries between systems, services, and modules to manage complexity and enable independent evolution.

System Boundaries

Overview

System Boundaries define where one system ends and another begins, establishing clear interfaces, ownership, and responsibilities. Well-defined boundaries reduce coupling and enable teams to work independently.

Core Principle: "Strong boundaries enable weak coupling. Define interfaces, not implementations."


1. Why System Boundaries Matter

  • Reduces Coupling: Systems can evolve independently
  • Enables Scaling: Teams can own and scale their systems
  • Clarifies Ownership: Clear who is responsible for what
  • Improves Testability: Easier to test in isolation
  • Facilitates Understanding: Simpler mental models

2. Types of Boundaries

Service Boundaries

code
┌─────────────────┐     ┌─────────────────┐
│  User Service   │────▶│  Order Service  │
│  (owns users)   │     │  (owns orders)  │
└─────────────────┘     └─────────────────┘
        │                        │
        ▼                        ▼
   Users Table              Orders Table

Module Boundaries (within monolith)

typescript
// src/modules/auth/
export interface AuthService {
  login(credentials: Credentials): Promise<Token>;
  verify(token: Token): Promise<User>;
}

// src/modules/orders/
import { AuthService } from '../auth';  // Uses interface, not implementation

Data Boundaries

code
Each service owns its own database:
- User Service → users_db
- Order Service → orders_db
- Payment Service → payments_db

No cross-database queries allowed!

3. Bounded Contexts (DDD)

markdown
## E-commerce System Boundaries

### Sales Context
- **Entities**: Product, Cart, Order
- **Language**: "Add to cart", "Checkout", "Purchase"
- **Owner**: Sales team

### Inventory Context
- **Entities**: Stock, Warehouse, SKU
- **Language**: "Restock", "Allocate", "Reserve"
- **Owner**: Operations team

### Shipping Context
- **Entities**: Shipment, Carrier, Tracking
- **Language**: "Ship", "Deliver", "Track"
- **Owner**: Logistics team

**Note**: "Product" means different things in each context!
- Sales: Product with price, description
- Inventory: Product with stock level, location
- Shipping: Product with weight, dimensions

4. Interface Definition

REST API Boundary

typescript
// Public API contract (boundary)
interface OrderAPI {
  POST /orders
  GET /orders/:id
  PUT /orders/:id/cancel
}

// Implementation details (hidden)
class OrderService {
  private database: Database;
  private paymentGateway: PaymentGateway;
  
  // Internal methods not exposed via API
  private validateInventory() { }
  private processPayment() { }
}

Event-Driven Boundary

typescript
// Published events (boundary)
interface OrderEvents {
  'order.created': { orderId: string; userId: string; total: number };
  'order.shipped': { orderId: string; trackingNumber: string };
}

// Other services subscribe to events, don't call directly

5. Ownership and Responsibilities

markdown
## Service Ownership Matrix

| Service | Team | Owns Data | Provides | Consumes |
|---------|------|-----------|----------|----------|
| User Service | Identity Team | Users, Profiles | User CRUD, Auth | - |
| Order Service | Commerce Team | Orders, Line Items | Order Management | User Service (user validation) |
| Payment Service | Finance Team | Transactions | Payment Processing | Order Service (order details) |
| Notification Service | Platform Team | - | Email/SMS | All services (events) |

6. Anti-Corruption Layer

typescript
// External API has different model than our domain
interface ExternalPaymentAPI {
  charge(amount_cents: number, card_token: string): ExternalResponse;
}

// Anti-corruption layer translates
class PaymentAdapter {
  constructor(private external: ExternalPaymentAPI) {}
  
  async processPayment(payment: Payment): Promise<PaymentResult> {
    // Translate our domain model to external API
    const response = await this.external.charge(
      payment.amount * 100,  // dollars to cents
      payment.cardToken
    );
    
    // Translate response back to our domain
    return {
      success: response.status === 'succeeded',
      transactionId: response.id
    };
  }
}

7. Boundary Crossing Patterns

Synchronous (API Call)

typescript
// Order Service calls User Service
const user = await userService.getUser(userId);
if (!user) throw new Error('User not found');

Asynchronous (Events)

typescript
// Order Service publishes event
eventBus.publish('order.created', { orderId, userId, total });

// Notification Service subscribes
eventBus.subscribe('order.created', async (event) => {
  await sendOrderConfirmationEmail(event.userId, event.orderId);
});

Shared Database (Anti-pattern)

typescript
// ❌ DON'T: Order Service directly queries users table
const user = await db.query('SELECT * FROM users WHERE id = ?', [userId]);

// ✅ DO: Call User Service API
const user = await userService.getUser(userId);

8. Boundary Violations

Common Violations

typescript
// ❌ Violation: Reaching into another service's database
await orderDb.query('SELECT * FROM users WHERE id = ?', [userId]);

// ❌ Violation: Exposing internal implementation
class OrderService {
  public database: Database;  // Leaking internals
}

// ❌ Violation: Tight coupling
class OrderService {
  constructor(private userService: UserServiceImpl) {}  // Depends on concrete class
}

// ✅ Correct: Use interface
class OrderService {
  constructor(private userService: IUserService) {}  // Depends on interface
}

9. Boundary Testing

typescript
// Test boundary with mocks
describe('OrderService', () => {
  it('validates user exists before creating order', async () => {
    const mockUserService = {
      getUser: jest.fn().mockResolvedValue(null)
    };
    
    const orderService = new OrderService(mockUserService);
    
    await expect(
      orderService.createOrder({ userId: '123', items: [] })
    ).rejects.toThrow('User not found');
    
    expect(mockUserService.getUser).toHaveBeenCalledWith('123');
  });
});

10. System Boundaries Checklist

  • Clear Ownership: Each boundary has an owner?
  • Well-Defined Interfaces: APIs/events documented?
  • No Shared Databases: Each service owns its data?
  • Bounded Contexts: Domain language consistent within boundary?
  • Anti-Corruption Layers: External systems isolated?
  • Testable: Can test each boundary independently?
  • Documented: Boundaries documented in architecture diagrams?
  • Enforced: Linting/architecture tests prevent violations?

Related Skills

  • 59-architecture-decision/adr-templates
  • 40-system-resilience/service-mesh
  • 51-contracts-governance/api-contracts