Skip to content

What is Clean Architecture? — Uncle Bob's Layered Design for Go

Clean architecture is a software design philosophy introduced by Robert C. Martin (Uncle Bob) in 2012, synthesizing earlier ideas from hexagonal architecture, onion architecture, and screaming architecture. The core principle is the Dependency Rule: source code dependencies must point inward. Outer layers can depend on inner layers; inner layers cannot depend on anything outer.

The architecture organizes code into four concentric circles: entities (enterprise-wide business rules), use cases (application-specific business rules), interface adapters (controllers, presenters, gateways), and frameworks/infrastructure (databases, web frameworks, external services). The innermost layers know nothing about the outer layers — they contain pure business logic with no framework imports, no database drivers, no HTTP concepts.

The practical benefit is testability and replaceability. Use cases can be tested without a web framework. Entities can be validated without a database. The database can be swapped without touching business rules. The architecture enforces these properties structurally — they’re not a matter of discipline but of import constraints.

The four layers in verikt’s clean architecture scaffold:

internal/entity/ → Core business entities. No external dependencies.
internal/usecase/ → Application use cases. Imports only entity/.
internal/interface/handler/ → HTTP handlers, adapters. Imports usecase/, entity/.
internal/infrastructure/ → Database, external services. Imports all inner layers.

Use cases define repository interfaces that the infrastructure layer implements. A CreateOrderUseCase declares OrderRepository as an interface parameter — the Postgres implementation lives in infrastructure/ and is injected at startup. The use case never references *sql.DB.

The challenge in Go is that there’s no enforcement mechanism beyond conventions and tooling. The pattern works when you discipline imports at the package level and use interfaces consistently:

internal/usecase/create_order.go
type OrderRepository interface {
Save(ctx context.Context, order *entity.Order) error
}
type CreateOrderUseCase struct {
repo OrderRepository
}

The usecase package imports entity — nothing else. The concrete PostgresOrderRepository in infrastructure/ imports usecase (for the interface) and entity, implementing the interface without the use case knowing.

verikt check enforces these import boundaries statically, catching violations before they accumulate.

verikt scaffolds the clean architecture layout with entity/, usecase/, interface/, and infrastructure/ directories and encodes the dependency rules in verikt.yaml. Run verikt check to catch dependency violations. See Architectures for the full comparison.

Hexagonal Architecture

A related pattern with the same dependency-inversion goal, different terminology. Hexagonal Architecture

Domain-Driven Design

DDD pairs naturally with clean architecture — entities and use cases map to DDD concepts. Domain-Driven Design

Architectures

See how verikt implements clean architecture alongside hexagonal, layered, and flat. Architectures