Custom Clean Architecture Implementation Guide
Expert guidance for implementing features using this project's custom Clean Architecture pattern with Golang. This is NOT Uncle Bob's standard Clean Architecture - it's a specialized adaptation.
Architecture Overview
Four layers with strict dependency rules:
Integration → Application → Domain ← Infrastructure
Dependency Rule: Inner layers NEVER depend on outer layers.
🚨 Critical Rules
MUST DO
- •START with BDD feature file - Never skip test-first development
- •Integration adapters MUST implement usecase interfaces - Enable type casting
- •Use context.Context as first parameter - Always
- •Convert at boundaries - DTO↔Entity↔Model
- •Follow error code format - PREFIX-XXYYYY
- •Type cast repositories to usecases - In dependency injection
NEVER DO
- •Skip BDD test creation - Tests come first
- •Create adapters without usecase interfaces - Will break dependency injection
- •Put business logic in controllers/repositories - Only in services
- •Use DTOs in domain/application - Only in integration layer
- •Access database from services - Only through usecases
- •Create circular dependencies - Dependencies flow inward only
Implementation Workflow
Step 1: Create BDD Test (MANDATORY)
Start here ALWAYS. Location: /test/integration/features/
Feature: Create entity functionality
Scenario: Create entity success
When I call "POST" "/v1/entities" with payload
Then status should be 201
And db should contain entity
Step 2: Domain Layer
- •
Entity (
/internal/domain/entity/)- •Simple structs, NO logic
- •Audit fields (CreatedAt, UpdatedAt)
- •
Errors (
/internal/domain/error/)- •Format:
PREFIX-XXYYYY - •One error per file
- •Format:
- •
Enums (
/internal/domain/enums/)- •String types
- •SCREAMING_SNAKE_CASE values
Step 3: Application Layer
- •
Adapter Interface (
/internal/application/adapter/)- •Service contracts
- •Use domain entities
- •
UseCase Interfaces (
/internal/application/usecase/)- •Atomic operations
- •FindX, SaveX, UpdateX, DeleteX
- •
Service Implementation (
/internal/application/service/)- •Business logic HERE
- •Orchestrate usecases
Step 4: Integration Layer
- •
Adapter Interfaces (
/internal/integration/adapter/)gotype Repository interface { usecase.Find // MUST embed usecase.Save // MUST embed } - •
DTOs (
/internal/integration/entrypoint/dto/)- •Request/Response structs
- •ToEntity() methods
- •Validation tags
- •
Controller (
/internal/integration/entrypoint/controller/)- •Handle HTTP
- •DTO↔Entity conversion
- •
Model (
/internal/integration/persistence/model/)- •GORM annotations
- •ToEntity() methods
- •
Repository (
/internal/integration/persistence/)- •Implements usecase interfaces
- •Entity↔Model conversion
Step 5: Infrastructure Layer
- •
Dependency Injection (
/internal/infra/dependency/injector.go)go// Type cast repository to usecase usecase.Find(i.GetRepository())
- •
Router (
/internal/infra/server/router/router.go)- •Add routes
- •Validation middleware
Step 6: Run Tests
make test-integration
Quick Patterns
Integration Adapter Pattern (CRITICAL)
// Application defines need
type FindProduct interface {
FindById(ctx, id) (*entity, error)
}
// Integration MUST implement
type ProductRepository interface {
usecase.FindProduct // EMBED!
}
// Type cast in DI
usecase.FindProduct(repository)
Error Codes
- •
CLI-01409= Client conflict (409) - •
USR-01404= User not found (404) - •
PRD-02500= Product server error (500)
Conversion Flow
Request → DTO → Entity → Model → DB Response ← DTO ← Entity ← Model ← DB
Reference Documentation
Detailed guides in references/:
- •Layer Implementation - Complete layer examples
- •Critical Patterns - Must-know patterns
- •Implementation Workflow - Step-by-step guide
Templates
Ready-to-use templates in assets/:
- •
entity-template.go- Domain entity template - •
service-template.go- Application service template - •
repository-template.go- Repository template
Implementation Checklist
Before starting any feature:
- • BDD feature file exists
- • Domain entity defined
- • Domain errors created
- • Application adapter interface defined
- • Application usecases created
- • Application service implemented
- • Integration adapters created WITH usecase interfaces
- • DTOs with ToEntity() methods
- • Controller handling HTTP
- • Model with ToEntity() method
- • Repository implementing usecases
- • Dependencies wired in injector
- • Routes added to router
- • Tests passing
Common Mistakes to Avoid
- •Forgetting usecase interfaces on adapters - Breaks type casting
- •Business logic in wrong layer - Only in services
- •Wrong dependency direction - Check imports
- •Missing BDD test - Always start with test
- •Wrong error code format - Use PREFIX-XXYYYY
- •Not converting at boundaries - DTO↔Entity↔Model
Example Implementations
Study these existing implementations:
- •Client:
/internal/{domain,application,integration}/*/client*.go - •User:
/internal/{domain,application,integration}/*/user*.go - •Forest:
/internal/{domain,application,integration}/*/forest*.go