Работа со сложными данными
#
Васильев Андрей Михайлович, 2025
Версии презентации
Проблема большого класса-хранилища
#
В рамках HTTP-обработчика необходимо иметь доступ к хранилищу данных, т.к. все
действия приложения так или иначе сводятся к выборке или изменению набора данных
При использовании большого класса-хранилища
- В хранилище начинают оседать все функции, связанные с обработкой данных внутри
- При написании теста обработчика ему необходимо предоставить тестовый дубль
класса-хранилища, а может быть и не одного
- Остаётся нерешённым вопрос хранения кода, которому необходимо
взаимодействовать со множеством хранилищ одновременно
Слой операций
#
Добавление промежуточного слоя, классов операций, позволяет решить ряд проблем
- Классы-операции должны решать только одну задачу
- В приложении может быть на порядок больше операций по сравнению с количеством
хранилищ, но каждая из них будет простой и понятной
- Операции могут взаимодействовать со множеством хранилищ для решения своей
задачи
Слой операций
#
- На уровне хранилища решается задача по хранению набора объектов
- На уровне хранилища решается задача по изменению набора объектов
- Сложные действия, включающие любую обработку данных, располагаются в
соответствующих операциях
- Операция не является декорацией для вызова функции в хранилище
В сравнении с СУБД можно провести следующие аналогии
- Хранилище представляет собой БД
- Операция представляет собой логику по выполнению запроса к БД
В рамках данных лабораторных работ хранилище де-факто имитирует СУБД
Операции на классах
#
Операции можно описать с помощью классов
CalculateTriangleStatistics(private val triangleStorage: TriangleStorage) {
fun statistics(color: Color): Map<Int, Double> {
val allTriangles = triangleStorage.list()
...
}
}
val operation = CalculateTriangleStatistics(TriangleStorage)
В рамках HTTP-обработчика необходимо обеспечить доступ к объекту-операции:
class ShowStatisticsHandler(
calculateTriangleStatistics: CalculateTriangleStatistics,
) : HttpHandler { request ->
val color: Color = ....
val statistics = calculateTriangleStatistics.statistics(color)
...
}
В рамках автоматических тестов достаточно сформировать мок-объект операции,
который будет возвращать необходимые данные при запросе
Операции на функциях
#
Операции можно описать с помощью функций
fun calculateTriangleStatistics(triangleStorage: TriangleStorage):
(Color) -> Map<Int, Double> = { color ->
val allTriangles = triangleStorage.list()
...
}
val operation = calculateTriangleStatistics(triangleStorage)
Внутри HTTP-обработчика необходимо обеспечить доступ к операции:
fun showStatisticsHandler(
calculateTriangleStatistics: (Color) -> Map<Int, Dobule>,
): HttpHandler = { request ->
val color: Color = ...
val statistics = calculateTriangleStatistics(color)
}
При написании автоматических тестов в HTTP-обработчик необходимо передать
функцию, которая будет возвращать данные, нужные для тестов