$npx -y skills add saifoelloh/golang-best-practices-skill --skill clean-architectureClean Architecture audit for Go services. Use when reviewing layered architecture, dependency rules, or gRPC/usecase/repository patterns. Ensures proper separation of concerns and dependency inversion.
| 1 | # Golang Clean Architecture |
| 2 | |
| 3 | Audit Go services for Clean Architecture compliance. Ensures proper layering, dependency rules, and separation of concerns in gRPC → Usecase → Repository → Domain architectures. |
| 4 | |
| 5 | ## When to Apply |
| 6 | |
| 7 | Use this skill when: |
| 8 | - Auditing service architecture |
| 9 | - Reviewing new features for layer violations |
| 10 | - Refactoring toward Clean Architecture |
| 11 | - Code review for dependency rules |
| 12 | - Planning service structure |
| 13 | - Migrating to layered architecture |
| 14 | - Ensuring testability through dependency injection |
| 15 | |
| 16 | ## Architecture Layers |
| 17 | |
| 18 | ``` |
| 19 | ┌─────────────────────────────────────┐ |
| 20 | │ Delivery (gRPC/HTTP/GraphQL) │ ← Thin, no business logic |
| 21 | ├─────────────────────────────────────┤ |
| 22 | │ Usecase (Business Logic) │ ← Orchestration |
| 23 | ├─────────────────────────────────────┤ |
| 24 | │ Repository (Data Access) │ ← CRUD only |
| 25 | ├─────────────────────────────────────┤ |
| 26 | │ Domain (Entities/Interfaces) │ ← Pure business logic |
| 27 | └─────────────────────────────────────┘ |
| 28 | ``` |
| 29 | |
| 30 | **Dependency Rule**: Dependencies point INWARD only (toward domain). |
| 31 | |
| 32 | ## Rules Covered (9 total) |
| 33 | |
| 34 | ### High-Impact Patterns (4) |
| 35 | |
| 36 | - `high-business-logic-handler` - Keep delivery layer thin |
| 37 | - `high-business-logic-repository` - No business logic in data layer |
| 38 | - `high-constructor-creates-deps` - Inject dependencies, don't create |
| 39 | - `high-transaction-in-repository` - Transactions belong in usecase |
| 40 | |
| 41 | ### Architecture Rules (5) |
| 42 | |
| 43 | - `arch-domain-import-infra` - Domain must not import infrastructure |
| 44 | - `arch-concrete-dependency` - Depend on interfaces, not concrete types |
| 45 | - `arch-repository-business-logic` - Repositories do CRUD only |
| 46 | - `arch-usecase-orchestration` - Usecases orchestrate, entities decide |
| 47 | - `arch-interface-segregation` - Small, consumer-defined interfaces |
| 48 | |
| 49 | ## Common Violations |
| 50 | |
| 51 | ### ❌ Business Logic in Handler |
| 52 | |
| 53 | ```go |
| 54 | // gRPC handler doing calculations |
| 55 | func (h *Handler) CreateOrder(ctx context.Context, req *pb.Request) (*pb.Response, error) { |
| 56 | total := req.Price * req.Quantity // BAD: calculation in handler |
| 57 | discount := total * 0.1 // BAD: business rules in delivery layer |
| 58 | |
| 59 | order := &domain.Order{ |
| 60 | Total: total - discount, |
| 61 | } |
| 62 | return h.orderRepo.Save(ctx, order) |
| 63 | } |
| 64 | ``` |
| 65 | |
| 66 | ### ✅ Business Logic in Usecase |
| 67 | |
| 68 | ```go |
| 69 | // Handler delegates to usecase |
| 70 | func (h *Handler) CreateOrder(ctx context.Context, req *pb.Request) (*pb.Response, error) { |
| 71 | order, err := h.orderUsecase.Create(ctx, req.Price, req.Quantity) |
| 72 | if err != nil { |
| 73 | return nil, err |
| 74 | } |
| 75 | return &pb.Response{OrderId: order.ID}, nil |
| 76 | } |
| 77 | |
| 78 | // Usecase contains business logic |
| 79 | func (u *OrderUsecase) Create(ctx context.Context, price, quantity int) (*domain.Order, error) { |
| 80 | total := price * quantity // GOOD: calculation in usecase |
| 81 | discount := total * 0.1 // GOOD: business rules in usecase |
| 82 | |
| 83 | order := &domain.Order{ |
| 84 | Total: total - discount, |
| 85 | } |
| 86 | return u.orderRepo.Save(ctx, order) |
| 87 | } |
| 88 | ``` |
| 89 | |
| 90 | ### ❌ Repository with Business Logic |
| 91 | |
| 92 | ```go |
| 93 | // Repository doing validation and business rules |
| 94 | func (r *OrderRepo) Save(ctx context.Context, order *domain.Order) error { |
| 95 | if order.Total < 0 { // BAD: validation in repository |
| 96 | return errors.New("invalid total") |
| 97 | } |
| 98 | if order.Total > 1000000 { // BAD: business rule in repository |
| 99 | order.Status = "needs_approval" // BAD: state change in repository |
| 100 | } |
| 101 | return r.db.Create(order) |
| 102 | } |
| 103 | ``` |
| 104 | |
| 105 | ### ✅ Repository Does CRUD Only |
| 106 | |
| 107 | ```go |
| 108 | // Repository only handles data persistence |
| 109 | func (r *OrderRepo) Save(ctx context.Context, order *domain.Order) error { |
| 110 | return r.db.Create(order) // GOOD: simple CRUD |
| 111 | } |
| 112 | |
| 113 | // Validation happens in usecase or domain entity |
| 114 | func (u *OrderUsecase) Create(ctx context.Context, price, quantity int) (*domain.Order, error) { |
| 115 | order := domain.NewOrder(price, quantity) // Entity validates itself |
| 116 | if err := order.Validate(); err != nil { // GOOD: validation in domain |
| 117 | return nil, err |
| 118 | } |
| 119 | if order.NeedsApproval() { // GOOD: business rule in domain |
| 120 | order.Status = "needs_approval" |
| 121 | } |
| 122 | return u.orderRepo.Save(ctx, order) |
| 123 | } |
| 124 | ``` |
| 125 | |
| 126 | ## Trigger Phrases |
| 127 | |
| 128 | This skill activates when you say: |
| 129 | - "Audit architecture" |
| 130 | - "Check layer dependencies" |
| 131 | - "Review Clean Architecture" |
| 132 | - "Verify separation of concerns" |
| 133 | - "Check dependency rules" |
| 134 | - "Review usecase/repository pattern" |
| 135 | - "Check for layer violations" |
| 136 | - "Audit service structure" |
| 137 | |
| 138 | ## How to Use |
| 139 | |
| 140 | ### For Architecture Audit |
| 141 | |
| 142 | 1. Identify all laye |