# استانداردهای کدنویسی

## اصول کلی

### 1. کد تمیز (Clean Code)

کد باید:
- خوانا باشد
- ساده باشد  
- قابل فهم باشد
- قابل نگهداری باشد

### 2. PEP 8 Compliance

**الزامی**: تمام کدها باید با PEP 8 مطابقت داشته باشند.

استفاده از ابزارها:
```bash
black src/      # Auto-formatting
flake8 src/     # Linting
isort src/      # Import sorting
```

## قوانین Naming

### Classes

```python
# ✅ GOOD: PascalCase
class UserService:
    pass

class PaymentGateway:
    pass

class DatabaseConnection:
    pass

# ❌ BAD
class user_service:  # Wrong case
class payment_gateway_service:  # Too long
class UServ:  # Unclear abbreviation
```

### Functions & Methods

```python
# ✅ GOOD: snake_case, descriptive
def calculate_total_price(items: List[Item]) -> Decimal:
    pass

def send_welcome_email(user: User) -> bool:
    pass

# ❌ BAD
def calcTotPrice():  # Mixed case
def cp():  # Not descriptive
def calculate():  # Too vague
```

### Variables

```python
# ✅ GOOD
user_email = "test@example.com"
total_amount = Decimal("100.00")
is_active = True
MAX_ATTEMPTS = 3  # Constant

# ❌ BAD
e = "test@example.com"  # Too short
userEmail = "test@example.com"  # camelCase
TOTAL = 100  # Constant style for variable
```

## Type Hints

**الزامی**: همه function signatures باید type hints داشته باشند.

```python
from typing import Optional, List, Dict, Any
from decimal import Decimal

# ✅ GOOD
def get_user(user_id: int) -> Optional[User]:
    pass

def create_invoice(
    user_id: int,
    amount: Decimal,
    items: List[InvoiceItem]
) -> Invoice:
    pass

# ❌ BAD
def get_user(user_id):  # No types
    pass

def create_invoice(user_id, amount, items):  # No types
    pass
```

## Docstrings

**الزامی**: همه public functions, classes, و methods باید docstring داشته باشند.

### Google Style (استاندارد پروژه)

```python
def create_user(
    email: str,
    password: str,
    full_name: str
) -> User:
    """Create a new user account.
    
    Args:
        email: User's email address
        password: Plain text password
        full_name: User's full name
        
    Returns:
        User: Created user object
        
    Raises:
        EmailAlreadyExistsException: If email exists
        WeakPasswordException: If password is weak
        
    Example:
        >>> user = create_user(
        ...     email="test@example.com",
        ...     password="SecurePass123!",
        ...     full_name="John Doe"
        ... )
    """
    pass
```

## Error Handling

### Use Specific Exceptions

```python
# ✅ GOOD
try:
    user = user_repository.get_by_id(user_id)
    if not user:
        raise UserNotFoundException(f"User {user_id} not found")
except DatabaseException as e:
    logger.error("database_error", error=str(e))
    raise
except Exception as e:
    logger.critical("unexpected_error", error=str(e))
    raise

# ❌ BAD
try:
    user = get_user(user_id)
except:  # Never use bare except!
    pass

try:
    user = get_user(user_id)
except Exception:  # Too broad
    pass
```

### Custom Exception Hierarchy

```python
class PeikarbandException(Exception):
    """Base exception."""
    pass

class DomainException(PeikarbandException):
    """Domain layer exceptions."""
    pass

class UserNotFoundException(DomainException):
    """User not found."""
    pass
```

## Code Organization

### Imports

```python
# 1. Standard library
import os
import sys
from typing import Optional, List
from decimal import Decimal

# 2. Third-party
import redis
from sqlalchemy import Column, Integer
from pydantic import BaseModel

# 3. Local
from src.config.settings import settings
from src.core.domain.entities.user import User
```

### Function Length

**Max 50 lines per function** (توصیه: 20-30 lines)

