Ответ
Паттерн Repository представляет собой слой абстракции между бизнес-логикой приложения и хранилищем данных (например, базой данных). Он инкапсулирует логику доступа к данным, предоставляя унифицированный интерфейс для выполнения CRUD-операций (Create, Read, Update, Delete) над сущностями.
Почему используется Repository?
- Изоляция: Отделяет бизнес-логику от деталей реализации конкретной СУБД или ORM, что упрощает смену хранилища данных.
- Тестируемость: Позволяет легко подменять реальный репозиторий на mock-объекты при юнит-тестировании бизнес-логики.
- Централизация: Предоставляет единую точку управления операциями с определенной сущностью, улучшая читаемость и поддерживаемость кода.
- Чистая архитектура: Способствует созданию более чистой и модульной архитектуры приложения.
Пример реализации на Python (с использованием ORM-сессии, например, SQLAlchemy):
from sqlalchemy.orm import Session # Пример для SQLAlchemy
from typing import List, Optional
# Предположим, у нас есть модель User
class User:
def __init__(self, id: int, name: str, email: str):
self.id = id
self.name = name
self.email = email
def __repr__(self):
return f"<User(id={self.id}, name='{self.name}')>"
class UserRepository:
def __init__(self, session: Session):
self.session = session
def get_by_id(self, user_id: int) -> Optional[User]:
# В реальном ORM здесь был бы запрос к БД
return self.session.query(User).filter_by(id=user_id).first()
def add(self, user: User):
self.session.add(user)
self.session.commit()
def update(self, user: User):
# В ORM изменения отслеживаются автоматически после add/query
self.session.merge(user) # Для отсоединенных объектов
self.session.commit()
def delete(self, user: User):
self.session.delete(user)
self.session.commit()
def get_all(self) -> List[User]:
return self.session.query(User).all()
def find_by_email(self, email: str) -> Optional[User]:
return self.session.query(User).filter_by(email=email).first()
Нюансы и лучшие практики:
- Разделение ответственности: Репозиторий должен заниматься только доступом к данным, не смешивая бизнес-логику.
- Сложные запросы: Для специфических или сложных запросов можно добавлять специализированные методы (например,
filter_by_status,find_active_users). - Unit of Work: Паттерн Repository часто используется в связке с паттерном Unit of Work для управления транзакциями и группировки изменений перед их сохранением.