Назад к задачам
СамокатПолучайте помощь с лайвкодингом в реальном времени с Sobes Copilot
Junior — Middle+
6
Ревизия и улучшение функции денежного перевода на Kotlin
Компании, где спрашивали:
Условие задачи
В данном примере показана простая функция на Kotlin, осуществляющая перевод средств с одного счета на другой. Необходимо выявить потенциальные проблемы, связанные с транзакциями, и предложить способы её оптимизации или полной замены.
fun transfer(sourceAccountId: Long, destinationAccountId: Long, transferAmount: Int) {
val sourceCurrentBalance = dao.getCurrentSum(sourceAccountId)
dao.updateSum(sourceAccountId, sourceCurrentBalance - transferAmount)
val destinationCurrentBalance = dao.getCurrentSum(destinationAccountId)
dao.updateSum(destinationAccountId, destinationCurrentBalance + transferAmount)
}
Что может пойти не так?
- Отсутствие проверки достаточности средств на исходном счёте → возможен отрицательный баланс.
- Нет валидации входных параметров (отрицательная сумма, одинаковые идентификаторы).
- Операции чтения и записи не находятся в одной атомарной транзакции → при конкурентных запросах может возникнуть состояние гонки и потеря средств.
- Ошибки доступа к базе (исключения) не обрабатываются, что может привести к частичному выполнению операции.
- Нет логирования и аудита действий, что усложняет отладку и мониторинг.
Варианты рефакторинга:
- Обернуть чтение и обновление балансов в единую транзакцию уровня
SERIALIZABLEили использовать механизмoptimistic locking. - Добавить предварительные проверки: достаточность средств, корректность суммы, различие счетов.
- Ввести обработку исключений и откат транзакции в случае ошибки.
- Переписать функцию так, чтобы она возвращала результат операции (
Result/Either) и/или бросала специализированные исключения. - При необходимости вынести бизнес‑логику в отдельный сервис‑класс, а работу с базой оставить в DAO, что упростит тестирование (мок‑объекты).
- Добавить логирование операции и запись в аудиторскую таблицу.
Можно ли обойтись без этой функции? Если в системе уже реализован общий механизм финансовых операций (например, сервис платежей), то данную функцию следует удалить и использовать централизованный API, где уже реализованы все перечисленные проверки и транзакционность.