liveBook · Manning

Service handle pattern

As explained in Functional Design and Architecture: Examples in Haskell

The Service Handle pattern represents access to a service through an explicit handle that encapsulates the service interaction boundary.

The Service Handle pattern represents a subsystem as an explicit value whose fields are operations. Client code receives that handle as a dependency and calls its small, high-level interface instead of reaching into implementation modules. The boundary makes dependencies visible, keeps implementation details behind the interface, and permits replacement without changing clients. section 4.2.2 section 4.3

Use a handle where a subsystem has accumulated many external relations or where business logic must not depend on infrastructure details. Keep the interface concise, accurate, and minimal; external code should use it rather than bypassing it. This supports low coupling, single responsibility, maintainability, and isolated testing with mocks or fakes. section 4.2.3 section 4.3

A handle is a record of operations

A greetings handle can expose both a pure greeting function and an effectful greeting function. Different handle values implement the same fields differently, while helloUser accepts the handle and selects the operation it needs. Injecting handle1 or handle2 changes behavior at composition time, not inside helloUser. section 4.2.2

Listing 13.6 Service Handle interface
data AstroServiceHandle = AstroServiceHandle
  { meteorReporter
        :: MeteorTemplate
        -> AppL (Either ReportingError MeteorId)     #1
  , asteroidReporter
        :: AsteroidTemplate
        -> AppL (Either ReportingError AsteroidId)   #2
  }

An API-like handle groups reporting operations into one algebraic data type; each field returns either a domain reporting error or an identifier. section 13.2.2

A hardware handle can hide device construction and lookup behind operations such as makeDevice, getBlankDevice, and getDevicePart. An implementation can be assembled from vendor components, and a test can call the same handle interface. Handles often abstract effects through impure methods, though they can also contain pure operations. section 4.2.3 section 4.2.3

For dependency inversion, construct the handle at the application boundary and pass it to business logic. A reporting handle can select TCP or HTTP implementations from configuration, while the application depends only on reporting operations and its ReportingError type. Networking and resource management remain outside the handle consumer. section 13.2.2

Choose this pattern when the service is primarily an API-like collection of distinct operations:

  • Inject a handle directly when clients need explicit dependencies and independently callable service methods. section 13.2.2
  • Consider ReaderT when a handle must be carried through a Reader environment as an advanced variation. section 13.3
  • Use scenario-like or other functional interfaces when sequential scripts or different interface shapes are required. section 13.2

How Functional Design and Architecture: Examples in Haskell covers it

How deep it goes
Defines handles as algebraic data types of functions, then works through injection, vendor assembly, mocks, and configuration-selected implementations.
Examples
Uses greetings functions, a hardware subsystem with vendor components, and meteor reporting over TCP or HTTP.
What it assumes
Uses first-class functions and algebraic data types while introducing the handle itself as the simplest functional interface.
What you can do after
Apply it via injected handles to replace implementations, isolate tests with mocks or fakes, and keep clients independent of infrastructure.
How it connects
Connects dependency inversion, functional interfaces, mocking, ReaderT, free monads, GADTs, final tagless, and the single-responsibility principle.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Design and Architecture: Examples in Haskell. The section links point to the parts of the book it draws on.