Преобразование между слоями
Mapper — объект, который преобразует данные из одного представления в другое (например, Entity → DTO, DTO → Entity).
# ❌ Преобразование размазано по коду
class UserController:
def get_user(self, user_id: int):
user = user_service.get_user(user_id)
# Преобразование в контроллере
return {
"id": user.id,
"name": user.name,
"email": user.email.address,
"created_at": user.created_at.isoformat()
}
# Проблемы:
# - Дублирование кода
# - Сложно изменить представление
# - Нарушение Single Responsibility
# ✅ Преобразование в Mapper
class UserMapper:
@staticmethod
def to_dto(user: User) -> UserDTO:
return UserDTO(
id=user.id,
name=user.name,
email=user.email.address,
created_at=user.created_at.isoformat()
)
@staticmethod
def to_entity(dto: UserDTO) -> User:
return User(
id=dto.id,
name=dto.name,
email=Email(dto.email),
created_at=datetime.fromisoformat(dto.created_at)
)
# Использование
class UserController:
def get_user(self, user_id: int):
user = user_service.get_user(user_id)
return UserMapper.to_dto(user)
class UserMapper:
@staticmethod
def to_dto(user: User) -> UserDTO:
return UserDTO(
id=user.id,
name=user.name,
email=user.email.address,
created_at=user.created_at.isoformat()
)
@staticmethod
def to_dto_list(users: List[User]) -> List[UserDTO]:
return [UserMapper.to_dto(user) for user in users]
# Использование
users = user_repository.find_all()
user_dtos = UserMapper.to_dto_list(users)
class UserMapper:
@staticmethod
def to_entity(dto: UserDTO) -> User:
return User(
id=dto.id,
name=dto.name,
email=Email(dto.email),
created_at=datetime.fromisoformat(dto.created_at)
)
@staticmethod
def from_request(request: CreateUserRequest) -> User:
return User.create(
name=request.name,
email=Email(request.email),
password=request.password
)
# Использование
request = CreateUserRequest(name="Alice", email="alice@example.com", password="password123")
user = UserMapper.from_request(request)
class UserMapper:
@staticmethod
def from_db_row(row: dict) -> User:
return User(
id=row['id'],
name=row['name'],
email=Email(row['email']),
created_at=datetime.fromisoformat(row['created_at'])
)
@staticmethod
def to_db_dict(user: User) -> dict:
return {
'id': user.id,
'name': user.name,
'email': user.email.address,
'created_at': user.created_at.isoformat()
}
# Использование
row = db.fetch_one("SELECT * FROM users WHERE id = ?", (user_id,))
user = UserMapper.from_db_row(row)
from dataclasses import dataclass, asdict
@dataclass
class UserDTO:
id: int
name: str
email: str
class UserMapper:
@staticmethod
def to_dto(user: User) -> UserDTO:
return UserDTO(
id=user.id,
name=user.name,
email=user.email.address
)
@staticmethod
def to_dict(dto: UserDTO) -> dict:
return asdict(dto)
# Использование
user = User(1, "Alice", Email("alice@example.com"))
dto = UserMapper.to_dto(user)
dto_dict = UserMapper.to_dict(dto)