随着箭头1.1的到来.我们有了新的Effect班.

到目前为止,我的业务类返回的目的要么是模拟返回错误或值的效果,例如:

    @Service
    class CreateDepartmentUseCaseImpl(
        private val createDepartmentsDrivenPort: CreateDepartmentsDrivenPort,
        private val getDepartmentByCodeDrivenPort: GetDepartmentByCodeDrivenPort
    ) : CreateDepartmentUseCase {
        override suspend fun execute(param: Department): Either<DomainError, Department> =
            Either.conditionally(getDepartmentByCodeDrivenPort.get(param.code) == null,
                { DepartmentAlreadyExistsError(param.code.value) },
                { createDepartmentsDrivenPort.create(param) })

    }

有了新的Effect,它可以被重构为:

    @Service
    class CreateDepartmentUseCaseImpl(
        private val createDepartmentsDrivenPort: CreateDepartmentsDrivenPort,
        private val getDepartmentByCodeDrivenPort: GetDepartmentByCodeDrivenPort
    ) : CreateDepartmentUseCase {
        override suspend fun execute(param: Department): Effect<DomainError, Department> = effect {
            ensure(getDepartmentByCodeDrivenPort.get(param.code) == null) { DepartmentAlreadyExistsError(param.code.value) }
            createDepartmentsDrivenPort.create(param)
        }
    }

在模拟测试中,更改了:

    @Test
    fun `should create department`() = runTest {
        val dep = createValidDepartment()
        val createDepartmentRequest = CreateDepartmentRequest(dep.code.value, dep.name.value, dep.description.value)
        `when`(createDepartmentsUseCase.execute(dep)).thenReturn(dep.right())

    @Test
    fun `should create department`() = runTest {
        val dep: Department = createValidDepartment()
        val createDepartmentRequest = CreateDepartmentRequest(dep.code.value, dep.name.value, dep.description.value)
        `when`(createDepartmentsUseCase.execute(dep)).thenReturn(effect { dep })

问题是,对新的Effect级或Either级业务服务进行建模的最佳方法是什么,为什么?

推荐答案

如果Either适合你的用例,没有理由重构到Effect.

问题是,对我们的业务服务、新效果类或两者进行建模的最佳方法是什么?为什么?

遗憾的是,在软件领域,除了商业服务模型,通常没有适合所有人的答案,我推荐Either个.

这也是为什么我们可以将Effect分配给val,当返回Either时,我们需要将需要suspend fun的lambda挂起invoke.

val operation: Effect<E, A> =
  effect { ... }

suspend fun operation(): Either<E, A> =
  operation.toEither()

因此,如果您只需要对操作的result进行建模,那么需要使用Either<E, A>.如果需要传递lambda/操作,则可以使用Effect.

您可以将Effect视为比Either更低的级别实现,因为所有计算块(如either { }option { }ior { }result { }等)现在都是通过effect实现的.

这可以在either { }的箭头实现中看到.

suspend fun <E, A> either(block: suspend EffectScope<E>.() -> A): Either<E, A> =
  effect(block).toEither()

Kotlin相关问答推荐

Kotlin协程挂起继续线程

Kotlin异步不并行运行任务

T和T有什么区别:任何>

Kotlin接口方法默认值&;可传递依赖项

在 Kotlin 中,为什么在 `+` 之前但在 `.` 之前没有换行符?

Kotlin 插件之间的区别

如何使用 Either monad 并避免嵌套 flatMap

T except one class

具有多个不同类型来源的 LiveData

比较 Kotlin 中的可比对象列表

Kotlin Compose,在行中对齐元素

在用Kotlin编写的Android库公共API中处理R8+JvmStatic Annotation+Lambda

Kotlin中的测试无法访问受保护(protected)的方法

使用范围的稀疏sparse值列表

Java中lazy的Kotlin类似功能是什么?

Kotlin Android:属性委托必须有一个 'getValue(DashViewModel, KProperty*>)' 方法

Jetpack Compose 折叠工具栏

Kotlin内联属性的用例是什么?

Kotlin 错误:public function exposes its 'public/*package*/' return type argument

为什么在 Kotlin 中return可以返回一个return?