关键词:系统架构、系统框架、软件开发、插件式、模块化、数据交换系统、条件系统、条件表达式、公式表达式、golang、delphi、c++。
目录
一、前言
二、框架结构图
三、数据交换系统
四、生产-消费模型
五、公式表达式
六、条件表达式
七、数据表达式
八、后话
九、参考链接
前面两篇介绍了插件式模块化软件框架的思想,本文主要介绍软件开发中用于独立模块之间进行信息交换的数据交换系统、条件系统和公式系统组成的数据平台,以及介绍基于此数据平台的“生产-消费”模型。
本文以航司系统举例是以“说明”为目的,并非真实业务需求,不用较真逻辑紧密性。
关于模块化设计思想、生产-消费模型、条件系统、公式系统等相关知识参阅文末链接。
图一 框架结构图
数据平台由数据交换系统、条件系统和公式系统构成,业务模块使用数据平台提供的数据生产者和数据消费者对象实例,业务模块可以既是数据消费者又是数据生产者。
每个消费者模块拥有一个独立的数据消费者对象实例,依据业务逻辑动态管理自己模块的订阅条件(订阅和取消),也可以调用接口主动获取数据值和检查条件是否成立。
每个生产者模块拥有一个独立的数据生产者对象实例,依据业务逻辑动态管理自己模块的数据信息(生产和清除)。
数据交换系统就像PC的数据总线,提供数据的设置和获取功能。软件模块就像PC的硬件插件一样“彼此独立而又有机结合”。 一般的用户系统,用户信息和用户行为可以用Key-Value关系来表示。
数据生命周期有多种:运行时、终身、每月等。
数据形态有两种:一种是内存变量值,另一种是函数返回值。
数据所有者有两种:数据平台和业务模块,两者各自负责维护数据的生命周期。运行时业务模块根据数据ID向数据平台提交数据,或者提供数据取值回调函数,即生产数据。以此实现公共数据交换。
以航司客户系统为例,数据平台的“数据ID表”定义如图二所示(部分数据是“依据条件”从其他数据中提炼的,任何数据变化都会触发“数据事件”):
图二 数据ID表
一般的用户系统,用户行为可以使用“生产-消费”模型来解决,如图三所示:
图三 生产-消费模型
消费的数据资源包含:实物数据(如现金、充值额度、物品等)和非实物数据(剩余里程、积分等),如乘客购票时需要消耗现金、里程、积分,或组合消耗。
生产的数据资源包含:实物数据和非实物数据,数据生产也分一次性生产和运行时生产,一般实物数据或奖励性数据为一次性生产。
如图四,一个VIP乘客给一家三口买头等舱机票,当天登机起飞后,票务模块生产数据待增里程=3000,送(生产数据)积分30000和蛋糕3份(食毕),中途故障返航,飞控模块不计总里程。次日再登机,蛋糕和积分数据不再赠送(生产),票务模块重新计算待增里程=3000,飞机落地后飞控模块给总里程增加3000公里并将待增里程置0。
图四 条件表达式和数据表达式表
公式符号:=、+、-、*、/、FuncName、()、mod、div ,即赋值、加、减、乘、除、函数名、括号、求余、整除。
公式表达式(可以用在条件表达式和数据表达式中)举例:
FormulaExpr="总消费*1.5+总里程*1.2-已用积分"
消费者模块可以向数据交换系统直接消费数据,也可以通过条件系统间接消费数据。直接消费数据的获取接口比较简单,就不再详述。用户数据越齐全,条件系统的功能就越强大。
条件逻辑运算符号:and、or 、()。
条件比较运输符号:=、<、>、!=、<=、>=
条件表达式举例(比较符号左右可以式公式):
CondExpr="(性别=男)and(总里程>=100000)and(总消费>5000)"
CondExpr="(总消费*1.5+总里程*1.2-已用积分)>10000"
CondExpr="(总消费*1.5+总里程*1.2)>(总积分-已用积分)"
条件解析:
Conds = DataConsumer.Parse(CondExpr)
或主动检查条件是否成立:
DataConsumer.Check(Conds)
或监听条件成立后触发回调:
DataConsumer.Listen(Conds, OnCondEstablish)
生产者模块可以向数据平台直接提交(生产)数据,也可以向数据平台提供数据的取值回调函数(间接生产)。
数据运输符号:+、-、*、/、=,即加、减、乘、除、赋值
数据表达式举例(多个数据表达式用逗号分隔,运算符右边可以是公式):
DataExpr="登录次数+1,积分+10"
DataExpr="登录次数+1,月活跃度+1,积分=积分+月活跃度*10"
DataExpr="随机奖品ID=Random((剩余积分+剩余里程) / 100)"
数据解析、生产:
Datas = DataProducer.Parse(DataExpr)
DataProducer.Clear()
DataProducer.Make(Datas)
有了统一接口的“数据平台”,模块的独立就越高,随之而来的模块开发效率、代码可靠性、可移植性、可移除性就越高,即可实现流水线式的开发生产。
另外,运用“生产-消费”模式来解释和执行用户行为,结合“条件表达式和数据表达式配置表”(图四)和“数据ID表”(图二),更多业务逻辑的编码工作可转化为用配置实现,极大的提升模块的开发工作。
理论尚且清晰明了,一个系统运用成功,另一个系统要能运用自如也绝非易事,细节之处尚需深思权衡。
最后还是用前面系列文章所说的话结束:有些功能虽然不是万能的,但是按82法则,它能解决80%的问题就足够了。
关于模块化思想参阅或其它:
插件式模块化软件框架的思想图解一(框架篇)https://blog.csdn.net/guestcode/article/details/119701789插件式模块化软件框架的思想图解二(案例篇)https://blog.csdn.net/guestcode/article/details/119981524关于生产-消费模型参阅或其它:
生产者消费者模式-Java实现https://www.cnblogs.com/chentingk/p/6497107.html关于条件系统参阅或其它:
Go 表达式求值器https://blog.csdn.net/weixin_34409703/article/details/92112762关于公式系统参阅或其它:
golang实现的公式引擎https://studygolang.com/articles/24125?fr=sidebar