怎么, UseCase我必须得用吗?

社区移动开发Android
UseCase我必须得用吗? Android 开发人员须知

picture.image

简介

如果你已经在 Android 开发领域工作了一段时间, 你可能听说过UseCase. 它们通常被视为"简洁架构"的圣杯. UseCase承诺将业务逻辑从表现层和数据层中分离出来, 使代码更加模块化, 可重用和可测试. 但问题就在这里: UseCase并不总能解决问题.

事实上, 盲目应用UseCase可能会导致代码臃肿和不必要的复杂性, 而这正是简洁架构所要避免的. 在本文中, 我们将打破围绕UseCase的神话, 讨论UseCase何时必不可少, 何时只是浪费时间. 如果你是一名 Android 开发人员, 想知道遵循这种模式是否弊大于利, 那么这篇文章就是为你准备的.

picture.image

关于UseCase的争议性真相

从理论上讲, UseCase 在简洁的架构设置中是完全合理的: 它们封装了业务逻辑, 并确保应用各层保持解耦. 然而, 在日常应用开发中, 实际情况要细微得多.

太多的开发人员将 UseCase 视为一种需求, 从而导致冗余和不必要的代码. 结果呢?他们不但没有提高应用的可维护性和可扩展性, 反而创建了臃肿的代码库, 其中充满了没有实际用途的抽象层.

picture.image

当你应该避免使用UseCase时: 保持简单

我们先来看看什么情况下应该避免使用UseCase. 许多开发人员犯的最大错误就是在应用中的每一个小操作中都使用 UseCase, 即使不涉及重要的业务逻辑.

示例: 从远程仓库获取数据

想象一下, 你正在构建一个简单的待办事项应用, 需要从本地数据库中获取任务列表. 操作很简单:查询存储库, 获取列表并将其显示在用户界面上.

在这里使用 UseCase 只会增加不必要的复杂性. 你没有任何复杂的业务逻辑需要隔离或在应用的不同部分重复使用. ViewModel 可以直接调用资源库, 而无需使用 UseCase.

class TaskViewModel(private val repository: TaskRepository) : ViewModel() {
    val tasks = liveData {
        val taskList = repository.getTasks()
        emit(taskList)
    }
}

为什么这里要避免使用 UseCase?因为它不会增加价值. 逻辑已经很简单了, 引入一个 UseCase 只会使代码变得臃肿, 而没有任何明显的好处. 简洁架构提倡简单明了, 而在这里, UseCase 的作用恰恰相反.

picture.image

当有必要使用 UseCase 时: 处理复杂的业务逻辑

现在, 让我们来谈谈什么情况下UseCase实际上是必要的. 当你需要封装需要与用户界面和数据层解耦的**复杂业务逻辑时, UseCase就会大显身手.

示例: 在旅行应用中预订航班

考虑用户在旅行应用中预订航班的场景. 这个过程涉及多个步骤:

  1. 验证用户输入(日期, 目的地).
  2. 检查航班可用性.
  3. 预订航班
  4. 处理付款.
  5. 发送预订确认.

在这里, 你需要处理不同服务之间的多次交互--航班可用性, 预订和付款--其中每次交互都可能失败或需要特定的错误处理.

在这种情况下使用UseCase是非常合理的. 通过在 UseCase 中封装预订流程, 你可以

  • 确保遵循所有业务规则.
  • 在应用的不同部分重复使用逻辑(例如, 通过不同的UI进行预订).
  • 更容易独立于UI和数据层测试预订逻辑.
class BookFlightUseCase(
    private val flightRepository: FlightRepository,
    private val paymentProcessor: PaymentProcessor
) {
    suspend operator fun invoke(flightId: String, userDetails: User, paymentInfo: PaymentInfo): BookingResult {
        if (!validateInput(userDetails)) throw InvalidInputException()
        val availability = flightRepository.checkAvailability(flightId)
        if (!availability) throw FlightNotAvailableException()

        val reservation = flightRepository.reserveFlight(flightId, userDetails)
        val paymentResult = paymentProcessor.processPayment(paymentInfo)

        return BookingResult.Success(reservation, paymentResult)
    }
}

在本例中, UseCase 改进了代码组织, 可测试性和可重用性. 如果没有 UseCase, 这些逻辑很可能会被放在 ViewModel 或 Activity 中, 从而增加了维护, 测试和重用的难度.

picture.image

使用案例的真正目的: 避免臃肿, 而非创建臃肿

简洁架构的目的不是为了创建更多的抽象层而创建抽象层, 而是为了保持代码库的简洁, 有序和易于维护. 在没有必要的地方引入UseCase, 就违反了这一原则.

这就是许多开发人员犯错的地方: 他们遵循UseCase这样的模式, 因为他们被告知这是"简洁架构"的一部分, 却没有充分理解为什么要使用它. 结果, 他们的代码变得杂乱无章, UseCase 起不到任何实际作用, 使"简洁架构"变成了"简洁架构"所要防止的东西--臃肿且难以维护的代码.

picture.image

总结一下: UseCase是工具, 不是规则

关键的启示是:UseCase是工具, 而不是规则: 过度使用UseCase, 尤其是在没有复杂业务逻辑的情况下, 会导致不必要的抽象臃肿的代码.

在决定是否实施UseCase时, 请扪心自问:

  • 是否存在需要与表现层分离的业务逻辑?
  • 这些逻辑是否会在应用的其他地方重复使用?
  • 是否需要对这些逻辑进行独立测试?

如果这些问题的答案都是否定的, 那么就跳过 UseCase, 让代码保持简单. 如果答案是肯定的, 那么 UseCase 将帮助你实现更简洁, 更易维护的代码库.

明智地使用UseCase, 你就会走上编写简洁, 高效的 Android 代码的正确道路.

今天的内容就分享到这里啦!

一家之言, 欢迎斧正!

Happy Coding! Stay GOLDEN!

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论