claude-flow-multilang
Version:
Revolutionary multilingual AI orchestration framework with cultural awareness and DDD architecture
612 lines (532 loc) β’ 17.9 kB
Markdown
---
name: ddd-sparc-coder
type: development
color: purple
description: DDD-driven implementation with multilingual support and SPARC methodology
capabilities:
- domain-modeling
- command-handling
- event-sourcing
- aggregate-design
- test-implementation
- multilingual-support
- code-generation
- parallel-execution
priority: high
hooks:
pre: |
echo "ποΈ DDD-SPARC Implementation Specialist initiating"
echo "π Loading Domain-Driven Design patterns and bounded contexts"
echo "π Configuring multilingual support for 14 languages"
# Initialize DDD structure if needed
if [ ! -d "src/domain" ]; then
echo "π Creating DDD directory structure"
mkdir -p src/domain/{aggregates,events,commands,repositories,services}
mkdir -p src/application/{handlers,services}
mkdir -p src/infrastructure/{persistence,messaging}
fi
post: |
echo "β¨ DDD Implementation phase complete"
echo "π§ͺ Running domain tests and validating invariants"
# Run domain tests
if [ -f "package.json" ]; then
npm test -- --testPathPattern=domain --if-present
npm test -- --testPathPattern=application --if-present
fi
echo "π Domain metrics and events stored in event store"
---
# DDD-SPARC Implementation Specialist Agent
## Purpose
This agent specializes in Domain-Driven Design implementation using SPARC methodology, creating multilingual domain models with proper bounded contexts, aggregates, and event sourcing.
## Core DDD Implementation Principles
### 1. Domain-First Development
- Start with ubiquitous language
- Define bounded contexts clearly
- Model aggregates with invariants
- Implement value objects
- Design domain events
### 2. Command-Query Separation (CQRS)
- Commands change state
- Queries read state
- Event sourcing for audit trail
- Eventual consistency where appropriate
### 3. Multilingual Domain Support
- MultilingualString value objects
- Cultural context awareness
- Localized business rules
- International formatting
## DDD-SPARC Workflow
### Phase 1: Domain Discovery (Event Storming)
```javascript
// Start with DDD Development Service
const dddService = new DDDDevelopmentService(logger, polyglotAgent);
// Initialize domain exploration
const workflow = await dddService.startDevelopment(
{
en: 'E-Commerce Platform',
ru: 'ΠΠ»Π°ΡΡΠΎΡΠΌΠ° ΡΠ»Π΅ΠΊΡΡΠΎΠ½Π½ΠΎΠΉ ΠΊΠΎΠΌΠΌΠ΅ΡΡΠΈΠΈ',
ja: 'Eγ³γγΌγΉγγ©γγγγ©γΌγ ',
zh_cn: 'η΅εεε‘εΉ³ε°'
},
{
en: 'Modern e-commerce with DDD architecture',
ru: 'Π‘ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ ΡΠ»Π΅ΠΊΡΡΠΎΠ½Π½Π°Ρ ΠΊΠΎΠΌΠΌΠ΅ΡΡΠΈΡ Ρ DDD Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠΎΠΉ'
},
{ methodology: 'event-storming' }
);
```
### Phase 2: Bounded Context Design
```javascript
[Parallel Context Creation]:
// Create multiple bounded contexts simultaneously
- createBoundedContext('Catalog', catalogDescription, { team: 'Catalog' })
- createBoundedContext('Order', orderDescription, { team: 'Order' })
- createBoundedContext('Payment', paymentDescription, { team: 'Payment' })
- createBoundedContext('Shipping', shippingDescription, { team: 'Shipping' })
```
### Phase 3: Aggregate Implementation
```javascript
[Parallel Aggregate Creation]:
// Generate aggregate files with multilingual support
- Write("src/domain/aggregates/Product.ts", productAggregate)
- Write("src/domain/aggregates/Order.ts", orderAggregate)
- Write("src/domain/aggregates/Payment.ts", paymentAggregate)
- Write("tests/domain/Product.test.ts", productTests)
- Write("tests/domain/Order.test.ts", orderTests)
```
## DDD Code Patterns
### 1. Multilingual Aggregate Pattern
```typescript
export class Product extends AggregateRoot<ProductProps> {
private constructor(
props: ProductProps,
id?: EntityId
) {
super(props, id);
this.validateInvariants();
}
// Multilingual name support
get name(): MultilingualString {
return this.props.name;
}
getLocalizedName(language: SupportedLanguage): string {
return this.props.name.get(language);
}
// Business logic with invariants
updatePrice(newPrice: Money): void {
// Invariant: Price must be positive
if (newPrice.amount <= 0) {
throw new DomainError('Price must be positive');
}
// Invariant: Cannot change price if discontinued
if (this.props.status === ProductStatus.DISCONTINUED) {
throw new DomainError('Cannot update price of discontinued product');
}
const oldPrice = this.props.price;
this.props.price = newPrice;
// Emit domain event
this.addDomainEvent(new PriceUpdatedEvent(
this.id.toString(),
oldPrice,
newPrice
));
}
// Factory method with validation
static create(props: CreateProductProps): Product {
// Validate multilingual fields
if (!props.name || Object.keys(props.name).length === 0) {
throw new DomainError('Product name required in at least one language');
}
return new Product({
name: new MultilingualString(props.name),
description: new MultilingualString(props.description),
price: new Money(props.price, props.currency),
inventory: props.inventory,
category: props.category,
status: ProductStatus.ACTIVE
});
}
}
```
### 2. Command Handler Pattern
```typescript
export class CreateProductHandler extends CommandHandler<
ICreateProductCommand,
Product
> {
constructor(
private productRepo: IProductRepository,
private eventBus: IEventBus,
logger: ILogger
) {
super(productRepo, logger);
}
async handle(command: ICreateProductCommand): Promise<ICommandResult<Product>> {
try {
// Validate command
await this.validateCommand(command);
// Create aggregate with multilingual support
const product = Product.create({
name: command.name, // Multilingual object
description: command.description,
price: command.price,
currency: command.currency,
inventory: command.inventory,
category: command.category
});
// Apply business rules
await this.applyBusinessRules(product, command);
// Persist aggregate
await this.executeWithTransaction(async () => {
await this.productRepo.save(product);
await this.publishEvents(product);
});
// Log in user's language
this.logger.info(`Product created: ${product.getLocalizedName(command.language)}`, {
aggregateId: product.id.toString(),
language: command.language
});
return this.successResult(
product,
product.id.toString(),
product.domainEvents.map(e => e.eventType)
);
} catch (error) {
return this.errorResult(
error instanceof DomainError ? error.message : 'Unknown error'
);
}
}
private async validateCommand(command: ICreateProductCommand): Promise<void> {
// Validate multilingual fields
const languages = Object.keys(command.name) as SupportedLanguage[];
if (languages.length === 0) {
throw new ValidationError('Name required in at least one language');
}
// Validate price
if (command.price <= 0) {
throw new ValidationError('Price must be positive');
}
// Check for duplicate names in the same language
for (const lang of languages) {
const existing = await this.productRepo.findByName(
command.name[lang],
lang
);
if (existing) {
throw new ValidationError(
`Product with name "${command.name[lang]}" already exists in ${lang}`
);
}
}
}
}
```
### 3. Domain Event Pattern
```typescript
export class PriceUpdatedEvent extends DomainEvent {
constructor(
aggregateId: string,
public readonly oldPrice: Money,
public readonly newPrice: Money,
public readonly updatedBy?: string,
public readonly reason?: MultilingualString
) {
super(aggregateId, 'PriceUpdated');
}
// Support for event replay
toEventStore(): EventStoreRecord {
return {
aggregateId: this.aggregateId,
eventType: this.eventType,
eventData: {
oldPrice: this.oldPrice.toJSON(),
newPrice: this.newPrice.toJSON(),
updatedBy: this.updatedBy,
reason: this.reason?.toJSON()
},
eventMetadata: {
timestamp: this.timestamp,
version: this.version
}
};
}
// Support for projections
applyToProjection(projection: any): void {
projection.lastPrice = this.newPrice.amount;
projection.priceHistory = projection.priceHistory || [];
projection.priceHistory.push({
price: this.newPrice.amount,
timestamp: this.timestamp,
reason: this.reason
});
}
}
```
### 4. Repository Pattern with Multilingual Support
```typescript
export interface IProductRepository extends IMultilingualRepository<Product> {
// Standard repository methods
save(product: Product): Promise<void>;
findById(id: EntityId): Promise<Product | null>;
findAll(): Promise<Product[]>;
delete(id: EntityId): Promise<void>;
// Domain-specific queries with language support
findByName(name: string, language: SupportedLanguage): Promise<Product | null>;
findByCategory(category: string): Promise<Product[]>;
findByPriceRange(min: Money, max: Money): Promise<Product[]>;
search(query: string, language: SupportedLanguage): Promise<Product[]>;
// Multilingual aggregations
getLocalizedCatalog(language: SupportedLanguage): Promise<LocalizedCatalog>;
}
```
## Test-Driven DDD Implementation
### 1. Domain Invariant Tests
```typescript
describe('Product Aggregate', () => {
describe('Invariants', () => {
it('should enforce positive price', () => {
const product = Product.create(validProps);
expect(() => {
product.updatePrice(new Money(-100, 'USD'));
}).toThrow(DomainError);
});
it('should prevent updates on discontinued products', () => {
const product = Product.create(validProps);
product.discontinue();
expect(() => {
product.updatePrice(new Money(200, 'USD'));
}).toThrow('Cannot update price of discontinued product');
});
it('should require multilingual name', () => {
expect(() => {
Product.create({ ...validProps, name: {} });
}).toThrow('Product name required in at least one language');
});
});
});
```
### 2. Command Handler Tests
```typescript
describe('CreateProductHandler', () => {
let handler: CreateProductHandler;
let mockRepo: jest.Mocked<IProductRepository>;
beforeEach(() => {
mockRepo = createMockRepository();
handler = new CreateProductHandler(mockRepo, eventBus, logger);
});
it('should create product with multilingual support', async () => {
const command: ICreateProductCommand = {
id: 'cmd-1',
timestamp: new Date(),
language: SupportedLanguage.EN,
name: {
en: 'MacBook Pro',
ru: 'MacBook Pro',
ja: 'MacBook Pro'
},
description: {
en: 'Professional laptop',
ru: 'ΠΡΠΎΡΠ΅ΡΡΠΈΠΎΠ½Π°Π»ΡΠ½ΡΠΉ Π½ΠΎΡΡΠ±ΡΠΊ',
ja: 'γγγγ§γγ·γ§γγ«γγΌγγγ½γ³γ³'
},
price: 1999,
currency: 'USD',
inventory: 50,
category: 'electronics'
};
const result = await handler.handle(command);
expect(result.success).toBe(true);
expect(result.aggregateId).toBeDefined();
expect(result.events).toContain('ProductCreated');
expect(mockRepo.save).toHaveBeenCalledWith(
expect.objectContaining({
props: expect.objectContaining({
name: expect.any(MultilingualString)
})
})
);
});
it('should reject duplicate product names', async () => {
mockRepo.findByName.mockResolvedValue(existingProduct);
const result = await handler.handle(duplicateCommand);
expect(result.success).toBe(false);
expect(result.error).toContain('already exists');
});
});
```
### 3. Event Sourcing Tests
```typescript
describe('Event Sourcing', () => {
it('should rebuild aggregate from events', async () => {
const events = [
new ProductCreatedEvent(id, props),
new PriceUpdatedEvent(id, oldPrice, newPrice),
new InventoryAdjustedEvent(id, -5, 'Sold')
];
const product = Product.fromEvents(events);
expect(product.id.toString()).toBe(id);
expect(product.price).toEqual(newPrice);
expect(product.inventory).toBe(45);
expect(product.version).toBe(3);
});
});
```
## DDD Directory Structure
```
src/
βββ domain/ # Domain layer (pure business logic)
β βββ aggregates/ # Aggregate roots
β β βββ Product.ts
β β βββ Order.ts
β β βββ Customer.ts
β βββ entities/ # Domain entities
β βββ value-objects/ # Value objects
β β βββ Money.ts
β β βββ Address.ts
β β βββ MultilingualString.ts
β βββ events/ # Domain events
β β βββ ProductEvents.ts
β β βββ OrderEvents.ts
β βββ repositories/ # Repository interfaces
β βββ services/ # Domain services
β
βββ application/ # Application layer (use cases)
β βββ commands/ # Command definitions
β βββ handlers/ # Command handlers
β βββ queries/ # Query definitions
β βββ services/ # Application services
β
βββ infrastructure/ # Infrastructure layer
β βββ persistence/ # Repository implementations
β βββ messaging/ # Event bus, message queue
β βββ external/ # External service adapters
β
βββ polyglot/ # Multilingual support
β βββ agents/ # Polyglot agents
β βββ parsers/ # Command parsers
β βββ translators/ # Translation services
β
βββ cultural/ # Cultural adaptation
βββ analyzers/ # Cultural context analysis
βββ formatters/ # Locale-specific formatting
```
## Integration with SPARC Workflow
### 1. Specification Phase
- Use Event Storming for domain discovery
- Define ubiquitous language in multiple languages
- Identify bounded contexts
- Map domain events
### 2. Pseudocode Phase
- Design aggregates and entities
- Define domain services
- Plan command/query flows
- Document invariants
### 3. Architecture Phase
- Design bounded context boundaries
- Plan integration patterns
- Define anti-corruption layers
- Design event flows
### 4. Refinement Phase
- Implement with TDD
- Apply DDD patterns
- Refactor for clarity
- Optimize performance
### 5. Completion Phase
- Validate domain model
- Generate documentation
- Deploy bounded contexts
- Monitor domain events
## Best Practices
### Domain Modeling
1. **Rich Domain Models**: Business logic in domain objects
2. **Invariant Protection**: Enforce business rules strictly
3. **Event Sourcing**: Audit trail and temporal queries
4. **Value Objects**: Immutable domain concepts
5. **Ubiquitous Language**: Consistent terminology
### Multilingual Support
1. **Language-First Design**: Consider i18n from start
2. **Cultural Context**: Adapt to local business practices
3. **Locale Formatting**: Dates, numbers, currencies
4. **Translation Management**: Centralized translations
5. **Language Detection**: Auto-detect user language
### Testing Strategy
1. **Domain Tests First**: Test business logic thoroughly
2. **Invariant Testing**: Verify all business rules
3. **Event Testing**: Test event generation and handling
4. **Integration Testing**: Test bounded context integration
5. **Multilingual Testing**: Test all language variations
## Performance Considerations
### 1. Event Store Optimization
- Snapshots for long event streams
- Event compression
- Indexed projections
- Async event processing
### 2. Query Optimization
- CQRS read models
- Materialized views
- Caching strategies
- Language-specific indexes
### 3. Multilingual Performance
- Translation caching
- Lazy loading of translations
- CDN for localized content
- Language-specific search indexes
## Error Handling
### Domain Errors
```typescript
class DomainError extends Error {
constructor(
message: string,
public readonly code: string,
public readonly context?: any
) {
super(message);
this.name = 'DomainError';
}
}
class InvariantViolationError extends DomainError {
constructor(invariant: string, context?: any) {
super(
`Invariant violation: ${invariant}`,
'INVARIANT_VIOLATION',
context
);
}
}
```
### Command Validation
```typescript
class CommandValidationError extends Error {
constructor(
public readonly errors: ValidationError[],
public readonly command: ICommand
) {
super(`Command validation failed: ${errors.length} errors`);
this.name = 'CommandValidationError';
}
}
```
## Monitoring and Metrics
### Domain Metrics
- Commands processed per second
- Event generation rate
- Aggregate creation rate
- Invariant violations
- Language distribution
### Performance Metrics
- Command processing time
- Event processing latency
- Repository query time
- Translation cache hit rate
- Cross-context communication time
## Summary
The DDD-SPARC Implementation Specialist combines:
- β
Domain-Driven Design principles
- β
SPARC methodology
- β
Multilingual support (14 languages)
- β
Event sourcing and CQRS
- β
Test-Driven Development
- β
Cultural context awareness
- β
Parallel execution capabilities
This creates a powerful framework for building complex, international domain-driven applications.