---
title: Separate Processing And Data Access
impact: HIGH
impactDescription: enables testable business logic
tags: separation, repository, service, architecture, quality
---

## Separate Processing And Data Access

Mixing business logic with database queries creates tight coupling and makes testing require real databases.

**Incorrect (mixed concerns):**

```go
type OrderService struct {
    db *sql.DB
}

func (s *OrderService) CalculateDiscount(userId string) (int, error) {
    // Business logic mixed with data access
    var isPremium bool
    db.QueryRow("SELECT is_premium FROM users WHERE id = ?", userId).Scan(&isPremium)
    
    var orderCount int
    db.QueryRow("SELECT count(*) FROM orders WHERE user_id = ?", userId).Scan(&orderCount)
    
    discount := 0
    if orderCount > 10 { discount += 5 }
    if isPremium { discount += 10 }
    
    return discount, nil
}
```

**Correct (separated layers):**

```go
// Repository - data access only
type UserRepository interface {
    FindByID(id string) (*User, error)
}

type OrderRepository interface {
    CountByUserID(id string) (int, error)
}

// Service - business logic only
type DiscountService struct {
    userRepo  UserRepository
    orderRepo OrderRepository
}

func (s *DiscountService) CalculateDiscount(userId string) (int, error) {
    user, _ := s.userRepo.FindByID(userId)
    count, _ := s.orderRepo.CountByUserID(userId)
    
    return s.computeDiscount(user, count), nil
}

func (s *DiscountService) computeDiscount(user *User, orderCount int) int {
    discount := 0
    if orderCount > 10 { discount += 5 }
    if user != nil && user.IsPremium { discount += 10 }
    return discount
}
```

**Tools:** Architectural review, Code Review
