Skip to main content

separating-business-logic

Separates code into domain, application, and infrastructure layers so business rules stay framework-free and testable. Use when designing a new feature, splitting a god service, or moving rules out of controllers.

Quellinformationen

Repository
j4flmao/agent_skills_nodejs_nestjs
Letzte Quellaktivität
3. Mai 2026 um 03:46
Erkannte Sprache von SKILL.md
Englisch
Sterne
1
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
4 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
separating-business-logic
description
Separates code into domain, application, and infrastructure layers so business rules stay framework-free and testable. Use when designing a new feature, splitting a god service, or moving rules out of controllers.
license
MIT
# Separating Business Logic ## When to use - Designing a new feature from scratch - Splitting a god service into layers - Moving business rules out of controllers or infrastructure ## Core rules 1. **Domain layer**: Pure business rules, no framework, no I/O, no `console.log` 2. **Application layer**: Use-cases orchestrate domain + ports, no HTTP/DB direct 3. **Infrastructure layer**: Adapters for HTTP, DB, 3rd-party, implements ports 4. Controllers/handlers: only parse input, call one use-case, map Result to response 5. Domain entities contain invariants (rules that must always hold) and behavior ## Reference shape (TypeScript) ### Domain Entity ```typescript export class Order { private constructor( private readonly _id: string, private _items: OrderItem[], private _status: OrderStatus ) {} addItem(item: OrderItem): void { if (this._status !== 'draft') throw new BusinessError('INVALID_STATE', 'Cannot modify non-draft order'); this._items.push(item); } submit(): void { if (this._items.length === 0) throw new BusinessError('EMPTY_ORDER', 'Cannot submit empty order'); this._status = 'submitted'; } } ``` ### Application Use-Case ```typescript export class SubmitOrderUseCase { constructor( private readonly orderRepo: OrderRepository, private readonly paymentService: PaymentService ) {} async execute(orderId: string): Promise<Result<Order, AppError>> { const order = await this.orderRepo.findById(orderId); if (!order) return err(new NotFoundError('Order', orderId)); try { order.submit(); await this.orderRepo.save(order); return ok(order); } catch (e) { return err(e as AppError); } } } ``` ## Examples — Don't ```typescript // ❌ Controller with business logic @Post('order') createOrder(@Body() body: any) { if (body.items.length === 0) return { error: 'Empty' }; // Business rule in controller! return this.db.save(body); } ``` ## Checklist - [ ] Domain has no imports from infra or framework - [ ] Use-cases return `Result<T,E>` - [ ] Controllers only parse, call use-case, map response - [ ] Infrastructure implements ports, not vice versa See [reference/layer-examples.md](./reference/layer-examples.md) for full examples.
Auf GitHub ansehen