



























This document outlines a five-phase migration from a monolithic Express API (all logic in one file) to a clean layered architecture with separate concerns: HTTP routes, business services, and data access repositories.
Current State: src/routes.ts contains ~150 lines mixing HTTP handling, validation, and database access.
Target State: Clean layered architecture with routes → services → repositories → database.
Migration Time: 2-3 hours (depending on AI agent efficiency)
Risk Level: Medium (can be rolled back at each phase boundary)
Goal: Create file structure and type definitions. No implementation yet.
src/refactored/types.ts — Shared type definitions
export class AppError extends Error {
constructor(public code: string, message: string, public statusCode: number = 500) {
super(message);
}
}
export class ValidationError extends AppError {
constructor(message: string) {
super('VALIDATION_ERROR', message, 400);
}
}
export class NotFoundError extends AppError {
constructor(resource: string, id: string) {
super('NOT_FOUND', `${resource} ${id} not found`, 404);
}
}
export interface ServiceResult<T> {
data: T | null;
error: AppError | null;
}
src/refactored/repositories/ — Data access layer
user-repository.ts — User data accessorder-repository.ts — Order data accesssrc/refactored/services/ — Business logic layer
user-service.ts — User business logicorder-service.ts — Order business logicsrc/refactored/routes/ — HTTP handlers
user-routes.ts — User endpointsorder-routes.ts — Order endpointsgit commit -m "phase-1: scaffold new architecture with types and directory structure"
Goal: Create data access abstraction. Move all database queries to repositories.
interface UserRepository {
findAll(): Promise<User[]>;
findById(id: string): Promise<User | null>;
create(data: Omit<User, 'id'>): Promise<User>;
update(id: string, data: Partial<User>): Promise<User>;
delete(id: string): Promise<void>;
}
Similar pattern for orders.
src/routes.ts still has the old handlersgit commit -m "phase-2: extract repository layer for data access"
Goal: Move business logic from routes into services.
interface UserService {
getAllUsers(): Promise<User[]>;
getUserById(id: string): Promise<ServiceResult<User>>;
createUser(name: string, email: string): Promise<ServiceResult<User>>;
updateUser(id: string, name: string, email: string): Promise<ServiceResult<User>>;
deleteUser(id: string): Promise<ServiceResult<void>>;
}
Similar pattern for orders.
ValidationError for invalid inputNotFoundError for missing resourcesgit commit -m "phase-2a: user repository implementation"
git commit -m "phase-2b: order repository implementation"
git commit -m "phase-3a: user service implementation"
git commit -m "phase-3b: order service implementation"
Goal: Comprehensive test coverage for services and routes.
tests/unit/services/
user-service.test.ts
order-service.test.ts
Test cases:
tests/integration/routes/
user-routes.test.ts
order-routes.test.ts
Test cases:
git commit -m "phase-4a: unit tests for services"
git commit -m "phase-4b: integration tests for routes"
Goal: Update routes to use new services, remove old code.
npm test # All tests pass
npm run build # Clean build, no errors
npm run lint # No warnings
git log # Five clean commits
git commit -m "phase-5: migrate routes to service layer and remove old code"
If a phase fails:
git revert [phase-2-commit]; fix typesgit revert [phase-3-commit]; fix architecturegit revert [phase-5-commit]; fix routesAlways commit after each phase so rollback is clean.
After Phase 5:
Total: ~2 hours
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。