Loading skill
Install any skill in seconds. Free to start, no credit card required.
Get Started Free →ヘキサゴナルアーキテクチャ(ポート・アダプタパターン)、境界の分離、および外部依存関係の管理。
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 61% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 124% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 96% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 149% | 0% |
| case-22 | ✗→✓ | ▲ Improved | 68% | 0% |
六边形架构(端口与适配器)使业务逻辑独立于框架、传输层和持久化细节。核心应用依赖于抽象端口,而适配器在边缘实现这些端口。
当需求涉及边界、领域驱动设计、重构紧耦合服务,或将应用逻辑与特定库解耦时,使用此技能。
出站端口接口通常位于应用层(仅当抽象真正属于领域层时才位于领域层),而基础设施适配器实现它们。
依赖方向始终向内:
定义具有清晰输入和输出DTO的单个用例。将传输细节(Express req、GraphQL context、任务负载包装器)保持在此边界之外。
将每个副作用识别为端口:
UserRepositoryPort)BillingGatewayPort)LoggerPort、ClockPort)端口应建模能力,而非技术。
用例类/函数通过构造函数/参数接收端口。它验证应用层不变量,协调领域规则,并返回纯数据结构。
实例化适配器,然后将其注入用例。保持此连接集中化,以避免隐藏的服务定位器行为。
mermaidflowchart LR Client["Client (HTTP/CLI/Worker)"] --> InboundAdapter["Inbound Adapter"] InboundAdapter -->|"calls"| UseCase["UseCase (Application Layer)"] UseCase -->|"uses"| OutboundPort["OutboundPort (Interface)"] OutboundAdapter["Outbound Adapter"] -->|"implements"| OutboundPort OutboundAdapter --> ExternalSystem["DB/API/Queue"] UseCase --> DomainModel["DomainModel"]
使用以功能为先的组织方式,并带有显式边界:
textsrc/ 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
typescriptexport 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 }>; }
typescripttype 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 returns a new Order instance; it does not mutate in place. const authorizedOrder = order.markAuthorized(auth.authorizationId); await this.orderRepository.save(authorizedOrder); return { orderId: order.id, authorizationId: auth.authorizationId, }; } }
typescriptexport 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; } }
typescriptexport 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 或队列元数据读取。Other measured skills in the registry, with their headline benchmark lift.