Новое Распределяем каналы MAX по категориям и территориям. Читать новость

🔮 Убийца бойлерплейта: Встречайте Context Parameters (Kotlin 2.x)



Мы так привыкли к Dependency Injection (Dagger/Hilt/Koin), что перестали замечать, как он раздувает наш код.
Сценарий из жизни: вам нужно залогировать событие глубоко в слое бизнес-логики. Вы берете интерфейс Logger и прокидываете его через конструкторы пяти промежуточных классов, хотя он нужен только в одном методе на самом дне.

В Kotlin 2.1+ (KEEP-367) активно допиливают киллер-фичу, которая меняет правила игры - Context Parameters.

Историческая справка: Если вы помните экспериментальные Context Receivers (синтаксис context(Logger)), забудьте их. JetBrains официально задепрекейтили их в версии 2.0.20, заменив на более строгие и читаемые Context Parameters.

Как это выглядит теперь?

Допустим, у нас есть TransactionScope и Logger. Мы не хотим инжектить их в классы-прослойки, мы хотим потребовать их наличие в функции неявно.

// Новая магия: context(...) перед функцией с явными именами переменных
context(logger: Logger, tx: TransactionScope)
fun deleteUser(userId: String) {
logger.log("Deleting user $userId")

tx.execute {
// ... логика удаления в БД
}
}

В чем отличие от обычных параметров?
При вызове функции deleteUser вам не нужно передавать эти параметры руками! Компилятор сам найдет их в текущем скоупе (scope) и подставит под капотом.

class UserUseCase(
private val logger: Logger,
private val tx: TransactionScope
) {
fun execute() {
// Вводим зависимости в область видимости
with(logger) {
with(tx) {
// Вызываем функцию БЕЗ передачи логгера и транзакции!
// Компилятор сам слинкует их из контекста.
deleteUser("user_123")
}
}
}
}

(На практике вы настроите скоуп один раз на самом верхнем уровне — например, в базовой ViewModel или HTTP-хендлере Ktor — и вся вложенная цепочка вызовов получит к ним доступ).

Почему это круто для архитектуры?

1. Чистые сигнатуры: Бизнес-функции принимают только бизнес-аргументы (например, userId: String). Вся техническая инфраструктура (логирование, аналитика, права доступа, транзакции) выносится за скобки.
2. Читаемость (в отличие от старых Receivers): Раньше методы из контекста вызывались неявно (просто log()), и в большом классе было невозможно понять, откуда пришел этот метод. Теперь у нас есть жесткое имя: logger.log().
3. Идеально для Cross-cutting concerns: Это элегантное решение для сквозного функционала, который не должен загрязнять доменную модель.

⚠️ Правило Сеньора:
Context Parameters - это не замена конструкторному DI.
Если классу нужен UserRepository для выполнения всех его основных задач, передавайте его в конструктор. Используйте context(...) только для тех сущностей, которые меняются в зависимости от среды выполнения (call chain), или для утилитарных инструментов (например, AnalyticsScope).
Просмотры: 76
Открыть в MAX Сообщить о неточности

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти