Hexagonal Architecture Review Skill
When to Use
Invoke this skill when reviewing code for hexagonal architecture compliance, evaluating ports and adapters design, or assessing separation of concerns between core domain and external systems.
Core Concepts
Ports
Interfaces that define how the application core communicates with the outside world. They specify a protocol/contract without committing to implementation details.
Key Properties:
- Define abstract API for communication
- Can be implemented by any suitable technical means
- Protocol depends on purpose (method calls, RPC, web services)
Adapters
The glue between components and the external world. They translate between external systems and the ports defined by the application core.
Key Properties:
- Multiple adapters can implement one port
- Adapters are interchangeable without changing core logic
- Examples: GUI, CLI, test scripts, automated data sources
Review Checklist
Port Design
| Check |
Question |
| Abstraction |
Is the port defined as an interface, not a concrete implementation? |
| Independence |
Can the port be implemented without knowing specific technology? |
| Completeness |
Does the port define all operations needed by the core? |
| Minimalism |
Does the port avoid exposing unnecessary details? |
Adapter Design
| Check |
Question |
| Translation |
Does the adapter translate between external format and domain model? |
| Isolation |
Is external system logic contained entirely within the adapter? |
| Swappability |
Can this adapter be replaced without modifying core logic? |
| Testability |
Can the adapter be mocked for testing the core? |
Architecture Boundaries
| Layer |
Should Contain |
Should NOT Contain |
| Domain/Core |
Business logic, entities, use cases |
Framework code, I/O, external dependencies |
| Ports |
Interfaces/abstractions |
Implementation details |
| Adapters |
External integrations, translations |
Business logic |
| Infrastructure |
Concrete implementations, configs |
Domain rules |
Common Ports
| Port Type |
Purpose |
Example Interface |
| Database |
Data persistence operations |
Repository interface for CRUD |
| HTTP |
Handle incoming HTTP requests |
Handler interface for request processing |
| Messaging |
Message broker communication |
Publisher/Subscriber interfaces |
| Filesystem |
File I/O operations |
FileStore interface for read/write |
| Authentication |
User identity verification |
Authenticator interface |
| Payment Gateway |
Payment processing |
PaymentProcessor interface |
Common Adapters
| Adapter Type |
Translates Between |
Example |
| Database |
Domain model ↔ Database schema |
SQLAlchemy, GORM, SQLx |
| REST API |
HTTP requests ↔ Domain commands |
Chi handlers, Gin controllers |
| Message Queue |
Domain events ↔ Queue messages |
RabbitMQ, Kafka clients |
| CLI |
Command-line args ↔ Domain commands |
Cobra, Click |
| Filesystem |
Domain data ↔ File formats |
Local/cloud storage clients |
| Email |
Domain events ↔ Email messages |
SMTP, SendGrid adapters |
| GUI |
User interactions ↔ Domain events |
GTK, Qt, React |
Reference Directory Structure
my-app/
├── cmd/
│ └── server/
│ └── main.go # Entry point, wiring
│
├── internal/
│ ├── config/
│ │ └── config.go # Configuration handling
│ │
│ ├── app/
│ │ └── application.go # Application service interface
│ │
│ ├── domain/
│ │ ├── model/
│ │ │ └── entity.go # Domain entities (CORE)
│ │ └── repository/
│ │ └── repository.go # Repository interfaces (PORTS)
│ │
│ ├── usecase/
│ │ └── usecase.go # Use case implementations (CORE)
│ │
│ ├── interfaces/ # ADAPTERS (Driving/Primary)
│ │ ├── rest/
│ │ │ └── controller.go # REST controller
│ │ └── cli/
│ │ └── cli.go # CLI interface
│ │
│ └── infrastructure/ # ADAPTERS (Driven/Secondary)
│ ├── db/
│ │ ├── db.go # Database implementation
│ │ └── migration/
│ ├── http/
│ │ ├── handler/
│ │ └── router.go
│ └── logger/
│
└── pkg/
└── util/ # Shared utilities
Red Flags
Architecture Violations
| Violation |
Symptom |
Fix |
| Leaky Abstraction |
Port exposes database-specific types (e.g., sql.Row) |
Use domain types in port interface |
| Core Depends on Framework |
Domain imports HTTP/DB packages |
Inject dependencies via ports |
| Adapter Contains Logic |
Business rules in handler/repository |
Move logic to use case layer |
| Missing Port |
Core directly calls external service |
Extract interface, create port |
| God Adapter |
Single adapter handles multiple concerns |
Split into focused adapters |
Dependency Direction
WRONG: Domain → Infrastructure
(core imports database package)
RIGHT: Infrastructure → Domain
(adapter implements domain interface)
Quick Reference
| Question |
Expected Answer |
| Can I swap the database without changing business logic? |
Yes, via repository port |
| Can I test use cases without a real database? |
Yes, with mock adapter |
| Does the domain layer import external packages? |
No, only standard library |
| Are external systems abstracted behind interfaces? |
Yes, as ports |
| Can I add a CLI without modifying existing code? |
Yes, new adapter for existing port |
1---2name: hexagonal-review3description: Hexagonal architecture standards. Use when writing, generating, or reviewing code involving ports, adapters, or layer boundaries.4---5
6# Hexagonal Architecture Review Skill
7
8## When to Use
9Invoke this skill when reviewing code for hexagonal architecture compliance, evaluating ports and adapters design, or assessing separation of concerns between core domain and external systems.
10
11## Core Concepts
12
13### Ports
14Interfaces that define how the application core communicates with the outside world. They specify a protocol/contract without committing to implementation details.
15
16**Key Properties:**
17- Define abstract API for communication
18- Can be implemented by any suitable technical means
19- Protocol depends on purpose (method calls, RPC, web services)
20
21### Adapters
22The glue between components and the external world. They translate between external systems and the ports defined by the application core.
23
24**Key Properties:**
25- Multiple adapters can implement one port
26- Adapters are interchangeable without changing core logic
27- Examples: GUI, CLI, test scripts, automated data sources
28
29---
30
31## Review Checklist
32
33### Port Design
34
35| Check | Question |
36|-------|----------|
37| **Abstraction** | Is the port defined as an interface, not a concrete implementation? |
38| **Independence** | Can the port be implemented without knowing specific technology? |
39| **Completeness** | Does the port define all operations needed by the core? |
40| **Minimalism** | Does the port avoid exposing unnecessary details? |
41
42### Adapter Design
43
44| Check | Question |
45|-------|----------|
46| **Translation** | Does the adapter translate between external format and domain model? |
47| **Isolation** | Is external system logic contained entirely within the adapter? |
48| **Swappability** | Can this adapter be replaced without modifying core logic? |
49| **Testability** | Can the adapter be mocked for testing the core? |
50
51### Architecture Boundaries
52
53| Layer | Should Contain | Should NOT Contain |
54|-------|----------------|-------------------|
55| **Domain/Core** | Business logic, entities, use cases | Framework code, I/O, external dependencies |
56| **Ports** | Interfaces/abstractions | Implementation details |
57| **Adapters** | External integrations, translations | Business logic |
58| **Infrastructure** | Concrete implementations, configs | Domain rules |
59
60---
61
62## Common Ports
63
64| Port Type | Purpose | Example Interface |
65|-----------|---------|-------------------|
66| **Database** | Data persistence operations | `Repository` interface for CRUD |
67| **HTTP** | Handle incoming HTTP requests | `Handler` interface for request processing |
68| **Messaging** | Message broker communication | `Publisher`/`Subscriber` interfaces |
69| **Filesystem** | File I/O operations | `FileStore` interface for read/write |
70| **Authentication** | User identity verification | `Authenticator` interface |
71| **Payment Gateway** | Payment processing | `PaymentProcessor` interface |
72
73---
74
75## Common Adapters
76
77| Adapter Type | Translates Between | Example |
78|--------------|-------------------|---------|
79| **Database** | Domain model ↔ Database schema | SQLAlchemy, GORM, SQLx |
80| **REST API** | HTTP requests ↔ Domain commands | Chi handlers, Gin controllers |
81| **Message Queue** | Domain events ↔ Queue messages | RabbitMQ, Kafka clients |
82| **CLI** | Command-line args ↔ Domain commands | Cobra, Click |
83| **Filesystem** | Domain data ↔ File formats | Local/cloud storage clients |
84| **Email** | Domain events ↔ Email messages | SMTP, SendGrid adapters |
85| **GUI** | User interactions ↔ Domain events | GTK, Qt, React |
86
87---
88
89## Reference Directory Structure
90
91```
92my-app/
93├── cmd/
94│ └── server/
95│ └── main.go # Entry point, wiring
96│
97├── internal/
98│ ├── config/
99│ │ └── config.go # Configuration handling
100│ │
101│ ├── app/
102│ │ └── application.go # Application service interface
103│ │
104│ ├── domain/
105│ │ ├── model/
106│ │ │ └── entity.go # Domain entities (CORE)
107│ │ └── repository/
108│ │ └── repository.go # Repository interfaces (PORTS)
109│ │
110│ ├── usecase/
111│ │ └── usecase.go # Use case implementations (CORE)
112│ │
113│ ├── interfaces/ # ADAPTERS (Driving/Primary)
114│ │ ├── rest/
115│ │ │ └── controller.go # REST controller
116│ │ └── cli/
117│ │ └── cli.go # CLI interface
118│ │
119│ └── infrastructure/ # ADAPTERS (Driven/Secondary)
120│ ├── db/
121│ │ ├── db.go # Database implementation
122│ │ └── migration/
123│ ├── http/
124│ │ ├── handler/
125│ │ └── router.go
126│ └── logger/
127│
128└── pkg/
129 └── util/ # Shared utilities
130```
131
132---
133
134## Red Flags
135
136### Architecture Violations
137
138| Violation | Symptom | Fix |
139|-----------|---------|-----|
140| **Leaky Abstraction** | Port exposes database-specific types (e.g., `sql.Row`) | Use domain types in port interface |
141| **Core Depends on Framework** | Domain imports HTTP/DB packages | Inject dependencies via ports |
142| **Adapter Contains Logic** | Business rules in handler/repository | Move logic to use case layer |
143| **Missing Port** | Core directly calls external service | Extract interface, create port |
144| **God Adapter** | Single adapter handles multiple concerns | Split into focused adapters |
145
146### Dependency Direction
147
148```
149WRONG: Domain → Infrastructure
150 (core imports database package)
151
152RIGHT: Infrastructure → Domain
153 (adapter implements domain interface)
154```
155
156---
157
158## Quick Reference
159
160| Question | Expected Answer |
161|----------|-----------------|
162| Can I swap the database without changing business logic? | Yes, via repository port |
163| Can I test use cases without a real database? | Yes, with mock adapter |
164| Does the domain layer import external packages? | No, only standard library |
165| Are external systems abstracted behind interfaces? | Yes, as ports |
166| Can I add a CLI without modifying existing code? | Yes, new adapter for existing port |