- Добавлена документация SLM-архитектуры, базовых правил и прикладных разделов - Добавлены разделы: стили, SVG-спрайты, шаблоны генерации, PostCSS, REST, Realtime - Удалены устаревшие файлы (спрайты, скрипты, стили из app/)
3.9 KiB
title, description, keywords
| title | description | keywords | ||||||
|---|---|---|---|---|---|---|---|---|
| Business-композиция | Когда REST-данные нужно объединить или интерпретировать в бизнес-модуле. |
|
Business-композиция
Business-композиция используется, когда простого GET-метода или прозрачного GET-хука недостаточно: нужно объединить несколько источников, преобразовать DTO или вычислить доменное состояние.
Когда использовать
- Нужно объединить несколько GET-запросов.
- Нужно вычислить
isAuth,canEdit,hasAccess,hasPets. - Нужно преобразовать DTO в доменную модель.
- Нужно спрятать бизнес-сценарий за доменным API.
Такая логика не пишется в infrastructure/. REST-клиент остаётся прозрачным адаптером к API.
Пример поверх одного GET-хука
// src/business/pets/hooks/use-available-pets.hook.ts
import { useGetPetList } from 'infrastructure/pet-store-api'
/**
* Доменный список доступных питомцев.
*/
export const useAvailablePets = () => {
const query = useGetPetList('available')
return {
...query,
hasPets: Boolean(query.data?.length),
}
}
useGetPetList — infrastructure-хук. hasPets — бизнес-интерпретация, поэтому она появляется в business/pets.
Пример композиции нескольких GET-хуков
// src/business/pets/hooks/use-pets-dashboard.hook.ts
import { useGetPetList } from 'infrastructure/pet-store-api'
/**
* Данные dashboard по питомцам.
*/
export const usePetsDashboard = () => {
const availablePets = useGetPetList('available')
const pendingPets = useGetPetList('pending')
const soldPets = useGetPetList('sold')
return {
availablePets,
pendingPets,
soldPets,
total:
(availablePets.data?.length ?? 0) +
(pendingPets.data?.length ?? 0) +
(soldPets.data?.length ?? 0),
}
}
Композиция нескольких запросов не добавляется в infrastructure/pet-store-api/hooks/, потому что это уже сценарий потребления данных.
Пример auth-состояния
// src/business/auth/hooks/use-auth-state.hook.ts
import { useGetCurrentUser } from 'infrastructure/backend-api'
/**
* Состояние авторизации текущего пользователя.
*/
export const useAuthState = () => {
const currentUser = useGetCurrentUser()
const user = currentUser.data
return {
...currentUser,
user,
isAuth: Boolean(user),
}
}
isAuth не является частью REST-клиента. Это доменный смысл результата запроса.
Где размещать
src/business/
└── pets/
├── hooks/
│ └── use-available-pets.hook.ts
├── mappers/
│ └── map-pet-dto-to-pet.ts
├── types/
└── index.ts
Модуль business/ экспортирует наружу готовый доменный API через index.ts.
Что запрещено
// Плохо — business-смысл внутри infrastructure-хука
export const useGetPetList = (status: PetStatus) => {
const query = useSWR(...)
return {
...query,
hasPets: Boolean(query.data?.length),
}
}
REST-модуль отвечает за доступ к API. Business-модуль отвечает за смысл этих данных в продукте.