{
    "slug": "gateway_pattern",
    "term": "Gateway Pattern",
    "category": "quality",
    "difficulty": "intermediate",
    "short": "A class that encapsulates access to an external system or resource — wrapping HTTP APIs, queues, or legacy systems behind a clean interface that the rest of the application uses.",
    "long": "A Gateway (Martin Fowler, PoEAA) isolates external dependencies behind an interface. PaymentGateway, EmailGateway, SMSGateway — each wraps one external system. Benefits: the application code never calls the HTTP client or SDK directly; the gateway can be mocked in tests; switching providers means only changing the gateway implementation. Similar to Adapter but typically wraps external systems rather than incompatible interfaces. Distinguished from Repository (data storage) by focusing on external service calls.",
    "aliases": [
        "service gateway",
        "API wrapper",
        "external service adapter"
    ],
    "tags": [
        "patterns",
        "oop",
        "design",
        "testing"
    ],
    "misconception": "Gateways and adapters are the same — both wrap external interfaces, but a Gateway specifically wraps access to external systems (APIs, queues); an Adapter translates between two existing interfaces.",
    "why_it_matters": "Without a gateway, Stripe's SDK is called directly throughout the codebase — switching to Braintree requires hunting down every Stripe call; with a gateway, only one class changes.",
    "common_mistakes": [
        "Gateway that leaks provider-specific exceptions — wrap them in domain exceptions.",
        "Fat gateway with too much logic — gateways translate calls, not implement business rules.",
        "Not defining a gateway interface — without an interface, mocking in tests requires more work.",
        "One giant ExternalServiceGateway — one gateway per external system."
    ],
    "when_to_use": [],
    "avoid_when": [],
    "related": [
        "adapter_pattern",
        "repository_pattern",
        "dependency_injection",
        "strategy_pattern"
    ],
    "prerequisites": [
        "adapter_pattern",
        "dependency_injection",
        "interfaces"
    ],
    "refs": [
        "https://www.martinfowler.com/eaaCatalog/gateway.html"
    ],
    "bad_code": "// No gateway — Stripe SDK scattered everywhere:\nclass OrderService {\n    public function charge(Order $order): void {\n        $stripe = new \\Stripe\\StripeClient(getenv('STRIPE_KEY'));\n        $charge = $stripe->charges->create([\n            'amount'   => $order->total->cents(),\n            'currency' => 'gbp',\n            'source'   => $order->paymentToken,\n        ]);\n        // Stripe-specific code in domain service\n    }\n}",
    "good_code": "// Gateway isolates the provider:\ninterface PaymentGateway {\n    public function charge(Money $amount, string $token): PaymentResult;\n}\n\nclass StripeGateway implements PaymentGateway {\n    public function charge(Money $amount, string $token): PaymentResult {\n        $charge = $this->stripe->charges->create([...]);\n        return new PaymentResult($charge->id, $charge->status);\n    }\n}\n\n// Domain service depends on interface:\nclass OrderService {\n    public function __construct(private PaymentGateway $payments) {}\n    public function charge(Order $order): void {\n        $result = $this->payments->charge($order->total, $order->token);\n    }\n}",
    "quick_fix": "Create a Gateway class as the single entry point to an external system — all HTTP calls, data mapping, and error handling live in the gateway, keeping your domain code clean",
    "severity": "medium",
    "effort": "medium",
    "created": "2026-03-16",
    "updated": "2026-03-22",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/gateway_pattern",
        "html_url": "https://codeclaritylab.com/glossary/gateway_pattern",
        "json_url": "https://codeclaritylab.com/glossary/gateway_pattern.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Gateway Pattern](https://codeclaritylab.com/glossary/gateway_pattern) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/gateway_pattern"
            }
        }
    }
}