我是如何在5 天内,完成 60 个类的核心模块的重构 (3)

可以看到,UI 过度暴露了“处理 UI 逻辑所依赖的过程 API”,并在业务中直接干预了 UI 逻辑,这是典型的 MVP 写法,这造成了耦合。一旦 UI 的需求有变动,View 和 Presenter 的编写者都会受到牵连。

而且,职责过多造成了依赖过多,这个 Presenter 会因为过多的依赖,而越写越臃肿:受“破窗效应”的驱使,别的码农会因为此处已经有某个依赖,而不假思索的接着往下写。

到底怎样才算解耦

所谓解耦,是符合工程设计、符合设计模式原则的编码。

解耦的本质,我只说一遍:

职责边界明确,职责边界明确,职责边界明确。

viabus_flow_flow.png


符合单一职责原则:
UI 的职责仅限于“展示”,也就是发送请求、处理 UI 逻辑。业务的职责仅限于“提供数据”,也就是接收请求、处理业务逻辑、响应结果数据。

符合依赖倒置原则、最小知识原则:
UI 不需要知道数据是经过怎样的周转得来的,它只需发送请求,并在拿到结果数据后,自己内部消化 UI 逻辑。业务只需处理数据并响应数据给 UI,它不需要知道 UI 会怎样使用数据,更无权干预。

综上,无论是 UI 还是业务,都不应过度暴露内部逻辑 API 而受控于人,它们应只暴露请求 API,来响应外部的请求。过程逻辑应只在自己内部独立消化。

public class XXXListBusinessProxy extends BaseBusiness<XXXBus> implements IXXXListFragmentRequest { @Override public void multiAddOrRemove(final XXXListDTO dto) { handleRequest((e) -> { ... if (TextUtils.isEmpty(existBsms)) { sendMessage(e, new Result(XXXDataResultCode.XXX_LIST_FRAGMENT_MULTI_ADD_OR_REMOVE, false)); } else { wyhcJgDBManager.insertAllTaskOfMine(existBsms, layersConfig); sendMessage(e, new Result(XXXDataResultCode.XXX_LIST_FRAGMENT_MULTI_ADD_OR_REMOVE, true)); } return null; }); } @Override public void refreshPatternOfXXXList(final XXXListDTO dto) { handleRequest((e) -> { ... count.setMyXXXCount(wyhcJgDBManager.getMyXXXPatternCount()); return new Result(XXXDataResultCode.XXX_LIST_FRAGMENT_REFRESH_COUNT, count); }); } @Override public void changeXXXPatternOfMine(final XXXListDTO dto) { handleRequest((e) -> { if (toMine) { ... } else { ... sendMessage(e, new Result(XXXDataResultCode.XXX_LIST_FRAGMENT_GET_ALL_PATTERN_OF_MINE, count)); } return null; }); } } public class XXXListFragment extends BaseFragment implements IResponse { XXXBus.XXX().queryList(mDto); XXXBus.XXX().multiAddOrRemove(mDto); XXXBus.XXX().queryPattern(mDto); ... @Override public void onResult(Result testResult) { String code = (String) testResult.getResultCode(); switch (code) { case XXXDataResultCode.XXX_LIST_FRAGMENT_REFRESH_LIST: updateRecyclerView((List<Wyhcrw>) testResult.getResultObject()); if (isNeedUpdateCount()) { ... } else { finishLoading(); } break; case XXXDataResultCode.XXX_LIST_FRAGMENT_MULTI_ADD_OR_REMOVE: if ((boolean) testResult.getResultObject()) { loadData(true, true); } else { ToastUtils.showShort(getContext(), "操作失败"); } dismissProgressDialog(); break; case XXXDataResultCode.XXX_LIST_FRAGMENT_REFRESH_PATTERN: ... break; default: } } }

解耦有什么好处?

解耦的好处,福特最有话语权。

100 多年前,福特发明了世界上第一条流水线,让工人职责边界明确,从而得以分工和专注各自领域。

原先装配一辆车需 700 小时,通过流水线分工后,平均一辆 12.5 小时,这使得生产效率提升了近 60 倍!

#18c2f9f560ffe27f03218a2a4beba0fb#


软件工程同理。

由于 UI 和业务职责边界明确,且相互通过接口通信,使得 UI 和业务的编写者能够真正的分工。

写 UI 的人,不会被业务的编写打断,他可以一气呵成的写自己的 UI。写业务的人,同样不会被打断,他可以专注于业务逻辑、数据结构和算法的优化。

写 UI 和写业务的人,都可以自己实现接口,去独立的完成单元测试,完全不必依赖和等候对方的实现。

最后,在职责边界明确的情况下,UI 就算写 100 个 UI 逻辑,那也是 UI,业务就算写 100 个业务,那也是业务,纯种,所以不会杂乱,何况我们还可以借助“接口隔离原则”继续往下分工!

总结

综上,本文介绍了两个重构思路:

1.顺应开闭原则,对定制化功能进行抽象。

2.顺应单一职责、最小知识、依赖倒置原则,让职责边界明确,防止代码耦合。

看完这篇文章,如你觉得有所收获和启发,请不吝点赞,你的点赞就是对我最大的支持!

本次项目重构用到的,符合设计模式原则的 viabus 架构,已在 GitHub 开源:
GitHub:KunMinX/android-viabus-architecture

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwfyf.html