🧩 フィーチャー
フィーチャーは、スキーマと1つ以上のルートをグループ化する便利なラッパーです。サービスファクトリを簡潔に保ちながら、複雑な動作を構成できます。
1️⃣ 構造
フィーチャーはcompose
関数を使用して構成されます。この関数は複数のコンポーネント(スキーマ、ルート、または他のフィーチャー)を受け取り、それらを単一の構成可能なユニットに結合します。このコンポジションパターンにより、シンプルで再利用可能な部品から複雑な機能を構築できます。
src/features/user.ts
import { compose } from '../primitives';
import { createUserSchema, updateUserSchema } from '../schemas/user';
import { createUserRoute, getUserRoute, findUsersRoute, updateUserRoute } from '../routes/user';
export const createUserFeature = compose(createUserSchema, createUserRoute);
export const getUserFeatures = compose(getUserRoute, findUsersRoute);
export const editUserFeatures = compose(updateUserSchema, updateUserRoute);
compose
は任意の数の引数(スキーマ、ルート、さらには他のフィーチャー)を単一のComposableオブジェクトにフラット化し、サービスが消費できるようにします。コンポジションの順序は重要です - 通常、スキーマが最初に構成され、ルート実行前に検証が行われることを保証します。
2️⃣ フィーチャーを使用する理由
- 再利用性 – 複数のサービス間で同じフィーチャーを共有
- オーバーライド対応 – 下流アプリでフィーチャーを置換または拡張
- 明確性 – フィーチャー内で低レベルの詳細を隠蔽
3️⃣ 良いプラクティス
- 単一責任 – 作成、読み取り、更新、削除で別々のフィーチャーを作成
- 一貫した命名 –
<動詞><エンティティ>Feature(s)
は発見を助ける - スキーマを最初に構成 – 検証は常にルート実行に先立つべき
4️⃣ サービスでの使用
フィーチャーはdefService
関数を通じてサービスに消費されます。この関数は、構成されたフィーチャーに必要なコンテキスト(データベース接続など)を提供します。Ramdaのpartial
関数を使用してデータベース設定を事前適用し、Expressアプリケーションに簡単に統合できるサービスファクトリを作成します。
src/services/user.ts
import { compose, defService } from '../primitives';
import { partial } from 'lodash';
import { createUserFeature, getUserFeatures, editUserFeatures } from '../features/user';
export const userService = (db: any, configuration: any) =>
defService(
partial(
compose(editUserFeatures, getUserFeatures, createUserFeature),
{ dataStores: db, configuration }
)
);
このパターンにより、テスト、保守、拡張が容易なクリーンでモジュラーなサービスを作成できます。サービスファクトリパターンは、データベース接続やその他の依存関係がフィーチャーに適切に注入されることを保証します。
🎯 フィーチャーコンポジションの例
基本フィーチャー
// 単一操作フィーチャー
export const createUserFeature = compose(
createUserSchema,
createUserRoute
);
export const getUserFeature = compose(
getUserRoute
);
複合フィーチャー
// 複数操作を組み合わせたフィーチャー
export const userManagementFeature = compose(
createUserFeature,
getUserFeature,
updateUserFeature,
deleteUserFeature
);
高度なフィーチャー
// 認証を含む複雑なフィーチャー
export const authenticatedUserFeature = compose(
authenticationMiddleware,
userValidationSchema,
getUserByIdRoute,
userAccessValidation
);
📋 フィーチャーのベストプラクティス
1. 論理的なグループ化
関連する操作をまとめてグループ化:
// 良い - 関連操作のグループ化
export const userAccountFeatures = compose(
createAccountRoute,
activateAccountRoute,
deactivateAccountRoute
);
// 悪い - 無関係な操作の混在
export const mixedFeatures = compose(
createUserRoute,
sendEmailRoute,
generateReportRoute
);
2. 再利用可能な設計
// 再利用可能なベースフィーチャー
export const baseCrudFeature = (entitySchema, entityRoutes) =>
compose(entitySchema, ...entityRoutes);
// 特定エンティティ用の拡張
export const userCrudFeature = baseCrudFeature(userSchema, userRoutes);
export const productCrudFeature = baseCrudFeature(productSchema, productRoutes);
3. 明確な命名規則
// 一貫した命名パターン
export const createUserFeature = compose(/* ... */);
export const readUserFeature = compose(/* ... */);
export const updateUserFeature = compose(/* ... */);
export const deleteUserFeature = compose(/* ... */);
➡️ 次へ
サービスコンポーネントについて学習して、フィーチャーが完全なサービスにどのように構成されるかを理解しましょう。すべてのサービスは同じパターンと規約に従います!