Skip to content

Latest commit

 

History

History
70 lines (56 loc) · 2.05 KB

File metadata and controls

70 lines (56 loc) · 2.05 KB
title Model Dependencies as Services
id model-dependencies-as-services
skillLevel intermediate
applicationPatternId making-http-requests
summary Abstract external dependencies and capabilities into swappable, testable services using Effect's dependency injection system.
tags
service
architecture
dependency-injection
layers
testing
decoupling
rule
description
Model dependencies as services.
related
define-service-with-effect-service
use-default-layer-for-tests
author Sandro Maglione
lessonOrder 6

Model Dependencies as Services

Guideline

Represent any external dependency or distinct capability—from a database client to a simple UUID generator—as a service.

Rationale

This pattern is the key to testability. It allows you to provide a Live implementation in production and a Test implementation (returning mock data) in your tests, making your code decoupled and reliable.

Good Example

import { Effect } from "effect";

// Define Random service with production implementation as default
export class Random extends Effect.Service<Random>()("Random", {
  // Default production implementation
  sync: () => ({
    next: Effect.sync(() => Math.random()),
  }),
}) {}

// Example usage
const program = Effect.gen(function* () {
  const random = yield* Random;
  const value = yield* random.next;
  return value;
});

// Run with default implementation
const programWithLogging = Effect.gen(function* () {
  const value = yield* Effect.provide(program, Random.Default);
  yield* Effect.log(`Random value: ${value}`);
  return value;
});

Effect.runPromise(programWithLogging);

Explanation:
By modeling dependencies as services, you can easily substitute mocked or deterministic implementations for testing, leading to more reliable and predictable tests.

Anti-Pattern

Directly calling external APIs like fetch or using impure functions like Math.random() within your business logic. This tightly couples your logic to a specific implementation and makes it difficult to test.