Ports and Adapters: Dependencies Point Inward

Ports and Adapters: Dependencies Point Inward An architecture diagram generated by Archify. HTTP Handler · Architecture component HTTP Handler CLI · Architecture component CLI Queue Consumer · Architecture component Queue Consumer Port: PlaceOrder · driving, named after the operation · Inside: dependencies point inward, enforced by an import linter Port: PlaceOrder driving, named after the operation Domain · no framework imports · Inside: dependencies point inward, enforced by an import linter · the whole benefit Domain no framework imports the whole benefit Port: OrderRepository · driven, domain vocabulary · Inside: dependencies point inward, enforced by an import linter Port: OrderRepository driven, domain vocabulary Port: PaymentGateway · driven, domain vocabulary · Inside: dependencies point inward, enforced by an import linter Port: PaymentGateway driven, domain vocabulary Postgres Adapter · Architecture component Postgres Adapter In-Memory Adapter · for tests · Architecture component In-Memory Adapter for tests Stripe Adapter · Architecture component Stripe Adapter driving driven driven Inside: dependencies point inward, enforced by an import linter Legend Frontend Backend Database Message bus External

Driving ports

  • • The outside world calls in
  • • Few of them, named after business operations
  • • Adding an entry point costs one adapter, not a redesign

Driven ports

  • • The interface belongs to the domain
  • • OrderRepository.findUnpaid(), not SqlClient.query()
  • • Wrap what you do not control and cannot run in a unit test

Before adding a port

  • • Name the second adapter or delete the port
  • • A test double for something slow or external counts
  • • "We might swap the database someday" does not