当前的问题
- 不能单独复用业务层
- 业务Model定义不清晰,或者很难找到
- Repository定义为ViewModel的数据提供者,其中包含持久层+业务层,功能庞大,职责不明确
- UI层直接调用Repository,功能需求改变时会违反开闭原则
- UI层的Utils和Service层的Utils没有区分开
- Manager,Helper,Utils命名不统一
- 数据驱动界面更新编程方式不是银弹
组件化和模块化理解
组件化
从使用方式来说,就是直接复用成品的Activity交互页面。在集成了组件化产品的不同app中,组件模块的交互页面是完全相同的。(类似于webView加载网页,不管哪个webView加载相同url看到的结果都是一样的)
组件化是由产品决定要不要做的,是从产品层面设计的一个产品需求。
模块化
模块化就是写好代码,遵循面对对象编码的六大原则。
模块化是开发内部决定的技术手段。
所以如果产品没有组件化需求,就不要做组件化。源头不对,再怎么尝试做组件化,都不可能做的好。都只是在过度设计。
不忘初衷:做好代码复用
哪些代码可以复用?
UI层
产品没有做组件化的需求,所以UI层只复用自定义View,以UIComponent的方式提供复用业务层全部复用,创建Domain代表业务层,Domain内部角色:
- Model: 业务模型
- Repository: 针对数据模型的增删改查
- Service: 针对业务数据的整理等操作
- UseCase: 通过repository和service实现针对应用页面的数据接口,也是domain层对外的统一接口
业务模块架构
UseCase:
UseCase中通过Repository获取业务Model,再通过Service将业务Model整理为页面需要的DTO
ViewModel:
通过一个对象完整的了解整个业务具有哪些数据
daoBean, apiBean需要考虑序列化存储,数据会不全,也不易理解
Model由具有唯一标示的实体(Entity)和值对象(Value Object)构成
Repository:
提供针对业务Model的增删改查接口
优点:
- UI只复用UIComponent
- 定义业务Model,通过Model,Repository,Service就能大概了业务功能
- 代码层次结构,职责更加清晰,易维护
- 业务层和UI层的分离,抽离了与界面无关的抽象业务层,可单独复用
- 添加了业务层的访问接口UseCase,解决了需求变更时遵循开闭原则
单元测试实践
- webApi, deviceApi,Dao,Service,Utils 一般没有其他依赖,可以单元测试(unit test)
- Repository会依赖webApi,deviceApi,Dao等,需要mock它们的实现进行测试(double test)
- 使用robolectric让java test里面也可以依赖Android sdk 的api
Coroutines实践
- webApi, deviceApi, Dao, Service, repository, UseCase这些都只提供的main-safe的suspend方法