3.2 KiB
3.2 KiB
Architecture Violations Reference
Clean Architecture principles: Separation of concerns, layer independence, dependency inversion.
Layer Hierarchy
┌─────────────────┐
│ Controllers │ (HTTP handlers, routes)
│ (routes/) │
└────────┬────────┘
│
v
┌─────────────────┐
│ Services │ (Business logic)
│ (services/) │
└────────┬────────┘
│
v
┌─────────────────┐
│ Repositories │ (Data access)
│ (repositories/) │
└─────────────────┘
Rule: Only call downward. Controller → Service → Repository.
Violation Patterns
1. Layer Skipping
Violation:
# controllers/user_controller.py
from repositories.user_repository import UserRepository # VIOLATION!
def get_user(user_id):
user_repo = UserRepository() # Skips Service layer
return user_repo.get(user_id)
Fix:
# controllers/user_controller.py
from services.user_service import UserService
def get_user(user_id):
user_service = UserService()
return user_service.get_user(user_id)
# services/user_service.py
from repositories.user_repository import UserRepository
class UserService:
def __init__(self):
self.user_repo = UserRepository()
def get_user(self, user_id):
return self.user_repo.get(user_id)
Severity: HIGH
2. Circular Dependencies
Violation:
# module_a.py
from module_b import function_b
def function_a():
return function_b()
# module_b.py
from module_a import function_a # CIRCULAR!
def function_b():
return function_a()
Detection: Build dependency graph, check for cycles
Fix: Extract shared code to third module or use dependency injection
Severity: HIGH
3. Business Logic in Wrong Layer
Violation:
# controllers/user_controller.py
def create_user(data):
# Business logic in controller! VIOLATION!
if not data.get('email') or '@' not in data['email']:
return {"error": "Invalid email"}
if len(data.get('password', '')) < 8:
return {"error": "Password too short"}
user = User(**data)
db.session.add(user)
db.session.commit()
return {"success": True}
Fix: Move business logic to Service layer
Detection
def detect_layer_violations(files):
violations = []
for file in files:
# Parse imports
imports = extract_imports(file)
# Check layer
if 'controllers' in file.path or 'routes' in file.path:
# Controller layer
for imp in imports:
if 'repositories' in imp:
violations.append({
'type': 'Architecture',
'severity': 'HIGH',
'file': file.path,
'description': 'Controller imports Repository (skips Service)',
'suggestion': 'Import from services/ instead'
})
return violations
Version: 1.0.0 Last Updated: 2025-11-13