达达商城和众包任务是公司的两个变现业务,商城是做定位蓝领的电商,众包则是做除了物流之外的众包模式的尝试。 两个项目在开发上共同的难点都是系统如何应对灵活多变的业务形式,来支持新模式的落地。 对此我们设计了一套插件系统,很好的处理了系统的复杂性,让开发变的轻松简单。
起因和思路:
达达商城里有多种类型的商品,每种商品有不同的展示,定价,发货,库存管理,退款逻辑。在项目开发半年后,代码逻辑繁杂混乱,难以维护。在2016年的十一,我们实施了一次重构,思路为:
商品购买流程是不变的,明确每个流程节点的触发方法。
流程节点上业务的逻辑是灵活多变的,受到前端框架react组件化的启发,用插件的形式拆分隔离,对不同的商品做插件配置。
商品可以在后台绑定和修改插件,及调整插件参数。
结构图
商品,节点和插件:
每一个商品会绑定多个插件,每个商品可动态的添加删除插件:
用户购买任何类型商品,都会经历如下图的各个节点。 当某个节点被触发时,系统会检测购买的商品有哪些插件,并按顺序执行绑定插件在该节点的代码逻辑。
插件的灵活性和可读性:
插件的参数是可以实时配置的,可以针对商品的需求,调整插件参数。
插件的流程所执行的逻辑可以直接在后台看到,方便理清该商品的购买流程细节,无需再写文档。
编写一个插件:
接到新需求,你要做的只是编写一个插件文件。系统通过反射的方式,自动获取到路径里的新的插件,展示在后台界面上。后台配置后,插件即可生效
插件基础属性:
属性 说明
plugin_id 插件id
plugin_name 插件展示名称
category 插件分类
priority 插件的执行顺序
desc 插件在不同节点的逻辑描述插件配置参数Props:
继承Props Class,定义了该参数的属性,默认值等。Props是可以在后台配置的,实时生效。
节点方法:
节点的业务代码都写在节点方法中。 当一个节点被触发,绑定的插件上的节点方法就会按priority的顺序依次执行。 节点方法会输入该插件的配置参数Props,API传入的参数Form,和贯穿不同插件的参数Data。 每个插件执行结束后也会返回标准的Output Class,来处理一些异常情况。
使用现状:
当前达达商城已经使用了一年,运行良好,每次有新业务就用插件的形式增量添加,几乎没有再次重构的需要。
众包任务业务的结算系统也已使用插件系统来处理不同项目复杂的结算逻辑。接入整套插件系统及后台配置功能只花了半天的工作量。
未来发展: 自动化测试:
针对插件的自动化测试比单元测试更加贴近业务,比集成测试更加细粒度。插件系统对逻辑的细粒度分离和对input,output参数的把控,让自动化测试变得简单。后台界面可自动获取一个插件或一个业务所需要的所有input和所有预期的output参数,测试可以生成测例并定义input和预期的output。
开发流程优化:
业务的插件拆分产品也可以参与进来,界面的可读性让产品更能了解一个业务具体执行了哪些逻辑。在需求讨论时,产品和研发可以讨论出一个插件逻辑,在后台自动生成模板给研发,同时测试也可以开始根据此模版编写测例。
https://www.sohu.com/a/198019182_659464
什么是模块化,组件化, 插件化?
最近毕竟火的也就是组件化的应用了,可以大大加快项目的开发进度
单工程模式
移动开发诞生,我们开发移动项目,我相信大多用的是单工程单任务的开发模式,二话不说,直接就开始写起,是不是这样呢? new Project -> 分包 -> 写起。我相信都经历过,也写的比较爽,为什么呢? 这种模式不涉及乱七八糟的处理方式, 上手快,开发快,足够敏捷。那么原因是什么呢?Mobile Project 刚起步,项目都偏小,一些附加业务还没绑到App上。
模块化
Android Studio出来了,多出来了一个新的概念, Project, Module… 模块;当时以包的形式分离的公共包common,现在成了AS中的Module。大家都知道,Module包含两种格式: application, library。也就是说,一个Module就是一个小的项目,也是AS概念中的模块。因此我们开始设计common模块, common_business模块,甚至db模块。模块的好处是什么? 相比于包来讲,模块更灵活,耦合更低,随意插拔,想引入哪个就引入哪个。根据不同的关注点,将一个项目的可以共享的部分抽取出来,形成独立的Module,就是模块化。模块化不只包含公共部分,当然也可以是业务模块。
组件化
平时看看论坛,好多人都在问: 模块化和组件化有什么区别? 到底有什么区别呢,其实很小;但并不是完全相同的概念。 通过以上模块化的概念讲述,应该对模块化有了一个了解,那么区别是什么呢?
组件化是建立在模块化思想上的一次演进,一个变种。组件化本来就是模块化的概念。但是组件化的核心是
什么? 是模块角色的可转换性。是的,就是可转换性。
组件化的核心是角色的转换。 在打包时, 是library; 在调试时, 是application。
怎么理解组件化的概念 ?
Module的模式分两种, application和library。 library就是引用库,如你抽取的common。 application就是一个apk, 是一个完整的项目。
在调试时,我只关心我负责的模块,我希望我的模块是一个单独的app,因为这样更小,业务更专一,相对来讲修改与调试就会越省时省心,编译就会越快。试想当你需要改一段代码,既要关注自己的,也要关注别人的,是一种什么体验 ? 或者, 编译一个项目10M的代码和一个工程全部1G的代码,哪个比较舒服一些?
插件化
又有人问了: 插件化和组件化又有什么区别呢?插件化严格意义来讲,其实也算是模块化的观念。将一个完整的工程,按业务划分为不同的插件,都是分治法的一种体现。化整为零,相互配合。,越小的模块越容易维护。 插件化按理也算是模块化的一种体现,和组件化就不一个概念了。那么,到底有什么区别呢?
组件化的单位是组件(module)。
插件化的单位是apk(一个完整的应用)。
组件化实现的是解耦与加快编译, 隔离不需要关注的部分。
插件化实现的也是解耦与加快编译,同时实现热插拔也就是热更新。
组件化的灵活性在于按加载时机切换,分离出独立的业务组件,比如微信的朋友圈
插件化的灵活性在于是加载apk, 完全可以动态下载,动态更新,比组件化更灵活。
组件化能做的只是, 朋友圈已经有了,我想单独调试,维护,和别人不耦合。但是和整个项目还是有关联的。
插件化可以说朋友圈就是一个app, 我需要整合了,把它整合进微信这个大的app里面
其实从框架名称就可以看出: 组 和 插。
组本来就是一个系统,你把微信分为朋友圈,聊天, 通讯录按意义上划为独立模块,但并不是真正意义上的独立模块。
插本来就是不同的apk, 你把微信的朋友圈,聊天,通讯录单独做一个完全独立的app, 需要微信的时候插在一起,就是一个大型的app了。
插件化的加载是动态的,这点很重要,也是灵活的根源。
以上是对三个思想的解析,相信应该能明白不同的概念的具体意义和区别在哪了。在《关于移动架构的思考与总结》中我指出,所谓架构,无非两个方面: 分层和通信方式。 其实广义的架构也可以说是这两个方面:子模块(子系统)划分和通信。
子模块划分
除了大家公认的common部分, 业务模块的划分尤为重要,相比于狭义上的架构,广义上的子系统的划分的关注点,很考验技术经验以及对业务的理解。
通信方式
模块化的通信方式,无非是相互引入;我抽取了common, 其他模块使用自然要引入这个module
组件化的通信方式,按理说可以划分为多种,主流的是隐式和路由。隐式的存在使解耦与灵活大大降低,因此路由是主流
插件化的通信方式,不同插件本身就是不同的进程了。因此通信方式偏向于Binder机制类似的进程间通信
https://github.com/wangpengfei1992/ModularizedDemo