简体   繁体   中英

Why does Google recommend using classes acting as functions for use cases?

Introduction

Semantically speaking, classes and interfaces act as nouns and methods/functions act as verbs . This is something that I recently read in the Java to Kotlin and it is aligned with how the vast majority of the people naturally name methods and classes.

For example we would expect a Car class to have a getBrand method, not a GetBrand class with an invoke method returning the brand of the car.

However, while reading the recent Guide to app architecture from Google, I have came across their naming convention for use cases , where they suggest this naming:

verb in present tense + noun/what (optional) + UseCase

with the following syntax to use it in Kotlin (example from here ):

class FormatDateUseCase(userRepository: UserRepository) {

    private val formatter = SimpleDateFormat(
        userRepository.getPreferredDateFormat(),
        userRepository.getPreferredLocale()
    )

    operator fun invoke(date: Date): String {
        return formatter.format(date)
    }
}

Question

Looking at the code above, we just have a class acting as a function. Why does Google recommend using these classes instead os just using top-level functions? Am I missing something here?

Your statement is not completely correct: We don't "have a class acting as a function", but you can say that each instance of the class acts as a function. That is important, since for instance, the constructor of FormatDataUseCase has a parameter of type UserRepository .

So, if we wanted to convert the FormatDataUseCase into a top-level function, it would not have the same signature as the invoke function of FormatDataUseCase , but it should also have userRepository as an additional parameter:

fun formatDateUseCase(userRepository: UserRepository, date: Date): String {
        val formatter = SimpleDateFormat(
            userRepository.getPreferredDateFormat(),
            userRepository.getPreferredLocale()
        )
        return formatter.format(date)
    }

And that is probably the main advantage of the recommended approach: You can have often-needed parameters and values automatically injected when you inject the use case class. This hides the dependencies from the caller of the use case, and makes it more comfortable to use.

Also, in the example the SimpleDateFormat is just initialized once and then reused for every call of the function, but if we converted it to a function, we would need to create a new instance on each call.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM