Structural Complexity: Low

Facade in Go

Provide one simplified entry point over several collaborating subsystems so callers can trigger a workflow without knowing every step.

The Problem

Order placement often touches multiple services such as inventory, billing, and shipping. If every handler coordinates those services directly, the workflow gets repeated in many places and callers become coupled to low-level sequencing details.

The Solution

Facade introduces a higher-level API over a cluster of subsystems. In Go, it is usually a simple service struct with a method that orchestrates the underlying collaborators. The facade does not hide the subsystems from existence; it just gives common workflows a more coherent entry point.

Structure

  • Subsystems: Inventory, billing, and shipping services expose low-level operations.
  • Facade: OrderFacade coordinates the workflow in one place.
  • Client: Calls the simplified facade method instead of orchestrating the subsystems manually.

Implementation

This example wraps reservation, charging, and shipment scheduling behind a single PlaceOrder method. The handler-level caller only cares about the outcome of the business workflow.

package main

type InventoryService struct {
	stock map[string]int
}

func NewInventoryService() InventoryService {
	return InventoryService{stock: map[string]int{"KB-001": 12}}
}

func (s *InventoryService) Reserve(sku string, qty int) bool {
	available := s.stock[sku]
	if available < qty {
		return false
	}
	s.stock[sku] = available - qty
	return true
}

Best Practices

  • Keep the facade aligned with business workflows instead of turning it into a generic god object.
  • Expose lower-level services directly where advanced use cases need them. A facade should simplify, not imprison.
  • Inject the subsystems so orchestration can be tested without real infrastructure.
  • Use a facade to remove repeated sequencing logic, not to hide every dependency automatically.
  • Model failures explicitly because orchestration code is where partial-success bugs tend to surface.

When to Use

  • A workflow repeatedly coordinates several subsystems in the same order.
  • Callers should depend on one business-oriented entry point instead of many low-level services.
  • You want to make common use cases obvious without deleting the lower-level APIs.

When NOT to Use

  • There is no stable workflow to simplify.
  • The facade would just forward one method to one dependency without adding clarity.
  • You are using it to hide poor subsystem boundaries rather than fixing them.