User Tools

Site Tools


ai:prompt:review-pr-golang

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
ai:prompt:review-pr-golang [2026/06/11 14:00] phong2018ai:prompt:review-pr-golang [2026/06/11 14:20] (current) phong2018
Line 11: Line 11:
 ## 1. Clean Architecture (Strict) ## 1. Clean Architecture (Strict)
  
-- Domain layer must have **zero** infrastructure dependencies (no DB drivers, HTTP clientsexternal SDKs). +The project follows **4 layers**. The single rule: **every layer only imports inward — never outward.** 
-UseCase layer must **not** import `net/http`, gRPC, or any transport-specific package+ 
-Dependencies must point inward only: `Handler → UseCase → Domain`. +``` 
-All cross-boundary calls must go through interfaces defined in the **consumer package**. +Presentation (HTTP handler) 
-Flag any concrete struct that crosses layer boundary without an interface.+    ↓ calls via TodoUsecase 
 +Usecase 
 +    ↓ imports domain only 
 +Domain 
 +  model/       — entitiesvalue objects, domain errors, domain rule constants 
 +  repository/  — TodoRepository        (method signatures use domain/model types only
 +  service/     — NotificationClient    (method signatures use domain/model types only) 
 +               — FileStorage           (method signatures use stdlib primitives only) 
 +    ↑ implemented by 
 +Infrastructure 
 +  repository/  — TodoRepository (sqlx) 
 +  httpclient/  — NotificationClient  (maps domain/model → infrastructure/dto internally) 
 +  s3/          — S3Client 
 +``` 
 + 
 +### Import matrix 
 + 
 +| Layer | Allowed imports | Forbidden imports | 
 +|-------|----------------|-------------------| 
 +| `domain` | stdlib only | anything else | 
 +| `usecase` | `domain` only | `infrastructure`, `presentation` | 
 +| `infrastructure` | `domain`, `infrastructure/dto` | `usecase` impl, `presentation` | 
 +| `presentation` | `usecase` interfaces only | `infrastructure`, `container` | 
 + 
 +Verify with: 
 +```bash 
 +grep -r "infrastructure" internal/domain/   # must be zero results 
 +grep -r "infrastructure" internal/usecase/  # must be zero results 
 +``` 
 + 
 +### Interface placement rules 
 + 
 +| Interface | Lives in | Reason | 
 +|-----------|----------|--------| 
 +| `TodoRepository` | `domain/repository/` | usecase consumes it — contract owned by domain | 
 +| `NotificationClient` | `domain/service/` | usecase consumes it — named after business intent, not vendor | 
 +| `FileStorage` | `domain/service/` | usecase consumes it — vendor-neutral name | 
 +| `TodoUsecase` | `usecase/` | presentation consumes it — uses `usecase/dto` types, cannot live in domain | 
 +| `Transaction` | `usecase/` | transaction boundary is application orchestration, not a domain rule | 
 + 
 +Flag `TodoUsecase` placed in `domain/` — it would force domain to import `usecase/dto`, breaking the stdlib-only rule. 
 + 
 +### DTO placement rules 
 + 
 +| DTO type | Lives in | Tags | Used by | 
 +|----------|----------|------|---------| 
 +| Entity / Value Object | `domain/model/` | `db:` onlyno `json:` | domain, usecase, infrastructure | 
 +| Usecase DTO | `usecase/dto/` | `json:` only, no `db:` | usecase, presentation | 
 +| Infrastructure DTO | `infrastructure/dto/` | `json:` only, no `db:` | infrastructure only — never leaks out | 
 + 
 +- [ ] No `json:` tags on domain entities — they must not be serialized directly to HTTP responses. 
 +- [ ] No `db:` tags on usecase or infra DTOs. 
 +[ ] `infrastructure/dto` types must never appear in method signatures of `domain/repository/` or `domain/service/` interfaces
 +[ ] `usecase/dto` types must never appear in domain interface signatures. 
 + 
 +### Data flow at layer boundaries 
 + 
 +``` 
 +HTTP JSON → bind/validate (presentation) 
 +    → usecase/dto.CreateTodoInput 
 +    → map (usecase impl) → domain/model.Todo 
 +    → TodoRepository.Create(ctx, *model.Todo) 
 +    → map (usecase impl) → usecase/dto.TodoOutput 
 +    → JSON response 
 +``` 
 + 
 +- [ ] Presentation must bind to `usecase/dto` types, never to `domain/model` directly
 +[ ] Usecase impl is responsible for all mapping between `usecase/dto` ↔ `domain/model`. 
 +[ ] Infrastructure impl is responsible for mapping `domain/model` ↔ `infrastructure/dto` internally — this mapping must never leak out. 
 + 
 +### Presentation layer rules 
 + 
 +- [ ] `NewServer` must accept a `Dependencies` struct of usecase interfaces — never `*container.Container` directly (would pull all of infrastructure as transitive dep). 
 +- [ ] Handlers are thin: bind → validate → call usecase → return JSON. No business logic. 
 +- [ ] Handlers must not import anything from `infrastructure/` or `domain/` directly. 
 + 
 +### Transaction rules 
 + 
 +- [ ] `WithinTransaction` is called **only from usecase** — never from repository or presentation
 +[ ] Transaction boundary wraps writes that must be atomic (e.g. todo write + audit log insert). 
 +- [ ] Operations that must not roll back (e.g. sending notification) run **outside** `WithinTransaction`. 
 +- [ ] Reads (`GetByID`, `List`) do not need a transaction. 
 + 
 +### Error handling rules 
 + 
 +- [ ] Domain sentinel errors live in `domain/model/xxx_error.go` (e.g. `ErrTodoNotFound = errors.New(...)`). 
 +- [ ] Presentation middleware maps domain sentinels → HTTP codes via `errors.Is` / `errors.As` — this mapping lives only in middleware, never in usecase or infrastructure. 
 +- [ ] `AppError.Err` (internal error) must never be serialized to the client response.
  
 --- ---
Line 47: Line 134:
  
 - [ ] Define interfaces in the **consumer package**, not in the implementor's package. - [ ] Define interfaces in the **consumer package**, not in the implementor's package.
 +  - **Exception for this project:** `TodoRepository`, `NotificationClient`, `FileStorage` live in `domain/` because the consumer (usecase) depends on domain — this is intentional per the architecture, not a violation.
 - [ ] Keep interfaces minimal — only the methods the consumer actually calls. - [ ] Keep interfaces minimal — only the methods the consumer actually calls.
 - [ ] Flag any interface with 5+ methods as a potential fat interface violation. - [ ] Flag any interface with 5+ methods as a potential fat interface violation.
ai/prompt/review-pr-golang.1781186451.txt.gz · Last modified: by phong2018