Help us improve
Share bugs, ideas, or general feedback.
Designs, implements, and refactors hexagonal architecture (ports & adapters) with clear domain boundaries, dependency inversion, and testable use cases across TypeScript, Java, Kotlin, and Go.
npx claudepluginhub aaione/everything-claude-code-zhHow this skill is triggered — by the user, by Claude, or both
Slash command
/everything-claude-code:hexagonal-architectureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
六边形架构(端口与适配器)使业务逻辑独立于框架、传输和持久化细节。核心应用程序依赖于抽象端口,适配器在边缘实现这些端口。
Design, implement, and refactor Ports & Adapters systems with clear domain boundaries, dependency inversion, and testable use-case orchestration across TypeScript, Java, Kotlin, and Go services.
Guides implementing Hexagonal (Ports and Adapters) architecture: define ports, build adapters, enforce dependencies to isolate domain logic from infrastructure. For testable, adaptable systems.
Provides patterns, antipatterns, and PHP-specific guidelines for auditing Hexagonal Architecture (Ports & Adapters) implementations.
Share bugs, ideas, or general feedback.
六边形架构(端口与适配器)使业务逻辑独立于框架、传输和持久化细节。核心应用程序依赖于抽象端口,适配器在边缘实现这些端口。
当请求涉及边界、以域为中心的设计、重构紧密耦合的服务或将应用程序逻辑与特定库解耦时,使用此技能。
出站端口接口通常位于应用层(或仅在抽象真正是域级别时位于域中),而基础设施适配器实现它们。
依赖方向始终向内:
定义具有清晰输入和输出 DTO 的单个用例。将传输详细信息(Express req、GraphQL context、作业负载包装器)保持在此边界之外。
将每个副作用识别为端口:
UserRepositoryPort)BillingGatewayPort)LoggerPort、ClockPort)端口应建模能力,而非技术。
用例类/函数通过构造函数/参数接收端口。它验证应用程序级别的不变量,协调域规则,并返回纯数据结构。
实例化适配器,然后将其注入用例。保持此接线集中化,以避免隐藏的服务定位器行为。
flowchart LR
Client["客户端 (HTTP/CLI/Worker)"] --> InboundAdapter["入站适配器"]
InboundAdapter -->|"调用"| UseCase["用例 (应用层)"]
UseCase -->|"使用"| OutboundPort["出站端口 (接口)"]
OutboundAdapter["出站适配器"] -->|"实现"| OutboundPort
OutboundAdapter --> ExternalSystem["数据库/API/队列"]
UseCase --> DomainModel["域模型"]
使用具有显式边界的功能优先组织:
src/
features/
orders/
domain/
Order.ts
OrderPolicy.ts
application/
ports/
inbound/
CreateOrder.ts
outbound/
OrderRepositoryPort.ts
PaymentGatewayPort.ts
use-cases/
CreateOrderUseCase.ts
adapters/
inbound/
http/
createOrderRoute.ts
outbound/
postgres/
PostgresOrderRepository.ts
stripe/
StripePaymentGateway.ts
composition/
ordersContainer.ts
export interface OrderRepositoryPort {
save(order: Order): Promise<void>;
findById(orderId: string): Promise<Order | null>;
}
export interface PaymentGatewayPort {
authorize(input: { orderId: string; amountCents: number }): Promise<{ authorizationId: string }>;
}
type CreateOrderInput = {
orderId: string;
amountCents: number;
};
type CreateOrderOutput = {
orderId: string;
authorizationId: string;
};
export class CreateOrderUseCase {
constructor(
private readonly orderRepository: OrderRepositoryPort,
private readonly paymentGateway: PaymentGatewayPort
) {}
async execute(input: CreateOrderInput): Promise<CreateOrderOutput> {
const order = Order.create({ id: input.orderId, amountCents: input.amountCents });
const auth = await this.paymentGateway.authorize({
orderId: order.id,
amountCents: order.amountCents,
});
// markAuthorized 返回新的 Order 实例;它不就地修改。
const authorizedOrder = order.markAuthorized(auth.authorizationId);
await this.orderRepository.save(authorizedOrder);
return {
orderId: order.id,
authorizationId: auth.authorizationId,
};
}
}
export class PostgresOrderRepository implements OrderRepositoryPort {
constructor(private readonly db: SqlClient) {}
async save(order: Order): Promise<void> {
await this.db.query(
"insert into orders (id, amount_cents, status, authorization_id) values ($1, $2, $3, $4)",
[order.id, order.amountCents, order.status, order.authorizationId]
);
}
async findById(orderId: string): Promise<Order | null> {
const row = await this.db.oneOrNone("select * from orders where id = $1", [orderId]);
return row ? Order.rehydrate(row) : null;
}
}
export const buildCreateOrderUseCase = (deps: { db: SqlClient; stripe: StripeClient }) => {
const orderRepository = new PostgresOrderRepository(deps.db);
const paymentGateway = new StripePaymentGateway(deps.stripe);
return new CreateOrderUseCase(orderRepository, paymentGateway);
};
跨生态系统使用相同的边界规则;仅语法和接线样式更改。
application/ports/* 作为接口/类型。adapters/inbound/*、adapters/outbound/*。domain、application.port.in、application.port.out、application.usecase、adapter.in、adapter.out。application.port.* 中的接口。@Service 是可选的,非必需)。domain、application.port、application.usecase、adapter)。internal/<feature>/domain、application、ports、adapters/inbound、adapters/outbound。New... 构造函数的结构体。cmd/<app>/main.go 中接线(或专用接线包),保持构造函数显式。req、res 或队列元数据读取。