構成ルート
構成ルートは、具体的な実装を選んで接続するアプリケーション境界です。ドメインコードは必要な契約を示し、インフラストラクチャが実装を提供します。InferDI は組み立てコードだけに現れます。
ドメインの契約
ユースケースが依存するインターフェースはドメイン側に置きます。このファイルはコンテナーもフレームワークも import しません。
ts
export interface UserStore {
findName(id: string): Promise<string | undefined>
}
export class GetGreeting {
constructor(private readonly users: UserStore) {}
async execute(id: string) {
const name = await this.users.findName(id)
return name === undefined ? 'Hello, stranger' : `Hello, ${name}`
}
}インフラストラクチャ実装
インフラストラクチャがドメイン契約を実装します。実際のアダプターならデータベースクライアントを使いますが、この例では呼び出しを小さく保っています。
ts
import type { UserStore } from './domain'
export class PostgresUserStore implements UserStore {
constructor(private readonly dsn: string) {}
async findName(id: string) {
console.info(`query ${this.dsn} for ${id}`)
return id === '42' ? 'Ada' : undefined
}
}アプリケーションの構成
InferDI を import するのはこのファイルだけです。PostgresUserStore を選び、DSN を渡し、GetGreeting へ接続します。
ts
import { Container } from '@inferdi/inferdi'
import { GetGreeting } from './domain'
import { PostgresUserStore } from './infrastructure'
export const container = new Container()
.registerValue('dsn', 'postgres://localhost/app')
.registerClass('users', PostgresUserStore, ['dsn'])
.registerClass('greeting', GetGreeting, ['users'])登録タプルは各コンストラクターと照合されます。GetGreeting や PostgresUserStore を変更すると、古くなった配線がこの境界でエラーになります。
境界でサービスを使う
HTTP ルート、CLI コマンド、キューコンシューマーがトップレベルのサービスを解決します。業務処理は通常のメソッドを呼ぶだけです。
ts
import { container } from './container'
export async function handleUser(id: string) {
return container.get('greeting').execute(id)
}処理にリクエストやジョブの入力が必要なら、ここで子スコープを開きます。同じ境界で破棄するか、フレームワークアダプターにライフサイクルとの接続を任せてください。
ドメインを直接テストする
単体テストはコンテナーを作りません。偽の UserStore を、本番と同じ GetGreeting クラスへ渡します。
ts
import { GetGreeting, type UserStore } from './domain'
const fakeUsers: UserStore = {
async findName(id) {
return id === '42' ? 'Ada' : undefined
}
}
const service = new GetGreeting(fakeUsers)
const result = await service.execute('42')
if (result !== 'Hello, Ada') {
throw new Error(`Unexpected greeting: ${result}`)
}実際の構成グラフを動かしつつ 1 実装だけ差し替える統合テストでは .override() を使えます。単一のドメインサービスなら直接構築する方が明快です。続きはテストとオーバーライドを参照してください。
