В современной Android-разработке большинство проектов являются многомодульными. По сути, разработчики создают более мелкие части, а затем объединяют их для достижения требований проекта. Кроме того, как указано в документации Android, существует несколько типов модулей, которые можно использовать в проекте, например, функциональные модули, модули данных, общие модули и т. д.

По характеру этой структуры разные модули имеют разные зависимости и требования. Некоторые модули, как правило, больше зависят от платформы Android, в то время как другие более независимы. И мы хотим, чтобы наши модули были как можно более независимыми, чтобы максимизировать возможность их повторного использования. Например, модули домена — это обычно то место, где мы размещаем нашу бизнес-логику, и желательно, чтобы они были как можно более чистыми. Лично я предпочитаю, чтобы мои доменные модули были чистыми и независимыми, чтобы я мог использовать их в разных проектах без каких-либо изменений.

Мне, наверное, не нужно упоминать, что логирование — очень важная часть процесса разработки. Это очень полезный инструмент для отладки и мониторинга приложения. Но когда мы используем многомодульную структуру, пытаясь при этом сохранить наши модули независимыми, мы сталкиваемся с некоторыми проблемами. Один из них — ведение журнала. Конечно, мы можем использовать нашего старого знакомого `System.out.println()`, но это не очень хорошая практика. Мы также можем использовать класс Android Log, но это не очень хорошая практика.

Использование класса Android Log в наших модулях предметной области сделает их зависимыми от платформы Android. Помимо этого, не все проекты используют Logcat непосредственно для ведения журнала; некоторые могут использовать другие инструменты, такие как Timber, Crashlytics и т. д. Таким образом, использование инструмента прямого ведения журнала проекта в наших доменных модулях снижает возможность повторного использования модулей.

Так что мы можем сделать? Просто: мы можем использовать силу абстракции. Мы можем определить интерфейс для нашего проекта, а затем делегировать все детали ведения журнала проекту. Таким образом, наши доменные модули будут независимыми и чистыми. И мы можем использовать одни и те же модули домена в разных проектах без каких-либо изменений. Давайте посмотрим, как мы можем это сделать.

Сначала мы хотим определить интерфейс для нашего ведения журнала, аналогичный классу Android Log. Мы можем определить его в нашем модуле домена.

Затем мы можем реализовать этот интерфейс в нашем модуле приложения.

class LogcatLogger: Logger {
    override fun d(tag: String, msg: String) {
        Log.d(tag, msg)
    }

    override fun e(tag: String, msg: String, throwable: Throwable?) {
        Log.e(tag, msg, throwable)
    }

    override fun i(tag: String, msg: String) {
        Log.i(tag, msg)
    }

    override fun w(tag: String, msg: String) {
        Log.w(tag, msg)
    }
}

Но нам не нужно реализовывать это с помощью logcat. Мы можем использовать любой инструмент ведения журнала, какой захотим. Например, мы можем использовать Timber.

class AppLogger : Logger {
    override fun d(tag: String, msg: String) {
        Timber.tag(tag).d(msg)
    }

    override fun e(tag: String, msg: String, throwable: Throwable?) {
        Timber.tag(tag).e(throwable, msg)
    }

    override fun i(tag: String, msg: String) {
        Timber.tag(tag).i(msg)
    }

    override fun w(tag: String, msg: String) {
        Timber.tag(tag).w(msg)
    }
}

Затем мы можем использовать этот интерфейс в нашем модуле домена.

class UseCase(private val logger: Logger) {
    fun doSomething() {
        logger.d("UseCase", "doSomething")
    }
}

И мы можем обеспечить реализацию этого интерфейса в нашем модуле приложения с помощью Hilt.

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Provides
    fun provideLogger(): Logger {
        return AppLogger()
    }
}

И теперь у нас есть более независимый модуль домена. Мы можем использовать этот доменный модуль в разных проектах без каких-либо модификаций для ведения журнала. Мы можем использовать любой инструмент ведения журнала, который мы хотим в нашем проекте. Мы можем использовать Logcat, мы можем использовать Timber, мы можем использовать Crashlytics и т. д. Мы даже можем использовать разные инструменты ведения журнала в разных модулях.

Дайте мне знать, что вы думаете об этом подходе. Спасибо за прочтение.

ЛинкедИн

Всех вас люблю.

Будьте в курсе новых блогов.

Будьте осторожны.