```python
# ✅ GOOD: Short and focused
def calculate_discount(amount: Decimal, user: User) -> Decimal:
    """Calculate user discount."""
    if user.is_premium:
        return amount * Decimal("0.10")
    return Decimal("0.00")

# ❌ BAD: Too long (100+ lines)
def process_order(order_data):
    # 100+ lines of code
    pass
```

### Class Length

**Max 300 lines per class** (توصیه: 100-200 lines)

اگر class بزرگ شد، به چند class کوچکتر تقسیم کنید.

## Comments

### When to Comment

```python
# ✅ GOOD: Explain WHY, not WHAT
def calculate_tax(amount: Decimal) -> Decimal:
    # Iranian tax rate is 9% as of 2024
    TAX_RATE = Decimal("0.09")
    return amount * TAX_RATE

# ❌ BAD: States the obvious
def add(a, b):
    # Add two numbers
    return a + b
```

### TODO Comments

```python
# TODO(username): Description of what needs to be done
# TODO(john): Implement caching for this query
# FIXME(jane): This breaks when amount is negative
# HACK(bob): Temporary workaround until API is fixed
```

## Best Practices

### 1. Single Responsibility

```python
# ✅ GOOD
class UserRepository:
    def save(self, user: User) -> User:
        pass

class EmailService:
    def send_email(self, to: str, subject: str) -> bool:
        pass

# ❌ BAD
class UserManager:
    def save_user(self, user):
        pass
    
    def send_email(self, user):
        pass
    
    def log_activity(self, user):
        pass
```

### 2. DRY (Don't Repeat Yourself)

```python
# ❌ BAD
def get_user_name(user_id):
    db = connect_db()
    user = db.query(User).filter_by(id=user_id).first()
    db.close()
    return user.name

def get_user_email(user_id):
    db = connect_db()
    user = db.query(User).filter_by(id=user_id).first()
    db.close()
    return user.email

# ✅ GOOD
def get_user(user_id: int) -> Optional[User]:
    with get_db_context() as db:
        return db.query(User).filter_by(id=user_id).first()

def get_user_name(user_id: int) -> Optional[str]:
    user = get_user(user_id)
    return user.name if user else None
```

### 3. Early Return

```python
# ✅ GOOD: Early return
def process_payment(amount: Decimal) -> bool:
    if amount <= 0:
        return False
    
    if not user.has_sufficient_balance(amount):
        return False
    
    # Process payment
    return True

# ❌ BAD: Nested conditions
def process_payment(amount):
    if amount > 0:
        if user.has_sufficient_balance(amount):
            # Process payment
            return True
    return False
```

### 4. Use Constants

```python
# ✅ GOOD
MAX_LOGIN_ATTEMPTS = 3
PASSWORD_MIN_LENGTH = 8
SESSION_TIMEOUT_MINUTES = 30

if attempts >= MAX_LOGIN_ATTEMPTS:
    lock_account()

# ❌ BAD: Magic numbers
if attempts >= 3:  # What's 3?
    lock_account()
```

### 5. Avoid Deep Nesting

```python
# ✅ GOOD: Max 2-3 levels
def process_order(order: Order) -> bool:
    if not order.is_valid():
        return False
    
    if not user.can_order():
        return False
    
    return save_order(order)

# ❌ BAD: Too nested
def process_order(order):
    if order:
        if order.is_valid():
            if user:
                if user.can_order():
                    if save_order(order):
                        return True
    return False
```

## Code Review Checklist

قبل از ارسال PR، این موارد را بررسی کنید:

- [ ] همه تست‌ها pass می‌شوند
- [ ] Code coverage کافی است (>80%)
- [ ] تمام functions دارای type hints هستند
- [ ] تمام public functions دارای docstring هستند
- [ ] black, flake8, mypy بدون error
- [ ] هیچ TODO/FIXME جدید بدون توضیح نیست
- [ ] تغییرات در CHANGELOG.md ثبت شده
- [ ] مستندات به‌روز شده

---

**الزامات**: این استانداردها الزامی هستند و در code review بررسی می‌شوند.

