ワンクリックで
service-implementation
Implement Effect services as fine-grained capabilities avoiding monolithic designs
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Implement Effect services as fine-grained capabilities avoiding monolithic designs
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
Implement reactive state management with Effect Atom for React applications
Decide between Context Tag witness and capability patterns for dependency injection, understanding coupling trade-offs
Generate comprehensive predicates and orders for domain types using typeclass patterns
Design and compose Effect layers for clean dependency management
Implement typeclasses with curried signatures and dual APIs for both data-first and data-last usage
SOC 職業分類に基づく
| name | service-implementation |
| description | Implement Effect services as fine-grained capabilities avoiding monolithic designs |
Design and implement Effect services as focused capabilities that compose into complete solutions.
// ❌ WRONG - Mixed concerns in one service
export class PaymentService extends Context.Tag("PaymentService")<
PaymentService,
{
readonly processPayment: ...
readonly validateWebhook: ...
readonly refund: ...
readonly sendReceipt: ... // Notification concern
readonly generateReport: ... // Reporting concern
}
>() {}
Each service represents ONE cohesive capability:
// ✅ CORRECT - Focused capabilities
export class PaymentGateway extends Context.Tag(
"@services/payment/PaymentGateway"
)<
PaymentGateway,
{
readonly handoff: (
intent: Doc<"paymentIntents">
) => Effect.Effect<HandoffResult, HandoffError, never>
// ▲
// No requirements leaked
}
>() {}
export class PaymentWebhookGateway extends Context.Tag(
"@services/payment/PaymentWebhookGateway"
)<
PaymentWebhookGateway,
{
readonly validateWebhook: (
payload: WebhookPayload
) => Effect.Effect<void, WebhookValidationError, never>
}
>() {}
export class PaymentRefundGateway extends Context.Tag(
"@services/payment/PaymentRefundGateway"
)<
PaymentRefundGateway,
{
readonly refund: (
paymentId: PaymentId,
amount: Cents
) => Effect.Effect<RefundResult, RefundError, never>
}
>() {}
Service operations should never have requirements:
// The service interface stays clean
export class Database extends Context.Tag("Database")<
Database,
{
readonly query: (
sql: string
) => Effect.Effect<QueryResult, QueryError, never>
// ▲
// Requirements = never
}
>() {}
Dependencies are handled during layer construction, not in the service interface:
// Dependencies live in the layer
export const DatabaseLive = Layer.effect(
Database,
Effect.gen(function* () {
const config = yield* Config // Dependency
const logger = yield* Logger // Dependency
return Database.of({
query: (sql) =>
Effect.gen(function* () {
yield* logger.log(`Executing: ${sql}`)
const { connection } = yield* config.getConfig
return executeQuery(connection, sql)
})
})
})
)
Different implementations support different capabilities:
// Cash payments: Basic handoff only
export const CashGatewayLive = Layer.succeed(
PaymentGateway,
PaymentGateway.of({
handoff: (intent) => fulfillCashPayment(intent)
})
)
// Stripe: Full capability suite
export const StripeGatewayLive = Layer.mergeAll(
StripeHandoffLive, // Implements PaymentGateway
StripeWebhookLive, // Implements PaymentWebhookGateway
StripeRefundLive // Implements PaymentRefundGateway
)
Use Effect.serviceOption for capabilities that may not be available:
const processPayment = (order: Order) =>
Effect.gen(function* () {
const handoff = yield* PaymentGateway
const result = yield* handoff.handoff(order.paymentIntent)
// Optional capability - check if available
const refundGateway = yield* Effect.serviceOption(PaymentRefundGateway)
if (Option.isSome(refundGateway)) {
yield* setupRefundPolicy(refundGateway.value, order)
}
return result
})
Each capability can be tested in isolation:
const TestWebhook = Layer.succeed(
PaymentWebhookGateway,
PaymentWebhookGateway.of({
validateWebhook: (payload) =>
payload.signature === "valid"
? Effect.succeed(undefined)
: Effect.fail(new WebhookValidationError({ reason: "Invalid" }))
})
)
// Test only webhook validation, no other payment concerns
const testProgram = handleWebhook(payload).pipe(
Effect.provide(TestWebhook)
)
Use descriptive capability names:
*Gateway - External system integration*Repository - Data persistence*Domain - Business logic*Service - General capability (use sparingly)Tag identifiers should include namespace:
"@services/payment/PaymentGateway""@repositories/user/UserRepository""@domain/order/OrderDomain"Keep services focused, composable, and free of leaked requirements.