Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Бизнес-логика: ядро приложения
Бизнес-логика - это набор правил и алгоритмов, которые определяют как работает приложение в соответствии с требованиями бизнеса. Это не представление (UI) и не хранение данных (БД), а само решение проблемы, для которой создано приложение.
Что это и почему важно
Бизнес-логика отвечает на вопросы:
- Как рассчитать цену товара со скидкой?
- Когда отправить уведомление пользователю?
- Какие условия нужны для одобрения кредита?
- Как распределить заказы между доставщиками?
- Когда заблокировать аккаунт при подозрении на мошенничество?
Это не UI (кнопки, иконки) и не БД (таблицы, индексы) - это суть приложения.
Примеры бизнес-логики
Пример 1: E-commerce (интернет-магазин)
# Вычисление цены товара с скидкой
def calculate_final_price(base_price, discount_percent, quantity, is_premium_user):
"""Бизнес-логика: вычисление финальной цены"""
# Скидка в зависимости от количества
if quantity >= 10:
quantity_discount = 0.1 # 10% скидка
elif quantity >= 5:
quantity_discount = 0.05 # 5% скидка
else:
quantity_discount = 0
# Премиум пользователи получают ещё 5%
if is_premium_user:
premium_discount = 0.05
else:
premium_discount = 0
# Общая скидка (максимум 30%)
total_discount = min(discount_percent + quantity_discount + premium_discount, 0.3)
# Финальная цена
final_price = base_price * quantity * (1 - total_discount)
return final_price
# Использование
price = calculate_final_price(
base_price=100,
discount_percent=0.05,
quantity=15,
is_premium_user=True
)
print(f"Финальная цена: {price}") # 1275 (100 * 15 * (1 - 0.15))
Это бизнес-логика, потому что она содержит правила, определённые бизнесом (скидки, условия и т.д.).
Пример 2: Обработка платежей
# Бизнес-логика: одобрение платежа
def process_payment(user, amount):
"""Проверяет условия и обрабатывает платёж"""
# Правило 1: минимальная сумма платежа
if amount < 10:
return {'status': 'rejected', 'reason': 'Amount too small'}
# Правило 2: проверка баланса
if user.balance < amount:
return {'status': 'rejected', 'reason': 'Insufficient funds'}
# Правило 3: проверка лимитов (антифрод)
daily_spent = user.get_daily_spending()
if daily_spent + amount > user.daily_limit:
return {'status': 'rejected', 'reason': 'Daily limit exceeded'}
# Правило 4: новые пользователи должны подтвердить email
if not user.email_verified and user.account_age_days < 7:
return {'status': 'pending', 'reason': 'Verification required'}
# Все проверки пройдены - можно обработать платёж
user.balance -= amount
user.save()
return {'status': 'approved', 'transaction_id': 'TXN123'}
Это бизнес-правила: минимальная сумма, лимиты, проверки.
Структура: где должна жить бизнес-логика
WEB REQUEST
↓
[PRESENTATION LAYER]
└── views.py, serializers
(Получить данные, вызвать бизнес-логику)
↓
[APPLICATION LAYER] ← БИЗНЕС-ЛОГИКА ЗДЕСЬ
└── services.py, use_cases
(Вся логика: расчёты, валидация, координация)
↓
[DOMAIN LAYER]
└── models
(Создание объектов, валидация данных)
↓
[INFRASTRUCTURE LAYER]
└── repositories, database
(Сохранение в БД, работа с внешними сервисами)
↓
WEB RESPONSE
Плохо: бизнес-логика в View
# ❌ ПЛОХО: логика в view
from django.views import View
from django.http import JsonResponse
class PaymentView(View):
def post(self, request):
user = request.user
amount = float(request.POST.get('amount'))
# СЛИШКОМ МНОГО ЛОГИКИ В VIEW!
if amount < 10:
return JsonResponse({'error': 'Too small'})
if user.balance < amount:
return JsonResponse({'error': 'No funds'})
daily_spent = user.transactions.filter(
created_at__gte=timezone.now().date()
).aggregate(Sum('amount'))['amount__sum'] or 0
if daily_spent + amount > 5000:
return JsonResponse({'error': 'Limit exceeded'})
user.balance -= amount
user.save()
Transaction.objects.create(
user=user,
amount=amount,
status='completed'
)
return JsonResponse({'status': 'ok'})
Проблемы:
- Код невозможно тестировать без Django
- Бизнес-правила зашиты в view
- Повторное использование - невозможно
- Трудно менять правила
Хорошо: бизнес-логика в Service
# ✅ ХОРОШО: логика в отдельном service
from typing import TypedDict
class PaymentResult(TypedDict):
status: str # 'approved', 'rejected', 'pending'
reason: str
transaction_id: str | None
class PaymentService:
"""Сервис обработки платежей - чистая бизнес-логика"""
MIN_AMOUNT = 10
MAX_DAILY_LIMIT = 5000
def process_payment(self, user, amount) -> PaymentResult:
# Валидация
if amount < self.MIN_AMOUNT:
return {
'status': 'rejected',
'reason': f'Minimum amount is {self.MIN_AMOUNT}',
'transaction_id': None
}
# Проверка баланса
if user.balance < amount:
return {
'status': 'rejected',
'reason': 'Insufficient funds',
'transaction_id': None
}
# Проверка лимитов
daily_spent = self._get_daily_spending(user)
if daily_spent + amount > self.MAX_DAILY_LIMIT:
return {
'status': 'rejected',
'reason': 'Daily limit exceeded',
'transaction_id': None
}
# Обработка платежа
transaction_id = self._create_transaction(user, amount)
user.balance -= amount
user.save()
return {
'status': 'approved',
'reason': 'Payment processed',
'transaction_id': transaction_id
}
def _get_daily_spending(self, user) -> float:
"""Получить сумму трат пользователя за день"""
from django.utils import timezone
from django.db.models import Sum
result = user.transactions.filter(
created_at__date=timezone.now().date()
).aggregate(Sum('amount'))['amount__sum']
return result or 0
def _create_transaction(self, user, amount) -> str:
"""Создать запись о транзакции"""
from .models import Transaction
transaction = Transaction.objects.create(
user=user,
amount=amount,
status='completed'
)
return str(transaction.id)
# View теперь простой
from django.views import View
from django.http import JsonResponse
class PaymentView(View):
def post(self, request):
amount = float(request.POST.get('amount'))
# View ТОЛЬКО получает данные и вызывает бизнес-логику
service = PaymentService()
result = service.process_payment(request.user, amount)
status_code = 200 if result['status'] == 'approved' else 400
return JsonResponse(result, status=status_code)
Тестирование бизнес-логики
Код в Service легко тестировать:
import pytest
from django.test import TestCase
from .services import PaymentService
from .models import User
class TestPaymentService(TestCase):
def setUp(self):
self.service = PaymentService()
self.user = User.objects.create(
username='john',
balance=1000
)
def test_payment_too_small(self):
"""Платёж меньше минимума отклоняется"""
result = self.service.process_payment(self.user, 5)
assert result['status'] == 'rejected'
assert 'Minimum' in result['reason']
def test_insufficient_funds(self):
"""Платёж при недостаточных средствах отклоняется"""
result = self.service.process_payment(self.user, 2000)
assert result['status'] == 'rejected'
assert 'funds' in result['reason'].lower()
def test_successful_payment(self):
"""Успешный платёж обрабатывается"""
result = self.service.process_payment(self.user, 100)
assert result['status'] == 'approved'
assert result['transaction_id'] is not None
# Баланс должен уменьшиться
self.user.refresh_from_db()
assert self.user.balance == 900
Принципы написания бизнес-логики
- Отделение - бизнес-логика отделена от View, Model, БД
- Чистота - функции чистые (для одного входа один выход)
- Тестируемость - можно тестировать без Django
- Переиспользуемость - одна функция используется в разных местах
- Читаемость - код отражает бизнес-правила
Где писать бизнес-логику в Django
project/
└── myapp/
├── services/ ← ВСЯ БИЗНЕС-ЛОГИКА ЗДЕСЬ
│ ├── __init__.py
│ ├── payment.py
│ ├── user.py
│ └── order.py
├── models.py ← Структуры данных
├── views.py ← Обработка запросов (тонкий слой)
├── serializers.py ← Валидация и сериализация
└── urls.py
Реальный пример: расчёт налога
# services/tax.py - ВСЯ БИЗНЕС-ЛОГИКА ЗДЕСЬ
class TaxCalculator:
"""Расчёт налогов в зависимости от региона и суммы"""
TAX_RATES = {
'CA': 0.0725, # 7.25%
'TX': 0.0625, # 6.25%
'NY': 0.0800, # 8.00%
}
def calculate_tax(self, amount, state):
rate = self.TAX_RATES.get(state, 0.07)
return amount * rate
def calculate_total(self, subtotal, state):
tax = self.calculate_tax(subtotal, state)
return subtotal + tax
# Тест
def test_tax_calculator():
calc = TaxCalculator()
# Без Django, просто Python
tax = calc.calculate_tax(100, 'CA')
assert tax == 7.25
total = calc.calculate_total(100, 'TX')
assert total == 106.25
Вывод
Бизнес-логика:
- Это ядро приложения - решение задачи
- НЕ зависит от Django, БД, фреймворков
- Должна жить в Service слое отдельно от View
- Легко тестируется (unit тесты без Django)
- Переиспользуется в разных частях приложения
- Легко меняется (правила обновляются в одном месте)
- Это то, за что платит клиент, а не UI красота
Хороший разработчик отделяет бизнес-логику от технических деталей!