从Kotlin的干净架构定义用例的惯用方式

时间:2018-10-16 04:49:24

标签: android kotlin kotlinx.coroutines clean-architecture

我尝试将用例类从Java切换到Kotlin,从Rxjava切换到协程。

这是我的GetTopSongs班。

class GetTopSongs {

    suspend fun execute(limit:Int):Either<List<Song>>{
        //... do stuff
    }
}

我想知道在Kotlin中是否有比getTopSongs.execute(10)更好的方法?

3 个答案:

答案 0 :(得分:3)

使用operator overloading

class GetTopSongs {

    suspend operator fun invoke(limit:Int):Either<List<Song>>{
        //... do stuff
    }
}

因此您可以忽略额外的.execute呼叫:

val getTopSongs = GetTopSongs()
val result = getTopSongs(10)

答案 1 :(得分:1)

首先要注意的是Either是您在仅FP的API(例如RxJava)中需要的拐杖。在某种程度上,将mapskipUntil之类的运算符链接在一起可以得到不错的代码,但是您必须学习大量的运算符,并且在某些情况下您还需要其他内容。

Kotlin协程的最大好处是,您可以继续使用普通的旧式命令式编程样式,以及包括try-catch在内的控制流语句的全部功能。因此,我建议使用以下签名:

class GetTopSongs {
    suspend operator fun invoke(limit:Int): List<Song> {
       val result = ...
       if (someProblem) throw MyException("problem description")
       else return result
    }
}

回到命令式样式的较不明显的好处之一是,您不会遇到那些长达整页的类型推断错误。

答案 2 :(得分:0)

如果要使用Kotlin 1.3,则可以使用“可调用的暂停函数引用”。您可以为ViewModel构造函数提供函数类型:

class MyViewModel(val usecase: suspend (Int) -> List<Int>) {
    suspend fun doIt() {
        println(usecase(5))
    }
}

您的用例可以分为一个或多个类:

class MyUsecasses(val myRepo: MyRepo) {
    suspend fun usecase1(para: Int): List<Int> = myRepo...
    suspend fun usecase2(para: String): List<String> = myRepo...
}

创建ViewModel时,请提供功能参考:

val usecases = MyUsecasses(repo)
val viewmodel = MyViewModel(usecases::usecase1)

如果您不喜欢ViewModel构造函数中的函数类型,则可以使用typealias:

typealias Usecase1 = suspend (Int) -> List<Int>
class MyViewModel(val usecase: Usecase1)